I got this code:
#include <stdio.h>
int main(void){
char ordet;
int again = 1;
while(again == 1){
printf("Write a name: \n");
while (ordet!='\n'){
scanf("%c",&ordet);
if('A'<= ordet && ordet <='W')
{
printf("%c",ordet+3);
}
else if('W'<=ordet){
printf("%c", ordet-22);
}
}
printf("\nDo you want to write a new name? 1/0");
scanf("%d", &again);
}
return 0;
}
It runs fine the first time but as soon as you press 1 to write a new name you never get the chance to write it, it just keeps asking "Do you want to write a new name?" and ignores "Write a name:". I have tested with fflush(stdin), != EFO and space infront of %c but nothing works. How could I fix this since I really have no idea, started out with C a few days ago.
while (ordet!='\n'){
ordet is used without initialization here. Not quite UB (if your implementation uses unsigned char or signed char has no trap-representations), but bad enough.
scanf("%c",&ordet);
The above line is the only line potentially setting ordet. Please take note that the loop starting with it is only entered when ordet is not '\n'.
You probably want to reset it before entering the inner loop, or use a do-while-loop.
Actually, changing both loops to do-while-loops would be good.
scanf("%d", &again);
The above line reads a number from beginning of stdin, but leaves the newline.
This must be dealt with by consuming all whitespace on repeat.
Luckily, that's easily done as the inner loop ignores whitespace.
Change "%c" to " %c".
Also, all your scanf-invocations can fail. Check them!
There are 2 problems with your code:
ordet is not initialized before its first usage. It is undefined behavior.
You do not reset ordet anywhere outside the inner loop. That is, once ordet becomes equal to \n, the body of the inner loop is never executed again.
To fix it, you can write something like ordet = 0 before inner loop. And don't forget to skip new line character that is left in the buffer after reading again variable.
All input you write in the console from the keyboard is placed in a buffer, scanf reads from this buffer however if there are more characters in the buffer than what your format specifier specifies those characters will remain in the buffer.
e.g.
scanf( "%d", &n );
when you enter a numerical value 100 and press ENTER afterwards, the ENTER character is placed in the buffer as well "100\n" when you do scanf on the buffer (stdin) the 100 is extracted from the buffer but the \n remains.
Next time you write scanf("%d", &n ); the \n is still in there and will not be read by %d since it is not a %d number.
IMO the best way to handle this is instead to read from the keyboard using fgets, then after the content has been read use sscanf to extract the information you want:
char buffer[128];
fgets( buffer, sizeof(buffer), stdin );
sscanf( buffer, "%d", &n );
you also then can have additional error checks:
if (fgets( buffer, sizeof(buffer), stdin ) != NULL )
{
if (sscanf( buffer, "%d", &n ) ==1)
{
...
}
}
now to your code:
if you want to read character by character from the keyboard use fgetc() not scanf()
Use the C-runtime function isalpha()/toupper() to recognize a character.
In C, a character is an int, that is why most functions like fgetc return an int and not a char.
In general I would recommend using fgets() instead of reading one character at a time.
Related
I'm trying to read a line with scanf("%[^\n]"); right before it I'm reading an integer with "%d", was told to me that scanf doesn't erase the '\n' after reading, so I have to call fflush() to avoid it, but even doing that I still have the same problems, so here is my code:
scanf("%d", &n);
fflush(stdin);
lines = (char**)malloc(sizeof(char*)*n);
for(i = 0; i < n; i++){
lines[i] = (char*)malloc(sizeof(char)*1001);
}
for(i = 0;i < n;i++){
scanf("%[^\n]", linhes[i]);
}
I read an integer and then the scanf doesn't wait, it starts reading the input — doesn't matter what the integer value is, whether 5 or 10, the scanf reads all the strings to empty. Already tried with fgets and the result is almost the same, except that it reads some of the strings and skips others.
Let us look at this step by step:
"... read a line with scanf("%[^\n]");".
scanf("%[^\n]", buf) does not read a line. It almost does - sometimes. "%[^\n]" directs scanf() to read any number of non-'\n' char until one is encountered (that '\n' is then put back into stdin) or EOF occurs.
This approach has some problems:
If the first char is '\n', scanf() puts it back into stdin without changing buf in anyway! buf is left as is - perhaps uninitialized. scanf() then returns 0.
If at least one non-'\n' is read, it is saved into buf and more char until a '\n' occurs. A '\0' is appended to buf and the '\n' is put back into stdin and scanf() returns 1. This unlimited-ness can easily overfill buf. If no char was saved and EOF or input error occurs, scanf() returns EOF.
Always check the return value of scanf()/fgets(), etc. functions. If your code does not check it, the state of buf is unknown.
In any case, a '\n' is still usually left in stdin, thus the line was not fully read. This '\n' often is an issue for the next input function.
... scanf doesn't erase the '\n' after reading
Another common misconception. scanf() reads a '\n', or not, depending on the supplied format. Some formats consume '\n', others do not.
... call fflush() to avoid it
fflush(stdin) is well defined in some compilers but is not in the C standard. The usual problem is code wants to eliminate any remaining data in stdin. A common alternative, when the end of the line had not yet occurred, is to read and dispose until '\n' is found:
int ch; // Use int
while ((ch = fgetc(stdin)) != '\n' && ch != EOF);
I still have the same problems
The best solution, IMO, is to read a line of user input and then scan it.
char buf[sizeof lines[i]];
if (fgets(buf, sizeof buf, stdin) == NULL) return NoMoreInput();
// If desired, remove a _potential_ trailing \n
buf[strcspn(buf, "\n")] = 0;
strcpy(lines[i], buf);
I recommend that a buffer should be about 2x the size of expected input for typical code. Robust code, not this snippet, would detect if more of the line needs to be read. IMO, such excessively long lines are more often a sign of hackers and not legitimate use.
BLUEPIXY in the comment answered my question:
try "%[^\n]" change to " %[^\n]"
below is my simple code to enter a number and print it. it is inside a while(1) loop so i need to "Enter the number infinite number of time- each time it will print the number and again wait for the input".
#include<stdio.h>
int main()
{
int i;
while(1){
printf("\nenter i \n");
scanf("%d", &i);
if(i==1)
{
printf("%d \n", i);
}
}
return 0;
}
it was working fine. but suddenly i noticed that IF i ENTER a character(eg: "w") instead of number , from there it won't ask for input!!!**
it continuesly prints,
enter i
1
enter i
1
......
when i debug using GDB, i noticed that after i enter "w", that value of character "w" is not stored in &i . before i enter "w" it had 0x00000001 so that "1" is printed through out the process.
Why it doesn't ask for another input? According to my knowledge, when I enter "w" the ascii value of "w" should be stored in &i. But it doesn't happen.
If I put, "int i; " inside while loop it works fine! Why?
Please test my code in following way:
Copy and paste and run it
When "enter i" prompt will come enter 1
Second time enter "w". See what happens...
scanf with %d format specifier will read everything that "looks like a number", i.e. what satisfies the strictly defined format for a decimal representation of an integer: some optional whitespace followed by an optional sign followed by a sequence of digits. Once it encounters a character that cannot possibly be a part of a decimal representation, scanf stops reading and leaves the rest of the input data in the input stream untouched (to wait for the next scanf). If you enter just w, your scanf will find nothing that "looks like a number". It will read nothing. Instead it will report failure through its return value. Meanwhile your w will remain in the input stream, unread. The next time you try your scanf, exactly the same thing will happen again. And again, and again, and again... That w will sit in the input stream forever, causing each of your scanf calls to fail immediately and your loop to run forever (unless your uninitialized variable i by pure chance happens to start its life with the value of 1 in it).
Your assumption that entering w should make scanf to read ASCII code of w is completely incorrect. This sounds close to what %c format specifier would do, but this is not even close to what %d format specifier does. %d does not read arbitrary characters as ASCII codes.
Note also that every time you attempt to call that scanf with w sitting in the input stream, your scanf fails and leaves the value of i unchanged. If you declare your i inside the loop, the value of i will remain uninitialized and unpredictable after each unsuccessful scanf attempt. In that case the behavior of your program is undefined. It might even produce an illusion of "working fine" (whatever you might understand under that in this case).
You need to check the return value of scanf as well, as it will return the number of successfully scanned and parsed values. If it returns zero (or EOF) then you should exit the loop.
What happens when you enter e.g. the character 'w' instead of a number is that the scanf function will fail with the scanning and parsing, and return zero. But the input will not be removed from the input buffer (because it was not read), so in the next loop scanf will again read the non-numeric input and fail, and it will do this infinitely.
You can try this workaround:
int main()
{
int i;
char c;
while (1)
{
printf("enter i: ");
if (scanf("%d",&i) == 0)
scanf("%c",&c); // catch an erroneous input
else
printf("%d\n",i);
}
return 0;
}
BTW, when were you planning to break out of that (currently infinite) loop?
You need to read up on scanf(), since you seem to be basing your program around some assumptions which are wrong.
It won't parse the character since the conversion format specifier %d means "decimal integer".
Also, note that you must check the return value since I/O can fail. When you enter something which doesn't match the conversion specifier, scanf() fails to parse it.
You would probably be better of reading whole lines using fgets(), then using e.g. sscanf() to parse the line. It's much easier to get robust input-reading that way.
scanf return type can be checked and based on that inputs can be consumed using getchar to solve your problem.
Example code
int main()
{
int i;
int ch;
while(1){
printf("\nenter i \n");
if ( scanf("%d", &i) !=1 )
{
/*consume the non-numeric characters*/
for (; (ch = getchar()) != EOF && ch != '\n'; ) { }
}
if(i==1)
{
printf("%d \n", i);
}
}
return 0;
}
Description:
When scanf("%d", &i) encounters the character, it will not read it. The character will still remains in the input stream. So to consume those characters, getchar() can used. Then scanf will wait for the next input in further iteration.
I was always bad at inputting characters in C and this is another example. Though I understood (maybe) what's happening but I can't figure out the solution.
I have the following code
scanf("%ld %ld",&n,&m);
for(i=0;i<n;i++)
scanf("%ld",&array[i]);
for(i=0;i<m;i++)
{
fflush(stdin);
//inputting a character 'R' but it is picking '\n' from past buffer
scanf("%c",&query);
//As a result of above problem, it is also acting wierd for same reason
scanf("%ld",&d);
printf("%c %ld",query,d);
printf("\nI=%ld\n",i);
}
Please help me figure out the reason why its happening and what is the solution.
Using scanf with %d (or %ld) only extracts the number from the input stream; it leaves the newline in the stream.
So when you write scanf("%c", it reads that newline.
To fix this (if your intent is that scanf("%c" reads the first character of the next line), you need to flush the input of the previous line. One way to do that is:
int ch; while ( (ch == getchar()) != EOF && ch != '\n' ) { }
Your line fflush(stdin); causes undefined behaviour - don't do that. The fflush function is only for output streams.
Also , it is a really good idea to check the return value of scanf. If it was not what you expected then you may wish to take some action, instead of pretending that a number was entered.
Since you are tired of input issues, I can give you a method that can help to simplify your live.
I can observe that:
You have problems in handling end-of-lines.
Sometimes you need to input numbers and sometimes you need characters or another kind of input. So, you (think that you) are forced to use formatted input.
My advice is that you separate the issue of reading input from the issue of interpreting data entered from input.
The standard C brings only a few functions to handle input/output operations, in the standard header <stdio.h>.
If you are not interested in very sofisticated I/O results, the standard library is enough.
However, the functions of <stdio.h> usually have the effect that input is read one line at the time, which includes the end-of-line character: '\n'.
What you can do, then, it's what follows:
Read a line with fgets(..., stdin) and put the result in a buffer (not so long), used only for this purpose.
Once you have read an entire line, no more issues with end-of-line will bother you.
Then, re-read this line, that it's held in a buffer, and apply to it all the formatted input that you need.
A short example:
#include <stdio.h>
int main(void) {
char buffer[200] = ""; // Initialize array to 0's
long int n, m;
char c;
fgets(buffer, sizeof(buffer), stdin);
sscanf(buffer,"%ld %ld",&n,&m);
// Now you have processed the "integer number" input,
// read input characters again, withou any "flushes" and extrange things:
fgets(buffer, sizeof(buffer), stdin);
sscanf(buffer,"%c", &c);
fgets(buffer, sizeof(buffer), stdin);
// and so on...
}
Thus, every time you need to separate a section of input from a previous one, just do a new line reading with fgets(..., stdin), which stores the input in buffer, and then process the buffer with sscanf(), which applies the format string to the buffer instead of the input itself (in its flesh).
Note: This method can have a little problem: If the string input has more than sizeof(buffer) characters (in the example: 200), the line is not completely read. This situation can be handled by checking if the character before last in buffer is not equal to '\n' nor '\0'. In such a case, you would make automatically some kind of "flushing input" operation (reading and discarding characters till the next end-of-line is found).
My objective is to change the delimiter of scanf to "\n".
I tried using scanf("%[^\n]s",sen); and works fine for single inputs.
But when i put the same line inside a for loop for multiple sentences it gives me garbage values.
Does anyone know why?
Here's my code:
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]s",sen);
printf("%s\n",sen);
}
Consider this (C99) code:
#include <stdio.h>
int main(void)
{
char buffer[256];
while (scanf("%255[^\n]", buffer) == 1)
printf("Found <<%s>>\n", buffer);
int c;
if ((c = getchar()) != EOF)
printf("Failed on character %d (%c)\n", c, c);
return(0);
}
When I run it and type in a string 'absolutely anything with spaces TABTABtabs galore!', it gives me:
Found <<absolutely anything with spaces tabs galore!>>
Failed on character 10 (
)
ASCII (UTF-8) 1010 is newline, of course.
Does this help you understand your problem?
It works in this case (for a single line) but if I want to take multiple lines of input into an array of arrays then it fails. And I don't get how scanf returns a value in your code?
There are reasons why many (most?) experienced C programmers avoid scanf() and fscanf() like the plague; they're too hard to get to work correctly. I'd recommend this alternative, using sscanf(), which does not get the same execration that scanf() and fscanf() do.
#include <stdio.h>
int main(void)
{
char line[256];
char sen[256];
while (fgets(line, sizeof(line), stdin) != 0)
{
if (sscanf(line, "%255[^\n]", sen) != 1)
break;
printf("Found <<%s>>\n", sen);
}
int c;
if ((c = getchar()) != EOF)
printf("Failed on character %d (%c)\n", c, c);
return(0);
}
This reads the line of input (using fgets() which ensures no buffer overflow (pretend that the gets() function, if you've heard of it, melts your computer to a pool of metal and silicon), then uses sscanf() to process that line. This deals with newlines, which are the downfall of the original code.
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]s",sen);
printf("%s\n",sen);
}
Problems:
You do not check whether scanf() succeeded.
You leave the newline in the buffer on the first iteration; the second iteration generates a return value of 0 because the first character to read is newline, which is the character excluded by the scan set.
The gibberish you see is likely the first line of input, repeated. Indeed, if it were not for the bounded loop, it would not wait for you to type anything more; it would spit out the first line over and over again.
Return value from scanf()
The definition of scanf() (from ISO/IEC 9899:1999) is:
§7.19.6.4 The scanf function
Synopsis
#include <stdio.h>
int scanf(const char * restrict format, ...);
Description
2 The scanf function is equivalent to fscanf with the argument stdin interposed
before the arguments to scanf.
Returns
3 The scanf function returns the value of the macro EOF if an input failure occurs before
any conversion. Otherwise, the scanf function returns the number of input items
assigned, which can be fewer than provided for, or even zero, in the event of an early
matching failure.
Note that when the loop in my first program exits, it is because scanf() returned 0, not EOF.
%[^\n] leaves the newline in the buffer. %[^\n]%*c eats the newline character.
In any case, %[^\n] can read any number of characters and cause buffer overflow or worse.
I use the format string %*[^\n]%*c to gobble the remainder of a line of input from a file. For example, one can read a number and discard the remainder of the line by %d%*[^\n]%*c. This is useful if there is a comment or label following the number, or other data that is not needed.
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]s",sen);
printf("%s\n",sen);
getchar();
}
Hope this helps ... actually "\n" remains in stream input buffer... Ee need to flush it out before scanf is invoked again
I know I am late, but I ran into same problem after testing C after a long time.
The problem here is the new line is considered as input for next iteration.
So, here is my solution, use getchar() to discard the newline the input stream:
char s[10][25];
int i;
for(i = 0; i < 10; i++){
printf("Enter string: ");
scanf("%s", s[i]);
getchar();
}
Hope it helps :)
While using scanf("%[^\n]", sen) in a loop, the problem that occurs is that the \n stays within the input buffer and is not flushed. As a result next time, when the same input syntax is used, it reads the \n and considers it as a null input. A simple but effective solution to address this problem is to use:
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]%*c",sen);
printf("%s\n",sen);
}
%*c gets rid of the \n character in the input buffer.
I can't get around this problem. I need the user to type a string then hit enter, then another string. When he/she is done hit enter once more (this last string would only have \n character so I know when to stop).
char * buff = malloc (100);
printf("Type in strings, to finish hit enter\n");
do{
scanf (" %[^\n]",buff);
//do some other stuff with the string
} while(*buff);
printf("You have finished typing strings\n");
This approach I came up with is no use for me, since the [^\n] command is telling the function to read everything but the \n meaning that the \n is kept in the console buffer. If I simply do
while(*buff)
{
scanf ("%s",buff);
}
if I hit enter it does nothing.
Any other approach?
Yeah, scanf is actually looking for characters. What you want is gets (to get a line).
[edit] as pointed out by Daniel Fischer:
gets has (at last) been removed from the language. Even before, the
man page has for a long time said Never use gets()
Looks like my advice was not the best. I guess this means use fgets, as it protects against buffer overrun. Unlike gets, the newline character(s) will also be stored in the string and it is the programmer's responsibility to check for them.
const size_t bufsize = 100;
char buf[bufsize];
while( fgets(buf, bufsize, stdin) != NULL )
{
if( buf[0] == '\n' ) break;
/* Do something with your string... */
}
Besides what paddy pointed out (use gets to get a whole line), the condition
while(*buff);
won't ever be false, unless the user input would be a null character (as in ASCII value 0). The line break character (\n) has an ASCII value of 10, which evaluates to true in conditional statements.
Try this:
while(strlen(*buff) > 0);