Why is my program got into an infinite loop? - c

I want to scan a line until newline is pressed. I'm aware of gets() function, but I wanted to learn it with scanf(). The problem is, that my program falls into an infinite loop, where it scans the input from user and then infinitely prints it out, where it should print once after each scan. Can anybody explain why is it behaving like this?
#include<stdio.h>
int main()
{
char str[100];
while(str[0]!='\0')
{
scanf("%[^\n]",str);
printf("%s\n",str);
}
}

If you insist on using scanf, then change format specifier:
" %[^\n]"
The space in front will skip any previous "dangling" \n
Also you should initialize the str array before checking the contents of it, better yet use a do-while-loop instead .
Something like this should work
char str[100] = {0};
do
{
scanf(" %[^\n]",str);
printf("%s\n",str);
}
while(str[0]!='q');
Personally I prefer to use fgets(...) in combination with sscanf(...)
Also it is good practice to check the return value of scanf, there is a return value for a purpose.
added another while condition, loops until "q" or "quit"

Since %[^\n] does not accept newline, input is not accepted in the second loop.
Probably, this will do what you want.
#include<stdio.h>
int main(void){
char str[100];
while(1== scanf("%99[^\n]%*c",str)){//%*c consumes newline. Also In case of only newline terminates the loop
printf("%s\n",str);
}
}

BLUEPIXY is absolutely correct. The first return from scanf() is leaving the \n in the input buffer. Subsequent scanf() calls will return right away without reading any characters from stdin because scanf() stops reading on a \n. So a loop ensues. One way to avoid the loop is to read the \n from the input after the call to scanf() as shown below:
#include <stdio.h>
int main()
{
char str[100] = {0};
do
{
scanf("%[^\n]",str);
getchar();
printf("%s\n",str);
}while( str[0] != '\0' );
}
You seem to be under some false beliefs regarding how input works. So I'm going to explain below.
You don't need to do this in a loop because scanf() doesn't read and return one character at a time when you specify a string format. The input is buffered by the terminal. When you ask scanf() to return a string, the terminal will only send the input string to scanf() when it a newline is received. When that happens scanf() returns the string without the newline.
You'll need to do extra work to turn off terminal line buffering. The below example code shows how to turn off terminal I/O buffering.
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
int main()
{
struct termios old_tio, new_tio;
unsigned char c;
/* get the terminal settings for stdin */
tcgetattr(STDIN_FILENO,&old_tio);
/* we want to keep the old setting to restore them a the end */
new_tio=old_tio;
/* disable canonical mode (buffered i/o) and local echo */
new_tio.c_lflag &=(~ICANON & ~ECHO);
/* set the new settings immediately */
tcsetattr(STDIN_FILENO,TCSANOW,&new_tio);
do {
c=getchar();
printf("%c ",(char)c);
} while(c!='q');
/* restore the former settings */
tcsetattr(STDIN_FILENO,TCSANOW,&old_tio);
return 0;
}

Related

C : How to stop the loop when getting the end of input from keyboard or file while using scanf one char at a time

void main(void)
{
char character;
do {
scanf("%c", &character);
printf("%c", character);
} while (character != EOF);
}
I'm going to process the input character by character, and I am only allowed to use scanf(). However, the while loop does not stop. Since I may need to process the input with multiple-line strings, it is impossible to add one more condition: character != '\n'.
Can somebody help me with this problem? Thanks!
You have an incorrect expectation. When scanf() encounters the end of the input before either matching an input item or recognizing a matching failure, it returns EOF. Under no circumstance does it modify the value of the datum associated with an input item that has not been matched.
You are ignoring scanf's return value, which is generally a perilous thing to do, and instead testing whether scanf records EOF in the object associated with the input item, which, in your particular case, it must not ever do.
For a start it should be int main...
Also you need to check the return value from scanf - please read the manual page.
Taking this into account, the code should look like this
#include <stdlib.h>
#include <stdio.h>
int main()
{
char character;
while (scanf("%c", &character) == 1) {
if (character != '\n) {
printf("%c", character)
}
}
return EXIT_SUCCESS;
}

getchar() won't keep the console open

