I am building a basic C program that continuously asks users for a string input and prints out the entered input. The program is supposed to exit when a user enters a blank line. However, in my following program, even when I have a conditional that checks whether the user entered a blank line, the program still keeps on going until the user types an input. Below is my code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char userString[100];
while (1 == 1) {
scanf("%s", userString);
printf("USER ENTERED %s\n", userString);
if (userString[0] == '\n') {
exit(0);
}
}
}
scanf("%s", userString); scanf("%s", userString);
scanf with %s will read the input stream until it meets any of the whitespace. Thus newline will not be included as part of userString.
Use fgets instead.
fgets(userString, sizeof userString, stdin);
The scanf function usually read space delimited "token" (words, numbers, etc.).
Almost all format specifiers (including %s) skip leading white-space (all spaces, such as normal space, tab and newline). The only two formats that doesn't skip space is the %[ format and the %c format, the first of which could be useful for you but I recommend against it.
To read lines I recommend the fgets function instead. If the only character in the buffer is the newline then you have an empty line.
Related
I know that adding a space in front of %c in scanf() will scan my second character; however, if two letters were inputted in the first character, it will input the second letter into the second character. How do I scan a single character only?
#include <stdio.h>
int main(void)
{
char firstch, secondch;
printf("Enter your first character: ");
scanf("%c", &firstch);
printf("Enter your second character: ");
scanf(" %c", &secondch);
printf("\n Fisrt character : %c \n Second character : %c \n", firstch, secondch);
return 0;
}
This is my result after running:
Enter your first character: ab
Enter your second character:
First character : a
Second character : b
I only want to read the first character 'a', but the second letter 'b' was inputted right away before I enter my second character.
When you are reading a line of user-input, use a line-oriented input function like fgets() or POSIX getline(). That way the entire line of input is read at once and you can simply take the first character from the line. Say you read a line into the array used as buffer called buf, e.g.
#define MAXC 1024 /* if you need a constant, #define one (or more) */
int main (void) {
char buf[MAXC]; /* buffer to read each line into */
You can simply access the first character as buf[0], or since buf[0] is equivalent to *(but + 0) in pointer notation, you can simply use *buf to get the first character.
As a benefit, since all line-oriented functions read and include the '\n' generated by the user pressing Enter after the input, you can simply check if the first character is '\n' as a way of indicating end-of-input. The user simply presses Enter alone as input to indicate they are done.
Using a line-oriented approach is the recommended way to take user input because it consumes and entire line of input each time and what remains in stdin unread doesn't depend on the scanf conversion specifier or whether a matching failure occurs.
Using " %c%*[^\n]" is not a fix-all. It leaves the '\n' in stdin unread. That's why you need the space before " %c". Where it is insidious is if your next input uses a line-oriented function after your code reading characters is done. Unless you manually empty the '\n' from stdin, before your next attempted line-oriented input, that input will fail because it will see the '\n' as the first character remaining in stdin.
A short example using fgets() for a line-oriented approach would be:
#include <stdio.h>
#define MAXC 1024 /* if you need a constant, #define one (or more) */
int main (void) {
char buf[MAXC]; /* buffer to read each line into */
for (;;) { /* loop continually */
fputs ("enter char: ", stdout); /* prompt for input */
/* read/validate line, break on EOF or [Enter] alone */
if (!fgets (buf, sizeof buf, stdin) || *buf == '\n')
break;
printf (" got: %c\n\n", *buf); /* output character read */
}
}
Where you simply take input continually isolating the first character as the value you want until the user presses Enter alone to break the read-loop.
Example Use/Output
$ ./bin/fgetschar
enter char: a
got: a
enter char: ab
got: a
enter char: a whole lot of stuff you don't have to deal with using fgets()
got: a
enter char: banannas
got: b
enter char: cantelopes
got: c
enter char:
Look things over and let me know if you have further questions.
Using a space before the %c will skip whitespace before scanning the next non-whitespace character. %c itself just scans a single character -- the next character in the input after whatever else was scanned or skipped previously.
So the question is, what do you want to do? Do you want to skip over all extraneous input on the line after the first character (up to newline?) fgets or scanf("%*[^\n]"); scanf("%c"); will do that (but be careful -- if firstch was itself a newline, this will skip the next line.) Do you want to check the input and make sure it is exactly one character on a line? If so, use fgets (not scanf) and check that the line read is exactly two characters (a character and a newline). Or perhaps you really want to read keystrokes without having the user hit Enter after esch one? That requires changing the input source setup, which is OS dependent.
I'm still new to C coding, and I've found a suitable answer to my problem by using scanf("%*[^\n]");
#include <stdio.h>
int main(void)
{
char firstch, secondch;
printf("Enter your first character: ");
scanf(" %c%*[^\n]", &firstch);
printf("Enter your second character: ");
scanf(" %c%*[^\n]", &secondch);
printf("\n First character : %c \n Second character : %c \n", firstch,
secondch);
return 0;
}
Results after running:
Enter your first character: ab
Enter your second character: c
First character : a
Second character : c
Thanks to #Eraklon #Chris Dodd #David C. Rankin
This was supposed to be very simple, but I'm having trouble to read successive inputs from the keyboard.
Here's the code:
#include <string.h>
#include <stdio.h>
int main()
{
char string[200];
char character;
printf ("write something: ");
scanf ("%s", string);
printf ("%s", string);
printf ("\nwrite a character: ");
scanf ("%c", &character);
printf ("\nCharacter %c Correspondent number: %d\n", character, character);
return 0;
}
What is happening
When I enter a string (e.g.: computer), the program reads the newline ('\n') and puts it in character. Here is how the display looks like:
write something: computer
computer
Character:
Correspondent number: 10
Moreover, the program does not work for strings with more than one word.
How could I overcome these problems?
First scanf read the entered string and left behind \n in the input buffer. Next call to scanf read that \n and store it to character.
Try this
scanf (" %c", &characte);
// ^A space before %c in scanf can skip any number of white space characters.
Program will not work for strings more than one character because scanf stops reading once find a white space character. You can use fgets instead
fgets(string, 200, stdin);
OP's first problem is typically solved by prepending a space to the format. This will consume white-space including the previous line's '\n'.
// scanf("%c", &character);
scanf(" %c", &character);
Moreover, the program does not work for strings with more than one word. How could I overcome these problems?
For the the 2nd issue, let us go for a more precise understanding of "string" and what "%s" does.
A string is a contiguous sequence of characters terminated by and including the first null character. 7.1.1 1
OP is not entering a string even though "I enter a string (e.g.: computer)," is reported. OP is entering a line of text. 8 characters "computer" followed by Enter. There is no "null character" here. Instead 9 char "computer\n".
"%s" in scanf("%s", string); does 3 things:
1) Scan, but not save any leading white-space.
2) Scan and save into string any number of non-white-space.
3) Stop scanning when white-space or EOF reached. That char is but back into stdin. A '\0' is appended to string making that char array a C string.
To read a line including spaces, do not use scanf("%s",.... Consider fgets().
fgets(string, sizeof string, stdin);
// remove potential trailing \r\n as needed
string[strcspn(string, "\n")] = 0;
Mixing scanf() and fgets() is a problem as calls like scanf("%s", string); fgets(...) leave the '\n' in stdin for fgets() to read as a line consisting of only "\n". Recommend instead to read all user input using fgets() (or getline() on *nix system). Then parse the line read.
fgets(string, sizeof string, stdin);
scanf(string, "%c", &character);
If code must user scanf() to read user input including spaces:
scanf("%*[\n]"); // read any number of \n and not save.
// Read up to 199 `char`, none of which are \n
if (scanf("%199[^\n]", string) != 1) Handle_EOF();
Lastly, code should employ error checking and input width limitations. Test the return values of all input functions.
What you're seeing is the correct behavior of the functions you call:
scanf will read one word from the input, and leave the input pointer immediately after the word it reads. If you type computer<RETURN>, the next character to be read is the newline.
To read a whole line, including the final newline, use fgets. Read the documentation carefully: fgets returns a string that includes the final newline it read. (gets, which shouldn't be used anyway for a number of reasons, reads and discards the final newline.)
I should add that while scanf has its uses, using it interactively leads to very confusing behavior, as I think you discovered. Even in cases where you want to read word by word, use another method if the intended use is interactive.
You can make use of %*c:
#include <string.h>
#include <stdio.h>
int main()
{
char string[200];
char character;
printf ("write something: ");
scanf ("%s%*c", string);
printf ("%s", string);
printf ("\nwrite a character: ");
scanf ("%c%*c", &character);
printf ("\nCharacter %c Correspondent number: %d\n", character, character);
return 0;
}
%*c will accept and ignore the newline or any white-spaces
You cal also put getchar() after the scanf line. It will do the job :)
The streams need to be flushed. When performing successive inputs, the standard input stream, stdin, buffers every key press on the keyboard. So, when you typed "computer" and pressed the enter key, the input stream absorbed the linefeed too, even though only the string "computer" was assigned to string. Hence when you scanned for a character later, the already loaded new line character was the one scanned and assigned to character.
Also the stdout streams need to be flushed. Consider this:
...
printf("foo");
while(1)
{}
...
If one tries to execute something like this then nothing is displayed on the console. The system buffered the stdout stream, the standard output stream, unaware of the fact it would be encounter an infinite loop next and once that happens, it never gets a chance to unload the stream to the console.
Apparently, in a similar manner whenever scanf blocks the program and waits on stdin, the standard input stream, it affects the other streams that are buffering. Anyway, whatsoever may be the case it's best to flush the streams properly if things start jumbling up.
The following modifications to your code seem to produce the desired output
#include <string.h>
#include <stdio.h>
int main()
{
char string[200];
char character;
printf ("write something: ");
fflush(stdout);
scanf ("%s", string);
fflush(stdin);
printf ("%s", string);
printf ("\nwrite a character: ");
fflush(stdout);
scanf ("%c", &character);
printf ("\nCharacter %c Correspondent number: %d\n", character, character);
return 0;
}
Output:
write something: computer
computer
write a character: a
Character a Correspondent number: 97
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
Having this piece of code:
int main(void)
{
char str[4];
do
{
if (fgets(str,sizeof(str),stdin) == NULL)
break;
printf("\n %s \n", str);
}while (strncmp(str,"q\n",sizeof("q\n")));
return 0;
}
if i type more than 4 characters, then two lines are displayed. if i type 123456 and then press enter, does input store ['1','2','\n','\0'] or ['1','2','3','\0']? hen the second time printf is reached if i only press enter key one time?. How i can avoid this behaviour? I would like type 123456 and then get:
1234
The reason why fgets is only reading partial input is because the str array is too small. You need to increase the buffer size of str array.
Also remember that fgets will pick up \n ( enter / return ) that you press after giving your input.
To get rid of the \n do this:
fgets(str,sizeof(str),stdin);
str[strlen(str)-1] = '\0';
There is one MAJOR issue with your while condition ... I am not sure what your are trying to do there but strcmp is used to see if two strings are the same or not ... what you are doing is trying to compare a string to the size of something ...
There are multiple problems in your code:
you do not include <stdio.h>.
fgets() is given a very short buffer: 4 bytes, allowing for only 3 characters to be input at a time, including the '\n'. If you type more characters, they are buffered by the terminal and the standard stream library. It will take several calls to fgets() to read them all, 3 bytes at a time.
Your termination test is bogus: strncmp(str, "q\n", sizeof("q\n")) compares the string read by fgets() with "q\n" upto a maximum number of characters of 3 because sizeof("q\n") counts the q, the \n and the null terminator. You should just use strcmp() for this test.
You print the string with printf("\n %s \n", str);. Note however that a regular line read into str will contain the trailing newline so the printf call will actually output 2 lines.
Here is a modified version:
#include <stdio.h>
#include <string.h>
int main(void) {
char str[80];
while (fgets(str, sizeof(str), stdin) != NULL) {
str[strcspn(str, "\n")] = '\0'; // strip the newline if present
printf("\n %s \n", str);
if (!strcmp(str, "q"));
break;
}
return 0;
}
Try using getc() or fgetc() before using fgets()
When you use a scanf(), you press enter key (newline) which operates as accepting the input and transferring the input from stdin (standard input device) to your program.
scanf() itself does not consume the newline pressed. So, we need something down the code which will accept this newline and prevent this newline from acting as an input to the subsequent fgets(). This newline can be accepted using getc() or fgetc(), which should be written before fgets().
fgetc(stdin); OR getc(stdin);
In the below program when am reading input from keyboard its taking only 2 characters instead of 4 and remaining 2 characters its taking spaces by default.
why is it???
program to take char input through pointers/
int c,inc,arrysize;
char *revstring;
printf("enter the size of char arry:");
scanf("%d",&arrysize);
revstring = (char *)malloc(arrysize * sizeof(*revstring));
printf("%d",sizeof(revstring));
printf("enter the array elements:");
for(inc=0;inc<arrysize;inc++)
{
scanf("%c",&revstring[inc]);
}
for(inc =0;inc<arrysize;inc++)
printf("%c",revstring[inc]);
getch();
return 0;
}
scanf reads formatted inputs. When you tape a number, you tape the digits, and then, you press <Enter>. So there is a remaining \n in stdin, which is read in the next scanf. The same applies if you press <Enter> between the characters.
A solution is to consume the characters in the standard input stream after each input, as follow:
#include <stdio.h>
void
clean_stdin (void)
{
int c;
while ((c = getchar ()) != '\n' && c != EOF)
;
}
Another idea is to use fgets to get human inputs. scanf is not suitable for such readings.
Most of the time scanf reads formatted input. For most % formats, scanf will first read and discard any whitespace and then parse the item specified. So with scanf("%d", ... it will accept inputs with initial spaces (or even extra newlines!) with no problems.
One of the exceptions, however, is %c. With %c, scanf reads the very next character, whatever it may be. If that next character is a space or newline, that is what you get.
Depending on what exactly you want, you may be able to just use a blank space in your format string:
scanf(" %c",&revstring[inc]);
The space causes scanf to skip any whitespace in the input, giving you the next non-whitespace character read. However, this will make it impossible to enter a string with spaces in it (the spaces will be ignored). Alternately, you could do scanf(" "); before the loop to skip whitespace once, or scanf("%*[^\n]"); scanf("%*c"); to skip everything up to the next newline, and then skip the newline.