First of all, I'm new to C so pardon me if asking too much.
I have a function that tokenize an input by the user so let's say
user input: test -f myFile
then after the tokenize function it becomes
abc[0] = test
abc[1] = -f
abc[2] = myFile
However, at the same time, I also need to use the return value from that input (test) statement whether it is FALSE or TRUE (file exist or not exist).
I did (MY PROBLEM)
if (*abc != '1') {
printf ("nope.");
}
in hope for telling me first whether that file is valid / exist or not, before I call some other function. However, it says warning comparison between pointer and integer.
My original plan is:
// ask the user for input
// tokenize the input
if (*abc != '1') { // check the return value from the input
printf ("nope.");
}
// call another function
Any input why MYPROBLEM doesn't work? How do I execute test after I tokenize?
If you want to check whether anything was added to abc, you would have to initialize your array to NULs prior to calling tokenize and then afterwards, if (**abc == '\0') would tell you that nothing was tokenized.
However, it's probably better for your tokenize function to return a flag that indicates success or failure in addition to populating your array.
As for executing test, you can use the system() function or one of the exec() functions.
Related
I am trying to simulate a shell terminal in c, one of the functionalities is to be provide a simple memory to remember the last command executed. So how I am going about is:
Every time the user enters a command (String) the string is saved in a file (command_histroy.txt)
If the user enters "r" (command=="r"), the terminal calls the function getSavedCommand(), as I am only saving only one command so my function is:
char* getSavedCommand(void){
char cmd[1000];
int i=0;
char* filename = "files/command_history.txt";
FILE* file = fopen(filename,"r");
if(file!=NULL){
int c;
do{
c = fgetc(file);
cmd[i]=c;
i++;
} while (c != EOF);
}else{
puts("Error Reading file");
}
return cmd;
}
So as in the file "command_history.txt", there is only one line stored, I reassumed that it would return this one line in an array of chars. To test I printed the results:
cmd = getSavedCommand();
printf("|%s|",cmd);
And the result I get is:
arj#arj-Inspiron-1545:~/projet$ ./a.out
|ls -l /home/arj
�|
arj#arj-Inspiron-1545:~/projet$
What I want is:
|ls -l /home/arj|
I think the EOF is creating the problem. Can someone help me?
One of the problem is you don't null terminate your array before returning. You need something like cmd[i] = '\0' at the end.
One more serious problem is you are returning a pointer to an object that is destroyed when the function returns. cmd object has automatic storage and is destroyed at the end of the function. Use malloc to allocate the array, or pass a pointer to the array as the argument of your getSavedFunction.
This functionality (plus command line edition, and a slew of other goodies) is the whole point of GNU readline (if on Linux, it is probably provided as a prebuilt package) or its BSD clone libedit (probably already available on BSD Unix).
I'm another CS beginner working on a simple Shell. At the moment I am trying to change the current directory if an argument is passed, else, report to the current directory.
I tried using chdir() in my program, but it's apparently not working. I tried passing a char* arguments which is tokenized. I also tried with argv[1], but I must be doing something wrong because neither seems to work.
Also, I'm not exactly sure how to make the argument pointer (containing the directory string) static, so that when i use putenv(ARGUMENT HERE) there are no issues.
Here is the pertaining part of my code:
else if (strncmp(command[0], "cd", 2) == 0)
{
char *argmnts = strtok(0, " ");
if (arguments != NULL)
{
chdir(argmnts);
putenv(argmnts); // THE ARG STRING NEEDS TO BE A STATIC COPY
getcwd(promptBuff, sizeof(argmnts));
}
}
The pointer argmnts points to the tokenized argument part from: char strnBuffer[1000] which has already been tokenized for the command: command[0] = strtok(strnBuffer, " ");
I really appreciate any help/insight.
Thank you.
You probably have a '\n' left over on the end of the input line. Your strtok only recognizes space as separator, so it won't touch the newline. chdir("dir\n") will fail unless you actually have a directory with the newline at the end of its name.
fwrite(&studentg,sizeof(studentg),1,p);
while(!feof(p))
{
printf("flag");
fread(&studentg,sizeof(studentg),1,p);
printf("%s\t%s\t%s\t%s\t%s\t%s\t\n",studentg.name,studentg.add,studentg.tel,studentg.pc,studentg.qq,studentg.email);
}
Why I put only one object in file,but it output two same line?
And if I put two objects in file,it output one object correct,but another repeated.
I try show feof(p)'s return value,it show me that after fread ,feof(p)'s return value is still 0.Can anyone explain how it happens?
You won't get an end of file until you try to read beyond the file. This means that you have to check eof before the print:
fwrite(&studentg,sizeof(studentg),1,p);
finish = 0;
while(!finish)
{
printf("flag");
fread(&studentg,sizeof(studentg),1,p);
finish = feof(p);
if (!finish)
{
printf("%s\t%s\t%s\t%s\t%s\t%s\t\n",studentg.name,studentg.add,studentg.tel,studentg.pc,studentg.qq,studentg.email);
}
}
or
fwrite(&studentg,sizeof(studentg),1,p);
while(1)
{
printf("flag");
fread(&studentg,sizeof(studentg),1,p);
if (feof(p)) break;
printf("%s\t%s\t%s\t%s\t%s\t%s\t\n",studentg.name,studentg.add,studentg.tel,studentg.pc,studentg.qq,studentg.email);
}
From http://www.cplusplus.com/reference/cstdio/feof/:
"This indicator is generally set by a previous operation on the stream that attempted to read at or past the end-of-file."
This means that end of file is usually detected after an operation.
To fix your code, you may for example replace the condition in while loop with 1 or true and break execution when eof is reached (run feof inside loop).
Use of feof is one of the biggest misconception among beginners in File I/O. Everybody at some point has done the same mistake once or twice.
The way you have used it is Pascal's way but C way is different. The difference is::
Pascal's function returns true if the next read will fail because of end of file.
C's function returns true if the last function failed.
Thats why your code prints the last line twice because after the last line is read in and printed out, feof() will still return 0 (false) and the loop will continue. The next fgets() fails and so the line variable holding the contents of the last line is not changed and is printed out again. After this, feof() will return true (since fgets() failed) and the loop ends.
The correct way to use it is::
while( 1 ) {
fgets(line, sizeof(line), fp);
if ( feof(fp) ) /* check for EOF right after fgets() */
break;
fputs(line, stdout);
}
Still better way::
while( fgets(line, sizeof(line), fp) != NULL )
fputs(line, stdout);
First of all you should include a complete, reproducing, example to what you want to do, not a combined fragment of the code, which is hard to reproduce. Otherwise, note that using fwrite()/fread() on struct contents directly is not portable (see the free online book Porting UNIX Software), and is prone to errors. But you didn't provide enough context for us to understand what went wrong.
Simple question I hope. I have a function that keeps prompting for user input (characters) and returns a character once it finds that the input is valid under certain conditions. I'm writing tests for this and other similar functions, but don't know how to fake user input. By the way, I'm using scanf() to get user input.
You can change the behaviour of standard input to read from a file with freopen. Place the test input in a file and call this before your test.
freopen("filename", "r", stdin);
You can do something like
echo -e "Test string\nAnother string" | ./a.out
The string of echo command should be in the sequence which the program requires
cat test_str_file | ./a.out
The file test_str_file should contain the test strings in the sequence the program requires
On the other hand you can simply replace the code's input section with some dummy sections. If you have a separate module for input, then replace it with dummy.
If you're on unix or cygwin, you can invoke your executable and ask it to use a text file as stdin. For example:
bash$ ./a.out < input_file
Why not just call the function with a default value?
This is a very naive solution, but it may do what you want:
char getFakeUserInput()
{
static char* fakeInput = "This is some user input\n";
static int pos = 0;
if(pos >= strlen(fakeInput))
return '\0';
return fakeInput[pos++]
}
Move the validation to another function. And test it independently. Or fake the user input refactor the remainder to take in a function pointer that is called back to collect some letters. That should enable a simple fake.
I've not written C for a long time but something like could also work
/* test this independentaly */
int isvalid(char* chars){
/* do stuff and return result */
}
/*real function */
char* getinput() {
scanf(....)
return stuff_from_scanf;
}
/*fake/mock function */
char* getinputFake(char * testString) {
return testString;
}
test() {
int result = isvalue(getinputFake("test data"));
/* rest of test */
}
You don't need to test the scanf function, but you could replace it with a fscanf and pass in the stream with the chars like this
stdin
char* getinput(FILE * stream) {
fscanf(stream....)
return stuff_from_fscanf;
}
test() {
FILE * stream = .....; /*create a dummy stream say from */
int result = isvalue(getinput(stream);
/* rest of test */
}
I have a C program which will take one argument as input and, if the argument is matching with the string inside the executable, it will return 1 otherwise 0. The executable file name is prg1. I have some input strings in a file named inputs.txt. I want to get those strings from the input file and call the prg1 inside a C program with each string.
I have tried the following code but it's not working.There is no segmentation fault but when i am calling prg1 it executes, Because the printf() statement inside prg1 is working and i can see the output.it changes variable found to 0I cant change the prg1. Because my friend has given the executable file of that program to me, not the source code. Header files are stdio.h and string.h
int main()
{
FILE *fk;
char text[80],inp[16],test[50]={"./prg1 "};
int found=100;
fk=fopen("inputs.txt","r");
while((fscanf(fk,"%s",inp))!=EOF)
{
strcat(test,inp);
found=system(test);
if(found==1)
{
printf("\nAnswer is : %s",inp);
break;
}
strcpy(test,"./prg1 ");
}
fclose(fk);
return 0;
}
What is wrong with my code?
I am not sure of what you want to achieve but here are some comments:
1 - You should test the return value of fopen:
if (!fk) { ... }
2 - You're not cleaning the test buffer between each test, so you are effectively calling:
system("prg1 first_word");
system("prg1 first_wordsecond_word");
...
You should have something like:
strcpy(test, "prg1 ");
after entering the loop and before strcat.
3 - Do you have spaces in your input strings? You should fix your code to read until a newline in this case.
4 - You might want to use EXIT_SUCCESS and EXIT_FAILURE instead of 0 and 1.
prog1 returns 1 when finding match, but 1 stands for error (at least in linux systems). Try returning EXIT_SUCCESS and EXIT_FAILURE (defined in stdlib.h). Then, when the system() call returns 0, the match is found, when anything else, match is not found.
The fundamental flaw in your code is that you need to reset the contents of the 'test' array to be "prg1 " at the beginning of each iteration of the main loop, before you call strcat to add the next argument to the command line. Otherwise the command to be run will just continue to get longer with each iteration, as each input read is added to the existing command. I don't think that is what you intend.
For example, given two lines of input, "foo" and "bar", the first iteration of the loop will cause the command "prg1 foo" to be executed, while the second will cause "prg1 foobar" to be executed. An easy way to have checked that would be to insert a printf (or similar) before the call to system() to display what command is going to be executed.
You also should check the return code of fopen and check array bounds when assigning to an array using fscanf.