gcc and lccwin32:different result - windows

i try to compile this code:
#include <stdio.h>
void print(FILE *a)
{
int main();
int count=20;
int c;
int stop=0;
char answer;
while(!stop){
while((c=getc(a))!=EOF){
fprintf(stdout,"%c",c);
if(c=='\n'){
count--;
if(!count){
printf("do you want continue:y=for continue/q=for quit");
fflush(stdin);
answer=getchar();
if(answer=='y' || answer=='Y')
count=20;
else if(answer=='Q' || answer=='q'){
printf("you quit this program,press any key and hit the enter to close");
stop=1;
break;
}
else{
printf("argument is unacceptable,rolling back action");
main();
}
}
}
}
if(c==EOF)
stop=1;
}
}
void halt()/*do nothing just for halt and waiting for input*/
{
int a;
scanf("%d",&a);
}
int main()
{
FILE *in,*fopen();
char name1[25];
int a;
printf("enter the name of the file you want to show:");
scanf("%24s",name1);
in=fopen(name1,"r");
if(in==NULL){
printf("the files doesnt exist or it is in another directory, try to enter again\n");
main();
}
else
print(in);
fclose(in);
halt();
return 0;
}
the purpose of the program is to show 20 line content of a file. i compiled it in windows xp with lccwin32 and it works as expected. but problem arise when i change my os to linux (Ubuntu:pricise pangolin 12.04 LTS Desktop) and compile it with gcc.first it seems works fine but until the 20th line and prompt is out, when i put the argument (y for continue , q for quit)and hit the enter, but nothings happen. it just slipped away to elsepart which is starting again the program.so is it the gcc i have buggy or my code doesnt suit with gcc or may be i missed something?

