Thread: problems with fgets

  1. #1
    Registered User
    Join Date
    Nov 2010
    Posts
    122

    problems with fgets

    Hello people.
    I'm getting problems with fgets.
    Code:
    while (run) {
    		printMenu();
    		scanf("%d*c", &opt);
    
    		switch (opt) {
    		case 1:
    			printf("Create a new component\n");
    			do {
    				printf("Serial number?\n");
    				scanf("%s*c", c_serial_number);
    				validStringSize = verifyStrLengh(c_serial_number, STR_SERIAL);
    			} while ((indexof(c, n_elems, c_serial_number) != -1)
    					|| (validStringSize != -1));
    
    			do {
    				printf("Components' name\n");
    				fflush(stdin);
    				scanf("%s*c", c_name);
    				validStringSize = verifyStrLengh(c_name, STR_NAME);
    			} while (validStringSize != -1);
    
    
    			do {
    				//fflush(stdin);
    				printf("Components description\n");
    				//fflush(stdin);
    				fgets(c_description, STR_DESCRIPTION, stdin);
    			   // strip_newline( c_description, STR_DESCRIPTION );
    				//scanf("%s*c",c_description);
    		//		scanf("%*c");
    
    				validStringSize
    						= verifyStrLengh(c_description, STR_DESCRIPTION);
    			} while (validStringSize != -1);
    
    			do {//fflush(stdin);
    				printf("Price\n");
    				fflush(stdin);
    				validValue = scanf("%f", &price);
    			//	scanf("%*c");
    				if (validValue == 0) {
    					printf(
    							"You inserted a invalid character, use numbers please\n");
    
    				}
    				if ((validValue == 1) && (price <= 0)) {
    					printf("Insert a positive value to price, please\n");
    				}
    
    			} while ((validValue != 1) || (price <= 0));
    
    			if (insertComponent(c, &n_elems, c_serial_number, price, c_name,
    					c_description)) {
    				printf("Component successfully inserted\n");
    			} else {
    				printErrorMessage("Insertion unsuccessful\n");
    			}
    		//	scanf("%*c");
    			break;
    I'm trying read from stdin with fgets. Without sucess.
    Or "component's description" jumps withou get the value or get the value and enters on price infite cycle.
    strip_new line is a function that I read in "web" it works. (but It don't work)
    I need help, I've got to deliverd this "job" soon
    Last edited by marcoesteves; 01-20-2011 at 05:11 AM.

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    The obvious comments are.

    1) Never use fflush(stdin). The result of that is undefined (and it is certainly not guaranteed to discard pending input, which is presumably what you are attempting to use it for).

    2) Never mix usage of fgets(...., stdin) and scanf(). Use one or the other consistently, not one then the other. Mixing them - unless you and the user entering input are both very careful - is an effective way to get uncontrolled behaviour (eg looping on some input that causes a repeated failure to read). Use fgets() to read the input and (if you like) sscanf() to interpret the input after reading it.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  3. #3
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    1) fflush(stdin) doesn't work, for the same reason flushing your kitchen faucet won't work - it's not the toilet, and is an input stream, not an output stream.

    2) I don't see anything wrong with your use of fgets(), but obviously the char array must be properly sized, including the end of string char (and probably the newline char as well).

    code to remove the newline char, is generally:
    Code:
    len = strlen(charArrayName);
    if(charArrayName[len-1]=='\n')
      charArrayName[len-1]='\0';
    To stop the "jumping" over your fgets(), add this:
    getchar(); //pull one newline off the input buffer

    after each scanf() line of code. Obviously, fflush(stdin) isn't working, and *c in scanf() isn't pulling off the newline char as you'd like, either. That's what's causing the "jumping".

    Give that a shot.

  4. #4
    Registered User
    Join Date
    Nov 2010
    Posts
    122
    Thanks for the tips.

    Just to make clear.

    Your advice is use fgets to get strings and sscanf to get the float value of price?

  5. #5
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Yes, sscanf() and fgets make a lovely couple dancing together.

  6. #6
    Registered User
    Join Date
    Nov 2010
    Posts
    122
    Quote Originally Posted by Adak View Post
    1) fflush(stdin) doesn't work, for the same reason flushing your kitchen faucet won't work - it's not the toilet, and is an input stream, not an output stream.

    2) I don't see anything wrong with your use of fgets(), but obviously the char array must be properly sized, including the end of string char (and probably the newline char as well).

    code to remove the newline char, is generally:
    Code:
    len = strlen(charArrayName);
    if(charArrayName[len-1]=='\n')
      charArrayName[len-1]='\0';
    To stop the "jumping" over your fgets(), add this:
    getchar(); //pull one newline off the input buffer

    after each scanf() line of code. Obviously, fflush(stdin) isn't working, and *c in scanf() isn't pulling off the newline char as you'd like, either. That's what's causing the "jumping".



    Give that a shot.
    So, remove all fflush.
    Create a dump_line function and call it after fgets?

  7. #7
    Registered User
    Join Date
    Nov 2010
    Posts
    122
    Ok. I'll try a mix of the advices to get a nice solution.

    My program is full funtional. But the "basic things" don't work. This is make me mad

  8. #8
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    No, fgets() is good - it never leaves a mess behind on the input buffer -- as long as the char array it's feeding into, has enough room for the newline char, and the end of string char.

    scanf() is entirely different - it always tends to leave a newline char behind, leaving "dirty input" for whatever input follows it.

    I have almost become anal about adding a getchar() after every scanf(), just for that reason. Once you really understand scanf(), you know when it needs it, and when it won't, but even so, it is just a cranky witch that you're better off to avoid.

    Using fgets() and then using sscanf() is a better way to go, for sure, but books and teachers always seem to go for scanf() - taking the easy route, even if it's a poor choice in RL coding.
    Last edited by Adak; 01-20-2011 at 05:48 AM.

  9. #9
    Registered User
    Join Date
    Nov 2010
    Posts
    122
    Or I don't understand or something is missing.
    I change my code to this,
    Code:
    printf("Create a new component\n");
    			do {
    				printf("Serial number?\n");
    
    				fgets(c_description, STR_SERIAL, stdin);
    				getchar();
    				validStringSize = verifyStrLengh(c_serial_number, STR_SERIAL);
    			} while ((indexof(c, n_elems, c_serial_number) != -1)
    					|| (validStringSize != -1));
    
    			do {
    				printf("Components' name\n");
    		
    				fgets(c_description, STR_NAME, stdin);
    				getchar();
    				validStringSize = verifyStrLengh(c_name, STR_NAME);
    			} while (validStringSize != -1);
    
    
    			do {
    				printf("Components description\n");
    	
    				fgets(c_description, STR_DESCRIPTION, stdin);
    				getchar();
    	
    
    				validStringSize
    						= verifyStrLengh(c_description, STR_DESCRIPTION);
    			} while (validStringSize != -1);
    
    			do {
    				printf("Price\n");
    
    				validValue=sscanf(stdin,"%f",&price);
    				
    
    				if (validValue == 0) {
    					printf(
    							"You inserted a invalid character, use numbers please\n");
    
    				}
    				if ((validValue == 1) && (price <= 0)) {
    					printf("Insert a positive value to price, please\n");
    				}
    
    			} while ((validValue != 1) || (price <= 0));
    
    			if (insertComponent(c, &n_elems, c_serial_number, price, c_name,
    					c_description)) {
    				printf("Component successfully inserted\n");
    			} else {
    				printErrorMessage("Insertion unsuccessful\n");
    			}
    			getchar();//scanf("%*c");
    			break;
    and cycle infinite in price.

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    You can probably remove all the getchar() calls as well, if you're using fgets()

    > validValue=sscanf(stdin,"%f",&price);
    Use sscanf() on a string, not a stream.
    This should have generated compiler warnings - heed them!


    > fgets(c_description, STR_SERIAL, stdin);
    Typically, you should have
    Code:
    char buff[BUFSIZ];  // BUFSIZ is in stdio.h, and is at least 256
    fgets( buff, sizeof buff, stdin );  // read line
    // here is where you validate the input for say length, content etc
    strcpy(c_description, buff );  // finally move input to where you really need it.
    If you read directly into where you want the result (especially where you've measured the length precisely), then any extra input from the user will generally mess up the future input.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    Nov 2010
    Posts
    122
    Doesn't work If write a bigger string then STR_SERIAL, program don't stop

    Code:
    		case 1:
    			printf("Create a new component\n");
    			do {
    				printf("Serial number?\n");
    		
    				fgets(buff,sizeof buff,stdin);
    		
    				getchar();
    				validStringSize = verifyStrLengh(buff, STR_SERIAL);
    				if(validStringSize) {strcpy(c_serial_number,buff);}
    			} while ((indexof(c, n_elems, c_serial_number) != -1)
    					|| (validStringSize != -1));
    without getchar(); jumps.
    and verifyStrLengh is defined
    Code:
    int verifyStrLengh(char *str, int max_size) {
    	int excedeed = -1;
    	int aux;
    	aux = strlen(str);
    	if (aux > max_size) {
    		excedeed = 1;
    		printf("Max string size is %d, insert again please\n", max_size);
    	}
    	return excedeed;
    }

  12. #12
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Code:
    validValue=sscanf(stdin,"%f",&price);
    This doesn't work, since sscanf() uses what's in the buffer (stdin in this case), AT THAT MOMENT.

    Which is nothing.

    Stick with the good combo:
    Code:
    
    printf("Enter the price, in digits: ");
    fgets(c_description, STR_DESCRIPTION, stdin);
    sscanf(c_description, "%f", &price);
    
    //etc.
    Since you're giving fgets() the base address of c_description (which is it's name), the first part of the c_description will be over-written by the price data.

    So, you need to either:

    1) handle the data in c_description before you use fgets() again, or
    2) create some other char arrays, just for price, etc.

    With fgets(), you don't need any getchar() afterward, to help clean the input stream. It will confuse the user since the getchar() will wait for something to be in the input stream (it is buffered).

    It's either: scanf() with getchar() afterward, or fgets() with no getchar() afterward. Not both.

    Try and keep your string handling as simple, and straight forward (easy to understand), as possible. And remember, that only char's with the end of string char on the end ('\0'), are strings. Char's without the end of string marker char, are just a bunch of char's - not a string.

    Sometimes, a bunch of char's is just what you want for a program. Most times, it is definitely not what you want, however.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Most Common problems in C
    By Bayint Naung in forum C Programming
    Replies: 18
    Last Post: 06-02-2010, 08:20 PM
  2. Why doesn't fgets() read my input?
    By laczfinador in forum C Programming
    Replies: 10
    Last Post: 05-13-2009, 04:20 AM
  3. Program crashing at fgets() - any ideas why?
    By avi2886 in forum C Programming
    Replies: 4
    Last Post: 03-06-2009, 09:24 PM
  4. No clue how to make a code to solve problems!
    By ctnzn in forum C Programming
    Replies: 8
    Last Post: 10-16-2008, 02:59 AM
  5. simple shell (c), fgets problem
    By razza in forum Linux Programming
    Replies: 6
    Last Post: 05-26-2002, 10:44 PM

Tags for this Thread