Thread: Why doesn't fgets() read my input?

  1. #1
    Registered User
    Join Date
    Dec 2008
    Posts
    19

    Question Why doesn't fgets() read my input?

    Hello there!
    I have been strolling about the threads, looking for similar problems, but haven't found an exact solution... everyone keeps telling, that fgets() should be used for getting user input, instead fof gets(). Cool, let's give it a try. This sample program I copied from a website works just fine:

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
      char str[80];
      int i;
    
      printf("Enter a string: ");
      fgets(str, 10, stdin);
    
      /* remove newline, if present */
      i = strlen(str)-1;
      if( str[ i ] == '\n') 
          str[i] = '\0';
    
      printf("This is your string: %s", str);
    
      return 0;
    }
    Yet, my own program is not willing to take any user input...it finishes, before I'd have a chance to type anything!

    Code:
    #include <stdio.h>
    
    int main(){
    	/*********************************************************************/
    	char letter;
    	
    	printf("Gimme a letter!");
    	scanf("%c",&letter);
    
    	int num;
    	if(letter=='a'||letter=='b'||letter=='c')
    		num=2;
    	else if(letter=='d'||letter=='e'||letter=='f')
    		num=3;
    	else if(letter=='g'||letter=='h'||letter=='i')
    		num=4;
    	else if(letter=='j'||letter=='k'||letter=='l')
    		num=5;
    	else if(letter=='m'||letter=='n'||letter=='o')
    		num=6;
    	else if(letter=='p'||letter=='q'||letter=='r'||letter=='s')
    		num=7;
    	else if(letter=='t'||letter=='u'||letter=='v')
    		num=8;
    	else if(letter=='w'||letter=='x'||letter=='y'||letter=='z')
    		num=9;
    	else
    		printf("Why have not given me a letter?!\n");
    
    	printf("The letter is now encoded: %d\n",num);
    	/**********************************************************************/
    	printf("Gimme a word of 15 chars!");
    	char word[15];
    	fgets(word,16,stdin);
    	printf("%s",word);
    }
    I've noticed, that if I comment out the first block and only the second block is left (starting after the second comment line) then fgets() function properly... waits for input and printf() gives back the string. Could anyone explain this to me?
    Last edited by laczfinador; 05-12-2009 at 07:02 AM.

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    scanf("%c"..) leaves a "newline" in the input buffer, so you get an empty line from fgets(), since it reads everything up to the next newline. Add a space after the format of scanf, e.g. scanf("%c "...) and any newlines and such will be consumed by scanf... It is just one of those strange things.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Dec 2008
    Posts
    19
    Hey there!

    Unfortunatelly, if I add a space to the scanf format specifier, it causes another malfunctioning...after I altered the code, according to your suggestion, the scanf("%c ",letter) function did not read one letter only, but was awaiting for further input... however, after entering more characters, the "second" input was succesfully "caught" by fgets(), but the program totally skipped the printf() part, where the user is prompted to enter a word! Hm...

  4. #4
    Registered User
    Join Date
    Oct 2008
    Posts
    110
    try:

    Code:
    fgets(word,15,stdin);
    the first argument of fgets is the string which you want the read data to be stored, which is "word". If you haven't declared a string "szo" yet in your code I'm surprised it compiled. Also you should use the array size of your string as the second argument, to prevent run-time errors.
    PHI is one 'H' of alot more interesting than PI!

  5. #5
    Registered User
    Join Date
    Dec 2008
    Posts
    19
    Yes, well the code I posted here is "translated" to english, for better ungerstanding, and I seemingly forgot to change that "szo" to "word", but in the actual code, it is all "szo"...but thanks for noticing, I'll have to correct that...

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
    	char word[15];
    	fgets(word,16,stdin);
    You should NOT lie to fgets() as to the length of your buffer. It's best to use sizeof() rather than a constant, that way, if you change the variable itself, the fgets() size will automatically follow. Also, if you actually want a 15 character word, your buffer should probably be [at least] 17 long, since that gives you enough length to store the 15 characters of the word, a newline and the terminating zero.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Quote Originally Posted by matsp
    Also, if you actually want a 15 character word, your buffer should probably be [at least] 17 long, since that gives you enough length to store the 15 characters of the word, a newline and the terminating zero.
    15+1=16 characters would be enough since the newline need not be stored in the buffer. It is because of this edge case that I prefer to use strpos() rather than strlen() to implement the removal of the newline from the buffer.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by laserlight View Post
    15+1=16 characters would be enough since the newline need not be stored in the buffer. It is because of this edge case that I prefer to use strpos() rather than strlen() to implement the removal of the newline from the buffer.
    Yes, but that leaves the newline in the input buffer, which CAN lead to difficulties elsewhere - so we then ALSO need to write code to find out if there is a newline in the string or not, and if not clean up the input buffer - which may be a good idea to make the code more robust, but if we want somewhat more simple solution then it's easier to just have enough space for the newline...

    [Of course, the easiest solution is to majorly oversize the buffer, remove the newline and then check the length - but then it doesn't solve the "fell asleep with finger(s) on the keyboard" type input.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Quote Originally Posted by matsp
    which may be a good idea to make the code more robust, but if we want somewhat more simple solution then it's easier to just have enough space for the newline...
    I think that it would be easier to use gets() so that we do not have to check for the newline. After all, if we are going to assume that the user will enter input of no more than 16 characters including the newline, gets() is perfectly safe
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by laserlight View Post
    I think that it would be easier to use gets() so that we do not have to check for the newline. After all, if we are going to assume that the user will enter input of no more than 16 characters including the newline, gets() is perfectly safe
    [sarcasm]Good suggestion [/sarcasm]

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Quote Originally Posted by matsp
    Good suggestion
    Thank you

    On a more serious note for the benefit of laczfinador: my point is that you should have robust input handling, which is precisely why fgets() was suggested to you as a replacement for gets(). matsp's idea of allocating one more character for the newline works in the sense that you can simply replace the last character in the string with a null character. But this does not mean that the newline will not be left in the input buffer, since the user could enter one more character (or even more, leaving other characters in the input buffer as well).

    If you have robust input handling, you no longer need to allocate one extra character for the newline. With strpos(), it is just as easy to replace the newline with a null character, if the newline was placed in the string.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. fgets not getting user input
    By golgotha in forum C Programming
    Replies: 4
    Last Post: 03-14-2009, 11:27 AM
  2. Problem using sscanf fgets and overflow checking
    By jou00jou in forum C Programming
    Replies: 5
    Last Post: 02-18-2008, 06:42 AM
  3. Problem with Printing message
    By robert_sun in forum C Programming
    Replies: 2
    Last Post: 05-16-2004, 02:09 PM
  4. Replies: 1
    Last Post: 05-30-2003, 02:31 AM
  5. Serial Communications in C
    By ExDigit in forum Windows Programming
    Replies: 7
    Last Post: 01-09-2002, 10:52 AM

Tags for this Thread