I'm writing this code to compare two strings. The code works, my only problem being keeping the console open after it finishes. Normally, getchar() works like a charm, but in this case it is simply ineffective. I think it's due to the if-else functions. How do I keep the console open?
#include <stdio.h>
#include <string.h>
#define SIZE 50
int main (int argc , char** argv) {
char isim[SIZE];
printf("Adinizi yazin:\n");
scanf("%s", isim);
if(strcmp(isim, "Cihan") == 0)
printf("Hosgeldiniz!\n");
else
printf("Cihan degilsiniz. Lutfen programi terk edin.\n");
getchar();
return 0;
}
Just use two getchar(), one after the other. scanf() doesn't remove the newline character from the input buffer, so first getchar() "eats" that newline. The second getchar() to wait for next input, which will keep the console open.
From scanf() page in cplusplus.com:
the function will read and ignore any whitespace characters encountered before the next non-whitespace character (whitespace characters include spaces, newline and tab characters -- see isspace).
Emphasis by me.
The input is sent to the program after a newline, but
scanf("%s", &isim );
leaves the newline in the input buffer, since the %s format stops when the first whitespace character is encountered after some non-whitespace. getchar() then returns that newline immediately and doesn't wait.
To make your code work, try something like this
scanf("%s", &isim );
while( getchar() != '\n' ){
/* flush to end of input line */
}
#include <stdio.h>
#include <string.h>
#include <conio.h>
#define SIZE 50
int main (int argc , char** argv) {
char isim[SIZE];
printf("Adinizi yazin:\n");
scanf("%s", &isim);
if(strcmp(isim, "Cihan") == 0)
printf("Hosgeldiniz!\n");
else
printf("Cihan degilsiniz. Lutfen programi terk edin.\n");
getch();
return 0;
}
You can use statement: getch(); in conio.h header. getch() not read character in buffer, it read character directly from keyboard. So console will open if you not yet input. getchar() read character from buffer,a newline in your input buffer after scanf() not be read and save in buffer. Then getchar() will read newline and statement stop, console will close.

Best way to read stdin that may include newline?

