This is the basic code to a program I am writing to practise using files in C. I am trying to detect whether the output file already exists and if it does exist I want to ask the user if they would like to overwrite it or not. This is the reason that I have first opened the outfilename file in with fopen(outfilename,"r"); as opposed to fopen(outfilename,"w");.
It detects the case of the file not existing, however, if it does exist it executes the printf("Output file already exists, overwrite (y/n):"); statement but completely ignores the scanf("%c",&yn); statement!
The printf at the end of the program reads "yn=0" if the file doesn't exist and just "yn=" if it does exist. Can anybody help me?
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <string.h>
int main(void) {
FILE *inf;
FILE *outf;
char filename[21],outfilename[21];
char yn='0';
printf("Please enter an input filename: ");
scanf("%s",&filename);
printf("Please enter an output filename: ");
scanf("%s",&outfilename);
/* Open file for reading */
inf=fopen (filename,"r");
outf=fopen(outfilename,"r");
/*check that input file exists*/
if (inf!=NULL) {
/*check that the output file doesn't already exist*/
if (outf==NULL){
fclose(outf);
/*if it doesn't already exist create file by opening in "write" mode*/
outf=fopen(outfilename,"w");
} else {
/*If the file does exist, give the option to overwrite or not*/
printf("Output file already exists, overwrite (y/n):");
scanf("%c",&yn);
}
}
printf("\n yn=%c \n",yn);
return 0;
}
printf("Please enter an output filename: ");
scanf("%s",&outfilename);
When you enter the second string and hit the ENTER key, a string and a character are placed in the input buffer, they are namely: the entered string and the newline character.The string gets consumed by the scanf but the newline remains in the input buffer.
Further,
scanf("%c",&yn);
Your next scanf for reading the character just reads/consumes the newline and hence never waits for user input.
Solution is to consume the extra newline by using:
scanf(" %c", &yn);
^^^ <------------Note the space
Or by using getchar()
You may want to check out my answer here for a detailed step by step explanation of the problem.
Use
scanf("%20s",&filename);
and remember that stdin is line buffered and on Linux is following a tty discipline
You could use GNU readline or ncurses if you want more detailed control.
scanf("%s", ...) leaves the \n terminating the line in the input. It isn't causing a problem for the next one as scanf("%s", ...) starts by skipping whites. scanf("%c", ...) doesn't and thus you read the \n.
BTW You'll probably meet other problems is you put spaces in your file name (%s doesn't read them) and if you enter too long names (%s has no input length limitations).
One solution for the problem you complained (but not the other one) is to use scanf(" %c", ...) (see the space before %c? scanf is tricky to use) which starts by skipping white spaces.
scanf("%s",&filename);
also remove the &
scanf.c:13: warning: format '%s' expects type 'char ', but argument 2 has type 'char ()[20u]'
The better way to handle this problem I found is explained here.
It recomends to use an alternative way of handle input and is very well explained.
I use always this function to get user input.
char * read_line (char * buf, size_t length) {
/**** Copyright de home.datacomm.ch/t_wolf/tw/c/getting_input.html#skip
Read at most 'length'-1 characters from the file 'f' into
'buf' and zero-terminate this character sequence. If the
line contains more characters, discard the rest.
*/
char *p;
if ((p = fgets (buf, length, stdin))) {
size_t last = strlen (buf) - 1;
if (buf[last] == '\n') {
/**** Discard the trailing newline */
buf[last] = '\0';
} else {
/**** There's no newline in the buffer, therefore there must be
more characters on that line: discard them!
*/
fscanf (stdin, "%*[^\n]");
/**** And also discard the newline... */
(void) fgetc (stdin);
} /* end if */
} /* end if */
return p;
} /* end read_line */
Old Answer
I fixed this sort of problems with this rule:
// first I get what I want.
c = getchar();
// but after any user input I clear the input buffer
// until the \n character:
while (getchar() != '\n');
// this also discard any extra (unexpected) character.
If you make this after any input, there should be not problem.
Related
This is the basic code to a program I am writing to practise using files in C. I am trying to detect whether the output file already exists and if it does exist I want to ask the user if they would like to overwrite it or not. This is the reason that I have first opened the outfilename file in with fopen(outfilename,"r"); as opposed to fopen(outfilename,"w");.
It detects the case of the file not existing, however, if it does exist it executes the printf("Output file already exists, overwrite (y/n):"); statement but completely ignores the scanf("%c",&yn); statement!
The printf at the end of the program reads "yn=0" if the file doesn't exist and just "yn=" if it does exist. Can anybody help me?
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <string.h>
int main(void) {
FILE *inf;
FILE *outf;
char filename[21],outfilename[21];
char yn='0';
printf("Please enter an input filename: ");
scanf("%s",&filename);
printf("Please enter an output filename: ");
scanf("%s",&outfilename);
/* Open file for reading */
inf=fopen (filename,"r");
outf=fopen(outfilename,"r");
/*check that input file exists*/
if (inf!=NULL) {
/*check that the output file doesn't already exist*/
if (outf==NULL){
fclose(outf);
/*if it doesn't already exist create file by opening in "write" mode*/
outf=fopen(outfilename,"w");
} else {
/*If the file does exist, give the option to overwrite or not*/
printf("Output file already exists, overwrite (y/n):");
scanf("%c",&yn);
}
}
printf("\n yn=%c \n",yn);
return 0;
}
printf("Please enter an output filename: ");
scanf("%s",&outfilename);
When you enter the second string and hit the ENTER key, a string and a character are placed in the input buffer, they are namely: the entered string and the newline character.The string gets consumed by the scanf but the newline remains in the input buffer.
Further,
scanf("%c",&yn);
Your next scanf for reading the character just reads/consumes the newline and hence never waits for user input.
Solution is to consume the extra newline by using:
scanf(" %c", &yn);
^^^ <------------Note the space
Or by using getchar()
You may want to check out my answer here for a detailed step by step explanation of the problem.
Use
scanf("%20s",&filename);
and remember that stdin is line buffered and on Linux is following a tty discipline
You could use GNU readline or ncurses if you want more detailed control.
scanf("%s", ...) leaves the \n terminating the line in the input. It isn't causing a problem for the next one as scanf("%s", ...) starts by skipping whites. scanf("%c", ...) doesn't and thus you read the \n.
BTW You'll probably meet other problems is you put spaces in your file name (%s doesn't read them) and if you enter too long names (%s has no input length limitations).
One solution for the problem you complained (but not the other one) is to use scanf(" %c", ...) (see the space before %c? scanf is tricky to use) which starts by skipping white spaces.
scanf("%s",&filename);
also remove the &
scanf.c:13: warning: format '%s' expects type 'char ', but argument 2 has type 'char ()[20u]'
The better way to handle this problem I found is explained here.
It recomends to use an alternative way of handle input and is very well explained.
I use always this function to get user input.
char * read_line (char * buf, size_t length) {
/**** Copyright de home.datacomm.ch/t_wolf/tw/c/getting_input.html#skip
Read at most 'length'-1 characters from the file 'f' into
'buf' and zero-terminate this character sequence. If the
line contains more characters, discard the rest.
*/
char *p;
if ((p = fgets (buf, length, stdin))) {
size_t last = strlen (buf) - 1;
if (buf[last] == '\n') {
/**** Discard the trailing newline */
buf[last] = '\0';
} else {
/**** There's no newline in the buffer, therefore there must be
more characters on that line: discard them!
*/
fscanf (stdin, "%*[^\n]");
/**** And also discard the newline... */
(void) fgetc (stdin);
} /* end if */
} /* end if */
return p;
} /* end read_line */
Old Answer
I fixed this sort of problems with this rule:
// first I get what I want.
c = getchar();
// but after any user input I clear the input buffer
// until the \n character:
while (getchar() != '\n');
// this also discard any extra (unexpected) character.
If you make this after any input, there should be not problem.
This is the basic code to a program I am writing to practise using files in C. I am trying to detect whether the output file already exists and if it does exist I want to ask the user if they would like to overwrite it or not. This is the reason that I have first opened the outfilename file in with fopen(outfilename,"r"); as opposed to fopen(outfilename,"w");.
It detects the case of the file not existing, however, if it does exist it executes the printf("Output file already exists, overwrite (y/n):"); statement but completely ignores the scanf("%c",&yn); statement!
The printf at the end of the program reads "yn=0" if the file doesn't exist and just "yn=" if it does exist. Can anybody help me?
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <string.h>
int main(void) {
FILE *inf;
FILE *outf;
char filename[21],outfilename[21];
char yn='0';
printf("Please enter an input filename: ");
scanf("%s",&filename);
printf("Please enter an output filename: ");
scanf("%s",&outfilename);
/* Open file for reading */
inf=fopen (filename,"r");
outf=fopen(outfilename,"r");
/*check that input file exists*/
if (inf!=NULL) {
/*check that the output file doesn't already exist*/
if (outf==NULL){
fclose(outf);
/*if it doesn't already exist create file by opening in "write" mode*/
outf=fopen(outfilename,"w");
} else {
/*If the file does exist, give the option to overwrite or not*/
printf("Output file already exists, overwrite (y/n):");
scanf("%c",&yn);
}
}
printf("\n yn=%c \n",yn);
return 0;
}
printf("Please enter an output filename: ");
scanf("%s",&outfilename);
When you enter the second string and hit the ENTER key, a string and a character are placed in the input buffer, they are namely: the entered string and the newline character.The string gets consumed by the scanf but the newline remains in the input buffer.
Further,
scanf("%c",&yn);
Your next scanf for reading the character just reads/consumes the newline and hence never waits for user input.
Solution is to consume the extra newline by using:
scanf(" %c", &yn);
^^^ <------------Note the space
Or by using getchar()
You may want to check out my answer here for a detailed step by step explanation of the problem.
Use
scanf("%20s",&filename);
and remember that stdin is line buffered and on Linux is following a tty discipline
You could use GNU readline or ncurses if you want more detailed control.
scanf("%s", ...) leaves the \n terminating the line in the input. It isn't causing a problem for the next one as scanf("%s", ...) starts by skipping whites. scanf("%c", ...) doesn't and thus you read the \n.
BTW You'll probably meet other problems is you put spaces in your file name (%s doesn't read them) and if you enter too long names (%s has no input length limitations).
One solution for the problem you complained (but not the other one) is to use scanf(" %c", ...) (see the space before %c? scanf is tricky to use) which starts by skipping white spaces.
scanf("%s",&filename);
also remove the &
scanf.c:13: warning: format '%s' expects type 'char ', but argument 2 has type 'char ()[20u]'
The better way to handle this problem I found is explained here.
It recomends to use an alternative way of handle input and is very well explained.
I use always this function to get user input.
char * read_line (char * buf, size_t length) {
/**** Copyright de home.datacomm.ch/t_wolf/tw/c/getting_input.html#skip
Read at most 'length'-1 characters from the file 'f' into
'buf' and zero-terminate this character sequence. If the
line contains more characters, discard the rest.
*/
char *p;
if ((p = fgets (buf, length, stdin))) {
size_t last = strlen (buf) - 1;
if (buf[last] == '\n') {
/**** Discard the trailing newline */
buf[last] = '\0';
} else {
/**** There's no newline in the buffer, therefore there must be
more characters on that line: discard them!
*/
fscanf (stdin, "%*[^\n]");
/**** And also discard the newline... */
(void) fgetc (stdin);
} /* end if */
} /* end if */
return p;
} /* end read_line */
Old Answer
I fixed this sort of problems with this rule:
// first I get what I want.
c = getchar();
// but after any user input I clear the input buffer
// until the \n character:
while (getchar() != '\n');
// this also discard any extra (unexpected) character.
If you make this after any input, there should be not problem.
I wanna reproduce the terminal behavior when the input is just a new line (keeps printing the same string), but don't know how to do it.
Example: When the user just inputs a new line, the terminal keeps printing the directory, until a real command is inserted
int main()
{
char userInput[1024];
while (1)
{
printf("directory »» ");
scanf("%[^\n]" , userInput); // This scanf doesn't work
while (userInput[0] == '\n') // If the input is only a new line char, keep asking for more inputs and printing the directory
{
printf("directory »» ");
scanf(" %[^\n ]" , userInput); // This scanf doesn't work
}
//Input isn't a NewLine, process the input
process_Input_Function(userInput); //Isn't empty, search for my created commands
}
}
At the first enter press, it enters the loop, reproduce 1 time, and then the scanf doesn't detect new lines anymore, it just skips and waits to a real string.
What can i type inside of the scanfto detect a new line input and keep printing that string till a real command is inserted?
I tried with scanf("%c"...) but the problem with a char, is that i can't process the whole string command, if isn't empty
First of all, your two scanf calls are different. The first one is
scanf("%[^\n]", userInput);
which looks for anything that's not a newline, as you wish to do.
But the second one is
scanf(" %[^\n ]", userInput);
which is also looking for a space before the input, followed by any character that is also not a newline or a space. Thus, scanf is waiting for the space.
IMHO, the best way to recreate this behavior is going to be in the parsing step, after you have gotten the command from the command line. Essentially, your command input loop would look like this:
char *userInput = NULL;
size_t n = 0;
while (true) {
// print the prompt
printf(">");
// get the line
ssize_t userInputLength = getline(&userInput, &n, &stdin);
// parse the input, using a function you wrote elsewhere
parse(userInputLength, userInput);
}
(Note the use of POSIX getline() instead of scanf. This is a more recent standard library function that does exactly the task of getting a line of user input, and also allocates the buffer using malloc and realloc so that you don't have to care about buffer overflows or even sizing the buffer at all.)
The user input function wouldn't care that the userInput portion was blank. The function that would care is the parse function, which will simply interpret a blank userInput string as "do nothing" and continue on its merry way.
Hmm, the code I gave pretty much does that with one exception, it doesn't display a prompt each time...
Is this what you mean:
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // For the memset()
int main() {
char userInput[1024];
while (1) {
printf("»»» ");
fgets(userInput, 1024, stdin);
while (userInput[0] == '\n')
{
printf(">>> ");
memset(userInput, '\0', 1024);
fgets(userInput, 1024, stdin);
}
// Your command can be accessed from here //
printf("Command entered: %s\n", userInput);
printf("Input isn't a NewLine\n");
}
}
I changed the scanf() to fgets() to read from stdin so that we don't overwrite the buffer.
I'm newcomer to C and I am stuck. I want to write simple program, which will take input from keyboard and output it if it isn't an 'exit' word. I've tried few different approaches and none of them works. Almost in all cases I get infinite output of the first input.
Here is one of my approaches:
#include <stdio.h>
int main() {
char word[80];
while (1) {
puts("Enter a string: ");
scanf("%79[^\n]", word);
if (word == "exit")
break;
printf("You have typed %s", word);
}
return 0;
}
I thought after it finish every loop it should give me prompt again, but it doesn't.
What I am doing wrong.
Please if you know give me some advice.
Thanks in advance. Really, guys I will be so happy if you help me to understand what I am doing wrong.
Oh, by the way I've noticed that when I typed some word and press 'Enter', the result string also include Enter at the end. How can I get rid of this ?
Improper string compare - use strcmp().
if (word == "exit") simply compares 2 address: the address of the first char in word and the address of the first char in string literal "exit". Code needs to compare the content beginning at those addresses: strcmp() does that.
Left-over '\n' from the previous line's Enter. Add a space to scanf() format to consume optional leading white-space. Also check scanf() results.
scanf() specifiers like "%d", "%u" and "%f" by themselves consume optional leading white-space. 3 exceptions: "%c", "%n" and "%[".
Add '\n' at end of printf() format. # Matt McNabb
#include <stdio.h>
int main() {
char word[80];
while (1) {
puts("Enter a string: ");
// v space added here
if (scanf(" %79[^\n]", word) != 1)
break; // Nothing saved into word or EOF or I/O Error
if (strcmp(word, "exit") == 0)
break;
printf("You have typed %s\n", word);
}
return 0;
}
Nice that OP used a proper width limited value of 79 in scanf()
Oh, by the way I've noticed that when I typed some word and press 'Enter', the result string also include Enter at the end. How can I get rid of this ?
This is because you don't output a newline after printf("You have typed %s", word);. The next statement executed is puts("Enter a string: "); . So you will see You have typed helloEnter a string:. To fix this, change to printf("You have typed %s\n", word);
As others have mentioned, use strcmp to compare strings in C.
Finally, the scanf format string "%79[^\n]" does not match a newline. So the input stream still contains a newline. Next time you reach this statement the newline is still in the stream , and it still doesn't match because you specifically excluded newlines.
You will need to discard that newline (and any other input on the line) before getting the next line. One way to do that is to change the input to scanf("%79[^\n]%*[^\n]", word); getchar(); That means:
Read up to 79 non-newlines
Read all the non-newline things , and don't store them
Read a character (which must be a newline now) and don't store it
Finally it would be a good idea to check the return value of scanf so that if there is an error then you can exit your program instead of going into an infinite loop.
The specifier [^\n] will abort scanf if the next character is a newline (\n), without reading the newline. Because of that, the scanf calls after the first one won't read any input.
If you want to read single words, use the %79s specifier and the following code to remove the \n at the end of your string:
if(word[strlen(word)]=='\n')
word[strlen(word)]='\0';
If you want to read whole lines, you can remove the newline from the input buffer this way:
char line[80];
int i;
while(1)
{
puts("Enter a string:");
i=-1;
scanf("%79[^\n]%n",line,&i);
//%n returns the number of characters read so far by the scanf call
//if scanf encounters a newline, it will abort and won't modify i
if(i==-1)
getchar(); //removes the newline from the input buffer
if(strcmp(line,"exit")==0)
break;
printf("You have typed %s\n",line);
}
return 0;
It is better to clear (to have a reproducible content) with memset(3) the memory buffer before reading it, and you should use strcmp(3) to compare strings. Also, consider using fflush(3) before input (even if it is not actually necessary in your case), don't forget to test result of scanf(3), also most printf(3) format control strings should end with a \n -for end-of-line with flushing- so:
#include <stdio.h>
int main() {
char word[80];
while(1) {
puts("Enter a string: ");
memset (word, 0, sizeof(word)); // not strictly necessary
fflush(stdout); // not strictly necessary
if (scanf("%79[^\n]", word)<=0) exit(EXIT_FAILURE);
if (!strcmp(word,"exit"))
break;
printf("You have typed %s\n", word);
};
return 0;
}
I would suggest reading a whole line with fgets(3) and getting rid of its ending newline (using strchr(3)). Also read about getline(3)
Don't forget to compile with all warnings and debug info (e.g. gcc -Wall -g) and learn how to use the debugger (e.g. gdb)
Your first problem is that you can't compare a string with '=='. So:
if (word == "exit")
should be
if ( strncmp( word, "exit", 4 ) == 0 )
(You could also use strncmp( word, "exit", strlen(word) ) if you know that word is zero-terminated and safe from bad values. There's a few other options also.)
Your second problem is that scanf() is not consuming the input, probably because it's not matching what you've told it to expect. Here is a good explanation of how to do what you want to do:
http://home.datacomm.ch/t_wolf/tw/c/getting_input.html
This is the basic code to a program I am writing to practise using files in C. I am trying to detect whether the output file already exists and if it does exist I want to ask the user if they would like to overwrite it or not. This is the reason that I have first opened the outfilename file in with fopen(outfilename,"r"); as opposed to fopen(outfilename,"w");.
It detects the case of the file not existing, however, if it does exist it executes the printf("Output file already exists, overwrite (y/n):"); statement but completely ignores the scanf("%c",&yn); statement!
The printf at the end of the program reads "yn=0" if the file doesn't exist and just "yn=" if it does exist. Can anybody help me?
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <string.h>
int main(void) {
FILE *inf;
FILE *outf;
char filename[21],outfilename[21];
char yn='0';
printf("Please enter an input filename: ");
scanf("%s",&filename);
printf("Please enter an output filename: ");
scanf("%s",&outfilename);
/* Open file for reading */
inf=fopen (filename,"r");
outf=fopen(outfilename,"r");
/*check that input file exists*/
if (inf!=NULL) {
/*check that the output file doesn't already exist*/
if (outf==NULL){
fclose(outf);
/*if it doesn't already exist create file by opening in "write" mode*/
outf=fopen(outfilename,"w");
} else {
/*If the file does exist, give the option to overwrite or not*/
printf("Output file already exists, overwrite (y/n):");
scanf("%c",&yn);
}
}
printf("\n yn=%c \n",yn);
return 0;
}
printf("Please enter an output filename: ");
scanf("%s",&outfilename);
When you enter the second string and hit the ENTER key, a string and a character are placed in the input buffer, they are namely: the entered string and the newline character.The string gets consumed by the scanf but the newline remains in the input buffer.
Further,
scanf("%c",&yn);
Your next scanf for reading the character just reads/consumes the newline and hence never waits for user input.
Solution is to consume the extra newline by using:
scanf(" %c", &yn);
^^^ <------------Note the space
Or by using getchar()
You may want to check out my answer here for a detailed step by step explanation of the problem.
Use
scanf("%20s",&filename);
and remember that stdin is line buffered and on Linux is following a tty discipline
You could use GNU readline or ncurses if you want more detailed control.
scanf("%s", ...) leaves the \n terminating the line in the input. It isn't causing a problem for the next one as scanf("%s", ...) starts by skipping whites. scanf("%c", ...) doesn't and thus you read the \n.
BTW You'll probably meet other problems is you put spaces in your file name (%s doesn't read them) and if you enter too long names (%s has no input length limitations).
One solution for the problem you complained (but not the other one) is to use scanf(" %c", ...) (see the space before %c? scanf is tricky to use) which starts by skipping white spaces.
scanf("%s",&filename);
also remove the &
scanf.c:13: warning: format '%s' expects type 'char ', but argument 2 has type 'char ()[20u]'
The better way to handle this problem I found is explained here.
It recomends to use an alternative way of handle input and is very well explained.
I use always this function to get user input.
char * read_line (char * buf, size_t length) {
/**** Copyright de home.datacomm.ch/t_wolf/tw/c/getting_input.html#skip
Read at most 'length'-1 characters from the file 'f' into
'buf' and zero-terminate this character sequence. If the
line contains more characters, discard the rest.
*/
char *p;
if ((p = fgets (buf, length, stdin))) {
size_t last = strlen (buf) - 1;
if (buf[last] == '\n') {
/**** Discard the trailing newline */
buf[last] = '\0';
} else {
/**** There's no newline in the buffer, therefore there must be
more characters on that line: discard them!
*/
fscanf (stdin, "%*[^\n]");
/**** And also discard the newline... */
(void) fgetc (stdin);
} /* end if */
} /* end if */
return p;
} /* end read_line */
Old Answer
I fixed this sort of problems with this rule:
// first I get what I want.
c = getchar();
// but after any user input I clear the input buffer
// until the \n character:
while (getchar() != '\n');
// this also discard any extra (unexpected) character.
If you make this after any input, there should be not problem.