I hate scanf. I would suggest replacing the scanf("%24s",name1) with fgets(s,24,stdin);
(And then unfortunately doing if (s[strlen(s)-1] == '\n') s[strlen(s)-1] = '\0' to get rid of the \n at the end.
I would also suggest:
Not use recursion on main
Use int main(int argc, char *argv[]) and then passing the name of your file as an argument (so you would check that argc > 1 and then use argv[1] as the filename, and then when running the program do ./programname filename)
Still not using scanf

In addition to the issues reported by #Foon you also have those problems :
fflush(stdin) is not working as you think it does.
scanf() leaves the newline character in the input buffer.
Your problem is that there is still a newline (\n) in the input buffer when you call getchar(), so your y/q answer is not even read.
Replacing fflush(stdin) with a solution from 1., or replacing fflush()+getchar() with scanf("\n%c",&answer); should solve that particular issue.

Related

I am trying to write a shell program to execute more than one command at a time

My Code
#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
char * arg_list[3];
arg_list[0] = "ls";
arg_list[1] = "-l";
arg_list[2] = 0;
char *arg_list2[3];
arg_list2[0] = " ps";
arg_list2[1] = "-ef";
arg_list2[2] = 0;
for(int i=0;i<5;i++){ // loop will run n times (n=5)
if(fork() == 0) {
if (i == 0){
execvp("ls", arg_list);
}else if(i==1){
execvp("ps" , arg_list2);
}else if(i>1){
printf("[son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
}
for(int i=0;i<5;i++) // loop will run n times (n=5)
wait(NULL);
}
ME trying to modify it
#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
for(int i=0;i<5;i++){ // loop will run n times (n=5)
if(fork() == 0) {
printf("[son] pid %d from [parent] pid %d\n",getpid(),getppid());
execlp(argv[i],argv[i],argv[i+1],(char*)NULL);
exit(0);
}
}
for(int i=0;i<5;i++) // loop will run n times (n=5)
wait(NULL);
}
-- NEED GUIDANCE AND UNDERSTANDING
I am trying to make my own tiny little shell program. When I run my first code works fine, runs all commands on the command line. But I cannot know and define all commands the user might enter. So i am trying to get a base code which could run any commands single or multiple entered by user. I tried using execlp where it does not compile saying argv is not defined which is true as i don't want to specifically define it.
I am trying to make my own tiny little shell program. When I run my first code works fine, runs all commands on the command line. But I cannot know and define all commands the user might enter.
For sure.... A shell program purpose is basically:
Read user input
Execute user input
Return result of execution.
There's nothing in your code that read user input....
So i am trying to get a base code which could run any commands single or multiple entered by user.
So read user input ;-)
I tried using execlp where it does not compile saying argv is not defined which is true as i don't want to specifically define it.
For sure ... but how would GCC guessed that `argv[]̀ must be automaticallty filled with user input ?
There's nothing automatic when coding in C language. You have to manage this manually.
Also, note that argc, argv et envp are usually reserved for main() function:
main(int argc, char **argv, char **envp)
So you may use something else to build your command array.
In pseudo code, what you must implement is:
quit=0
while (quit = 0) {
command_to_run = read_user_input();
if (command_to_run == "exit") {
quit = 1;
} else {
execute(command_to_run);
}
}
Some advices:
Try to use more functions. For example, implement a fork_and_run(char **cmd) function to fork and then execute command provided by the user. Il will make your code more readable and easy to maintain.
Read carefully manpages: everything you should know (like, for example, the fact that array provided to execvp() must be NULL-terminated) is written in it.
Your debugging messages should be printed to stderr. The result of the command run must be printed to stdin, so use fprintf() instead of printf() to write to the correct stream.
I would use a #define debug(x) fprintf(stderr, x) or something similar for debugging output so that you can easily disable later ;-)

I am having a problem passing arguments to execvp using sleep and fork

I asked a really terrible question last time so I will try and do better here. I have the following code:
int main(int argc, char* argv[])
{
int forkChild;
char* argList[] = {"10","20","30"};
forkChild = fork();
if(forkChild == 0)
{
execvp("sleep",argList);
exit(0);
}
else
{
wait(NULL);
}
}
I am having trouble getting the execvp line to work. It will not sleep at all. It seems that the trouble might be because the argList array is passing strings and not integers to execvp. If I plug an integer directly into sleep it seems to work fine.
Eventually my program should be able to pass any parameter to execvp, so I am not sure why there is a problem with argument types. Is there something to this that I am not seeing?
Thanks

Accepting and printing a string

Can we accept and print a string like this in c++?
This code is not working properly.
#include<iostream>
#include<string>
using namespace std;
main()
{
string a;char ch;
for(int i=0;i<5;i++)
{cin>>ch;
a[i]=ch;
}
a[5]='\0';
cout<<a;
}
I am able to print individual elements like a[1],a[2],etc but unable to print the entire string.Why?
If you want to take a string, you could do the following.
#include <iostream>
int main() {
std::string str;
std::getline(std::cin, str);
std::cout << str;
}
Also, C++ automatically null terminates any string literal you use.
Well it's not really anywhere near best-practices but to fix your immediate issue you need to actually resize the string.
#include<iostream>
#include<string>
main()
{
std::string a;char ch;
a.resize(5); // <--- reserves memory
for(int i=0;i<5;i++)
{
std::cin>>ch;
a[i]=ch;
}
a[5]='\0'; //<-- unnecessary
st::cout<<a;
}
alternatively you can append the characters
#include<iostream>
#include<string>
main()
{
std::string a;char ch;
for(int i=0;i<5;i++)
{
std::cin>>ch;
a+=ch;
}
std::cout<<a;
}
The real problem here is not that you can't read or can't print the string, is that you are writing to unallocated memory. operator[], which is what you are using when you do something like a[i]=ch, does not do any kind of boundary checking and thus you are causing undefined behavior. In my machine, nothing is printed, for instance.
In short, you need to make sure that you have space to write your characters. If you are certain that you are going to read 5 characters (and adding a \0 at the end, making it 6 in length), you could do something like this:
std::string a(6, '\0')
If you are uncertain of how many characters you are going to read, std::string is ready to allocate space as need, but you need to use std::push_back to give it a chance to do so. Your loop contents would be something like:
cin >> ch;
a.push_back(ch);
If you are uncertain where the std::string object is coming from (as in, this is library code that accepts a std::string as an argument, you could use at(i) (e.g, a.at(i) = ch instead of a[i] = ch), which throws an exception if it is out of range.
You can print the string like this
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a;char ch;
for(int i=0;i<5;i++)
{
cin>>ch;
a.push_back(ch);
}
a.push_back('\0');
cout << a;
return 0;
}

getch() returns \377! instead of reading character

I am using Xcode and using the C language trying to understand how to use the Getch function to start a project. I copied some code someone had written as an example that should work, however instead of the code waiting for me to enter a character, it returns one for me:
#include <midi_lib.h> <---------- this needs to be here for later
#include <curses.h>
int main() {
keypad(stdscr, TRUE); /* I dont know if this is needed*/
char c;
puts("Enter a character\n");
c = getch();
printf("You just typed a %c! \n", c);
getch();
}
This is the output:
Enter a character
You just typed a \377!
It works if i use Getchar(), but i dont want to have to press enter.
I'm really new to coding so it maybe something simple, but i have no idea....
LT
Well, you didn't even initialize the Ncurses library with initscr().
There really are a lot of things you are missing, so I recommend you to read the Ncurses howto that explains you everything from initializing (e.g. what that keypad(stdscr, true) is) to input and a lot more.
Here's an example that works:
#include <ncurses.h>
int main()
{
int ch;
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
ch = getch();
endwin();
printf("The key pressed is %d\n", ch);
}
Try this to get you started
#include <midi_lib.h> <---------- this needs to be here for later
#include <curses.h>
int main()
{
char c;
keypad(stdscr, TRUE); /* I dont know if this is needed*/
puts("Enter a character\n");
do {
c = getch();
} while (c == (char)-1);
printf("You just typed a %c! \n",c);
}
Note that getch() is constantly polling the keyboard for input, when there is
none, it will get -1 and retry until there is some in which case it will fall out of the while loop and continue.
This probably isn't how you should be coding this, but it does answer your question. The computer will act busy while it is constantly polling the keyboard.

REPL (Read–eval–print loop) with Mathlink (Wolfram Mathematica)

I'm new to Mathlink, and before integrating it in my code I tried to write a small REPL to get accustomed to it. The code is as follows (irrelevent parts omitted, and sorry for the horrible blend of C and C++):
int main(int argc,char **argv)
{
init_and_openlink(argc,argv);
while(!feof(stdin))
{
int pkt;
char buf[1024];
if(!fgets(buf,1024,stdin))
continue;
MLPutFunction(lp,"EnterTextPacket",1);
MLPutString(lp,buf);
MLEndPacket(lp);
while(((pkt=MLNextPacket(lp),pkt))&&(pkt!=RETURNPKT))
{
MLNewPacket(lp);
if(MLError(lp))
return 1;
}
const char *result;
MLGetString(lp,&result);
printf("%s\n",result);
MLReleaseString(lp,result);
}
return 0;
}
but it doesn't seem to work at all. I've tried replacing the while loop with a single MLNextPacket instruction but to no avail; I spent hours searching Mathlink documentation, but that one is a big mess! Where I'm doing it wrong?
The EnterTextPacket MathLink packet will make the kernel return the result wrapped in a ReturnTextPacket MathLink packet. Try changing the condition in your while loop to:
while(((pkt=MLNextPacket(lp),pkt))&&(pkt!=RETURNTEXTPKT))

Resources