I have to write a program in C that handles the newline as part of a string. I need a way of handling the newline char such that if it is encountered, it doesn't necessarily terminate the input. So far I've been using fgets() but that stops as soon as it reaches a '\n' char. Is there a good function for processing the input from the console that doesn't necessarily end at the newline character?
To clarify:
I need a method that doesn't terminate at the newline char because in this particular exercise when the newline char is encountered it's replaced with a space char.
fgets gets a line from a stream. A line is defined as ending with a newline, end-of-file or error, so you don't want that.
You probably want to use fgetc. Here's a code example of a c program file fgetc.c
#include <stdio.h>
int main (void) {
int c;
while ((c = fgetc(stdin)) != EOF) fputc(c, stdout);
}
compile like this:
cc fgetc.c -o fgetc
use like this (notice the newline character '\n'):
echo 'Hello, thar!\nOh, hai!' | ./fgetc
or like this:
cat fgetc.c | ./fgetc
Read the fgetc function manual to find out more: man fgetc
If I understand your question correctly you want to read from the standard input until user has finished typing ( which ain't be a newline of course ). This can be done by setting a flag like EOF while getting input. One way which I came out with is this:
#include <stdio.h>
int main(void)
{
char ch;
char str[100];
int i = 0;
setbuf (stdout,NULL);
while ( (ch = getchar()) != EOF)// user can input until the EOF which he or she enters to mark the end of his/her typing or more appropriately input.
{
str[i] = ch;// you can store all the input character by character in a char array
i++;
}
printf ("%s",str);// then you can print it at last as a whole
return 0;
}
BEGINNER's NOTE- EOF can vary from system to system so check it and enter the proper EOF for your system.
If you are simply reading blocks of information without the need for scanf(), then fread() may be what you are after. But on consoles you can read to the \n, notice the \n, then continue reading more if you decide that \n is not for you.
scanf works when used as directed. Specifically, it treats \n as white space.
Depending on how your application is coded (i.e. how buffers are defined), a \n prompts the system to flush the buffer and feed data into scanf. This should occur as a default without you having to do anything.
So the real question is, what kind of data or characters do you need from the console? In some cases scanf will remove white space and NOT pass blanks, tabs, new lines, into your program. However, scanf can be coded to NOT do this!
Define how data should be entered and I can guide you on how to code scanf.

Changing the scanf() delimiter

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.

peek at input buffer, and flush extra characters in C

If I want to receive a one character input in C, how would I check to see if extra characters were sent, and if so, how would I clear that?
Is there a function which acts like getc(stdin), but which doesn't prompt the user to enter a character, so I can just put while(getc(stdin)!=EOF);? Or a function to peek at the next character in the buffer, and if it doesn't return NULL (or whatever would be there), I could call a(nother) function which flushes stdin?
Edit
So right now, scanf seems to be doing the trick but is there a way to get it to read the whole string, up until the newline? Rather than to the nearest whitespace? I know I can just put "%s %s %s" or whatever into the format string but can I handle an arbitrary number of spaces?
You cannot flush the input stream. You will be invoking undefined behavior if you do. Your best bet is to do:
int main() {
int c = getchar();
while (getchar() != EOF);
return 0;
}
To use scanf magic:
#include <stdio.h>
#include <stdlib.h>
#define str(s) #s
#define xstr(s) str(s)
#define BUFSZ 256
int main() {
char buf[ BUFSZ + 1 ];
int rc = scanf("%" xstr(BUFSZ) "[^\n]%*[^\n]", buf);
if (!feof(stdin)) {
getchar();
}
while (rc == 1) {
printf("Your string is: %s\n", array);
fflush(stdout);
rc = scanf("%" xstr(LENGTH) "[^\n]%*[^\n]", array);
if (!feof(stdin)) {
getchar();
}
}
return 0;
}
You can use getline to read a whole line of input.
Alternatively (in response to your original question), you can call select or poll on stdin to see if there are additional characters to be read.
I had a similar problem today, and I found a way that seems to work. I don't know the details of your situation, so I don't know if it will work for you or not.
I'm writing a routine that needs to get a single character from the keyboard, and it needs to be one of three specific keystrokes (a '1', a '2', or a '3'). If it's not one of those, the program needs to send and error message and loop back for another try.
The problem is that in addition to the character I enter being returned by getchar(), the 'Enter' keystroke (which sends the keystroke to the program) is saved in an input buffer. That (non-printing) newline-character is then returned by the getchar() facility in the error-correction loop, resulting further in a second error message (since the newline-character is not either a '1', a '2', nor a '3'.)
The issue is further complicated because I sometimes get ahead of myself and instead of entering a single character, I'll enter the filename that one of these options will request. Then I have a whole string of unwanted characters in the buffer, resulting in a long list of error messages scrolling down the screen.
Not cool.
What seems to have fixed it, though, is the following:
c = getchar(); // get first char in line
while(getchar() != '\n') ; // discard rest of buffer
The first line is the one that actually uses the character I enter. The second line disposes of whatever residue remains in the input buffer. It simply creates a loop that pulls a character at a time from the input buffer. There's no action specified to take place while the statement is looping. It simply reads a character and, if it's not a newline, goes back for the next. When it finds a newline, the loop ends and it goes on to the next order of business in the program.
We can make a function to clear the keyboard buffer, like this:
#include <stdio.h>
void clear_buffer(){
char b;
//this loop take character by character in the keyboard buffer using
//getchar() function, it stop when the variable "b" was
//enter key or EOF.
while (((b = getchar()) != '\n') && (b != EOF));
}
int main()
{
char input;
//get the input. supposed to be one char!
scanf("%c", &input);
//call the clearing function that clear the buffer of the keyboard
clear_buffer();
printf("%c\n",input); //print out the first character input
// to make sure that our function work fine, we have to get the
// input into the "input" char variable one more time
scanf("%c", &input);
clear_buffer();
printf("%c\n",input);
return 0;
}
Use a read that will take a lot of characters (more than 1, maybe 256), and see how many are actually returned. If you get more than one, you know; if you only get one, that's all there were available.
You don't mention platform, and this gets quite tricky quite rapidly. For example, on Unix (Linux), the normal mechanism will return a line of data - probably the one character you were after and a newline. Or maybe you persuade your user to type ^D (default) to send the preceding character. Or maybe you use control functions to put the terminal into raw mode (like programs such as vi and emacs do).
On Windows, I'm not so sure -- I think there is a getch() function that does what you need.
Why don't you use scanf instead of getc, by using scanf u can get the whole string.

Resources