Results 1 to 11 of 11

Thread: [RESOLVED] ANSI-C and reading use input from stdin

  1. #1

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,682

    Resolved [RESOLVED] ANSI-C and reading use input from stdin

    (This is about C, not C++...)

    I'm just fiddling with reading some simple user input. The idea is that the user enters a string of less than 20 chars long and then later on enters their age as an integer.

    A problem arises if the user enters "asdflajsdkjflakjsdlflajsldjlfajlkdlkjfasdfkjjfaiou" and hits enter. Only the first 19 chars are read (which is good), but the rest is left on the stdin stream. Thus when the age is requested, the remaining text is read straight away.

    My Question:
    Is there a built-in function that will let me clear out whats remaining in stdin? I have thought of just using a loop to get eat all the remaining queued-up bytes, but that seems a bit messy to me for some reason.

    I put 2 comments in th places where I need to clear out the input...

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(int argc, char *argv[])
    {
    	char firstName[20];
    	int end = 0;
    	int age = -1;
    
    	printf("Please enter your first name\n: ");
    	fgets(firstName, sizeof(firstName), stdin);	//read the user's name from stdin
    	
    	/*flush input here?*/
    
    	end = strlen(firstName) - 1;
    
    	if(firstName[end]=='\n')
    		firstName[end] = '\0'; //kill the newline if there is one
    
    	printf("Hello %s, enter your age: ", firstName);
    	scanf("%d", &age);
    
    	/*flush input again here?*/
    
    	if(age < 18)
    		printf("You are a mere pipsqueak!");
    	else if(age < 25)
    		printf("You are a noob!");
    	else if(age < 30)
    		printf("You are a budding expert!");
    	else if(age < 50)
    		printf("You are an old fart!");
    	else if(age < 75)
    		printf("You are a grizzled ancient!");
    
    	printf("\n");
    	
    	return 0;
    }
    I don't live here any more.

  2. #2
    PowerPoster sunburnt's Avatar
    Join Date
    Feb 2001
    Location
    Boulder, Colorado
    Posts
    1,403

    Re: ANSI-C and reading use input from stdin

    I think the function you're looking for is (from stdio.h)
    Code:
    fflush(stdin);
    Let me know if it works.
    Every passing hour brings the Solar System forty-three thousand miles closer to Globular Cluster M13 in Hercules -- and still there are some misfits who insist that there is no such thing as progress.

  3. #3

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,682

    Re: ANSI-C and reading use input from stdin

    Sunburnt, yeah I did try that earlier (I saw it mentioned in the man pages for "stdio.h") however GCC said it was not defined. Further investigation suggested it was not available under linux, neither is fpurge() apparently.
    I don't live here any more.

  4. #4
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594

    Re: ANSI-C and reading use input from stdin

    fflush(stdin) works on Microsoft compilers, but is heavily frowned upon because, as far as the standard is concerned, you cannot flush input streams.

    No, a loop eating up all remaining input is exactly the way to go. Best pack it into a function.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  5. #5

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,682

    Re: ANSI-C and reading use input from stdin

    Do you know what condition I should look for in order to stop 'eating'?

    Checking getchar() against: NULL, EOF and '\n' are all apparently incorrect and give varying results.

    I'm surprised that something like this isn't mentioned in the man pages.

    Hmm, maybe if I use putchar to shove a newline back onto stdin and then eat until i find it? That sounds even dirtyer, yuck.
    I don't live here any more.

  6. #6
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594

    Re: ANSI-C and reading use input from stdin

    Check against both EOF and '\n', that should work. But do this only if the string fgets read does not end in '\n', otherwise there'll be no '\n' and getchar() will block.
    Of course, if it's EOF, you might as well terminate.
    And no, using putchar() won't work.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  7. #7

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,682

    Re: ANSI-C and reading use input from stdin

    Yes you are right, getchar() is blocking, and does so until I hit enter a second time.
    I don't live here any more.

  8. #8

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,682

    Re: ANSI-C and reading use input from stdin

    RESOLVED (kind of)

    Ok, I ended up writing a new function that does what I want.

    awgets(char*, int) is similar to fgets() except that awgets doesn't keep the newline char, and also it flushes the stin stream after reading one line of input. This is useful for reading a string like "i like cheese" into a char array.

    The integer you supply is ideally the length to the char array you are reading into. If you supply 20, then awgets will read no more than 19 characters and it will then add a null terminator in the last element of the destination array. Thus avoiding buffer overruns.

    For example if you call:
    Code:
    char text[20];
    ...
    awgets(text, 20);
    and then the user enters:
    Hello everyone, I'm Fred!

    ...then the text array will now contain "Hello everyone, I'm\0".
    The remaining " Fred\n" is discarded and removed from stdin.

    This stops the user's input for one prompt overflowing and affecting future prompts.




    Quote Originally Posted by awinput.h
    #pragma once

    /****** Prototypes ******************************/
    int awgets(char *dest, int size);

    /****** Definitions ******************************/
    int awgets(char *dest, int size)
    {
    /*
    This function allows you to read a string of maximum length: <size-1>.
    If the user types more than that number of chars then the rest
    (up to a newline character, which is discarded) is removed
    from stdin so that future reads are not affected.

    Returns the number of characters read from stdin
    */

    int i = 0;
    char ch = 'a';
    char bail = 0;

    size--; //leave a char free for the null terminator

    while(i < size)
    {
    ch = fgetc(stdin);
    if(ch == EOF || ch == '\n') //handle the end of the stream
    {
    bail = 1;
    break;
    }

    *dest++ = ch; //store the char that was read
    i++; //count the number of chars read so far
    }

    *dest = '\0'; //set the null terminator

    //we've either hit the end of the stream or a newline OR we've
    //read enough characters, so empty the remaining data on stdin...
    if(!bail)
    while( (ch = fgetc(stdin)) != EOF && ch != '\n' );

    return i;
    }
    I don't live here any more.

  9. #9
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594

    Re: [RESOLVED] ANSI-C and reading use input from stdin

    The function should somehow report that it truncated the input.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  10. #10

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,682

    Re: [RESOLVED] ANSI-C and reading use input from stdin

    Even though the data that was lost is unrecoverable?

    Ok, so something like...

    Code:
    int awgets(char *dest, int size, char *truncated)
    {...}
    setting that char* to 1 if some data was lost?

    Basically like an "out" parameter in C#.
    I don't live here any more.

  11. #11
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594

    Re: [RESOLVED] ANSI-C and reading use input from stdin

    Yes, even then. You never know when you need the info.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width