I'm trying to read a whole line using scanf multiple times and for some reasons it only works the first time.
The second time the loop runs the compiler ignores the scanf function
Here is my code:
#include <stdio.h>
int main()
{
char msg[100];
char to[100];
while (1)
{
printf("[]:Msg to ? :");
scanf("%s", to);
printf("[]:Msg: ");
scanf("%99[^.]", msg);
printf("Sending %s\n", msg);
}
return 0;
}
And this is the output Im given:
[]:Msg to ? :Him []:Msg: Hello mister him!. Sending Hello mister
him! []:Msg to ? :[]:Msg:
And here I was expecting to be able to change the variable to ...
Adding a space before %s for some reason has no effect here
The problem is here:
scanf("%99[^.]", msg);
This statement reads up to 99 characters, but only until the next non-matching character. Now if you put
Hello mister him!.
into the input buffer, you indeed have
"Hello mister him!.\n"
in the stdin input stream buffer. Now, the scanf processes everything up to (but not including) the dot, so the dot and the newline remains in the input buffer. The next call to scanf()
scanf("%s", to);
now fetches the dot and the newline from the output buffer, which automatically concludes the next line to read. Now the input buffer is empty and the following scanf waits for the next message.
To fix this, you can skip the dot and the newline like this:
scanf("%99[^.]", msg);
getchar(); // Pacman (Eat the dot)
and in the other scanf use
// scanf(" %s", to); // Skip the preceding newline
(this is unnecessary, as H.S. pointed out)
Please note, that the case of an input message >99 chars is not handled properly yet.
If you wants to read a whole line using scanf you can use %[^\n] instead of %99[^.]. And make sure to add a getchar() if any 'enter' is pressed just before scanning with %[^\n].
The changes showed in the code bellow may be useful:
while (1)
{
printf("[]:Msg to ? :");
scanf("%[^\n]", to);
getchar();
printf("[]:Msg: ");
scanf("%[^\n]", msg);
getchar();
printf("Sending %s\n", msg);
}
Related
I am trying to create a program that repeatedly asks the user for input. However, in this case, the program just keeps printing "Enter your input" until it crashes after I enter something for the first time.
#include <stdio.h>
int main() {
while (1) {
char input[100];
printf("Enter a input: ");
scanf("%[^\n]s", input);
}
}
In:
scanf("%[^\n]s", input);
There are 2 problems:
The s is not part of that specific specifier, it should be only %[^\n].
That specifier leaves the \n newline character in the input buffer.
Your cycle will enter an infinite loop because there is always something to read there, but it's something that must not be parsed and should remain in the buffer.
A simple way to get rid of it is to place a space before the specifier:
scanf(" %[^\n]", input);
^
|
You are asking scanf() to read everything up to, but not including, the line break that ends the user's input.
So, the line break stays in the input buffer. Then on subsequent calls to scanf(), the line break is still not read from the input buffer, preventing scanf() from reading any new input.
You need to read that line break from the input buffer so that a subsequent call to scanf() can read the user's next input.
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 am using GCC to compile my C code.
My second scanf is not stopping to get the input.
It only reads in the first scanf and prints the two statements, one with what I entered in string and the other is just blank.
int main (void) {
setvbuf(stdout, NULL, _IONBF, 0);
char string[25] = {'\0'};
char c;
scanf(" %s", string);
scanf(" o%c", &out);
printf("Input is : %s \n\n", string);
printf("Out is: %c", out);
return 0;
}
Instead of getting
Input is whatever I typed and a prompt to enter a char for out
I got output as shown below
Input is : whatever i typed
Out is:
The program terminates. Can someone help. I've done some research and tried to put a space before %c for out and for string and still nothing happened.
You haven't defined out. And c is unused here. Having said that
Change
scanf(" o%c", &out); //What is that o in here? Is it a typo?
to
scanf(" %c", &out);
If your terminal uses line-buffered input
scanf(" %s", string);
can read the input till the first white-space. So the input buffer from the white-space is unused which is available for the next scanf which automatically starts reading from the buffer. So if you enter a string with spaces, the white-space will be assigned to the character out in your case
Change first scanf like below to clear the buffer:
if( scanf(" %s", string) == 1)
{
while(getchar()!='\n')
continue;
}
Also you might wish to replace
scanf(" %s", string);
with
fgets(string,25,stdin);
/* Use 26 if you actually wish to have max 25 characters
* ie char string[26]={'\0'}
*/
fgets has the advantage that it can read the white spaces and the newline charcter '\n' and it will automatically trim the output in case of an overflow.
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