Thread: A few questions...

  1. #1
    Registered User
    Join Date
    May 2003
    Posts
    49

    A few questions...

    I'm having trouble making fail-proof programs with menus and input and such. There are just some things that I've tried to learn and figure out but can't. I figure I should learn what these things mean and do in order to become a better programmer. So, I have a few questions regarding the problems I'm having:

    1) My biggest problem seems to be newlines. I can't figure out how to properly skip over them. So this brings up my question; what is code like this saying:

    Code:
    while ((ch = getchar()) != '\n')
    {
    ......
    }
    In non-code terms, is it saying "If a newline character is in the user input, ignore it and execute everything inside the while loop", or is it saying "If a newline character is in the input, do everything inside of the while loop (because a newline character was encountered)"

    2) My programming book uses this code as a function to get the first character of input and skip the rest. For example, if "astral" was typed in, it would only get the "a" and skip the rest of the word. How does it work?:

    Code:
    get_first()
    {
    	int ch; 
    
    	ch = getchar();
    	while (getchar() != '\n')
    		continue;
    	return ch;
    }
    Now what I don't understand about this code is "getchar() != '\n'". I don't understand why the getchar() function is being used and how the function works by using it here. I need this to be explained in an easy-to-understand manner. This one really confuses me, and my book definitely doesn't explain it well.


    Here is the program I've been trying to make. The goal of the program is to get two integers from the user, and then the user chooses either "a" or "b" to add the two values or subtract one from the other.

    3) The program is then supposed to start over once you've added or subtracted, asking for two integers again, but it does not do this and simply starts over at the part where it asks if you want to add or subtract. How can I fix this?:

    Code:
    #include <stdio.h>
    int add(int, int);
    int subtract(int, int);
    char get_choice();
    int get_int();
    char newline();
    
    main()
    {
    	int n, m;
    	char ch;
    
    	n = get_int();
    	m = get_int();
    	                                         //15
    	while ((ch = get_choice()) != 'q')
    	{
    	switch(ch)
    	{
    	case 'a' :
    		add(n, m);
    		break;
    	case 'b' :
    		sub(n, m);
    		break;                //25
    	default :
    		printf("That is invalid. Try again.\n");
    	}
    	}
    
    	return 0;
    
    }
    
    int get_int()                 //35
    {
    	int num;
    	char ch;
    
    	printf("Please enter an integer:\n");
    	scanf("%d", &num);
    	return num;
    }
    
    char get_choice()
    {
    	char ch;                  
    		
    	printf("Please choose either of the following actions:\n");    
    	printf("a. add      s. subtract\n");
    	ch = newline();
    	while (ch < 'a' || ch > 'b')
    	{ 
    		printf("Invalid answer. Please choose a or s:\n");
    		ch = newline();                                             //55
    	}
    	return ch;
    }
    
    char newline()
    {
    	char c; 
    	
    	c = getchar();
    	while (getchar() != '\n')             //65
    		continue;
    	return c;
    }
    
    int add(num1, num2)                       
    {
    	int total;
    
    	total = num1 + num2;
    	printf("%d + %d = %d\n", num1, num2, total);       //75
    
    }
    
    int sub(num1, num2)
    {
    	int total;
    
    	total = num1 - num2;
    	printf("%d - %d = %d\n", num1, num2, total);
    
    }
    There's probably a lot wrong with this code, and I know it's definitely not fail-proof, but I want to fix the mentioned problems first. So, how do I make the whole program start over once the two variables have been added or subtracted (i.e. get two new integers)?

  2. #2
    Registered User Dohojar's Avatar
    Join Date
    Feb 2002
    Posts
    115
    Code:
    while ((ch = getchar()) != '\n')
    {
    ......
    }
    Ok the first thing this loop will do is call the getchar() function. getchar() will get a character from stdin. Next the character returned from getchar() is assigned to ch. ch is then compaired to '\n'. If ch is not a '\n' then the loop will continue. What the loop is saying is: loop while ch is not equal to '\n'.
    Hope this helps explain it a bit better
    Dohojar Moajbuj
    Time is the greatest teacher, too bad it kills all its students

  3. #3
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    >what is code like this saying:
    Code:
    while ((ch = getchar()) != '\n')
    {
    ......
    }
    The ch = getchar() means "read one character from the stdin and assign this value to the int ch". Since this expression is parenthesized, it evaluates ch and compares it to the newline character, "if the character just read from the stdin was not a newline, perform the statements enclosed in braces". Or, "if the character just read from the stdin was a newline, break out of the while loop.

    >How does it work?
    Code:
    get_first()
    {
    	int ch; 
    	/* Read a character from the stdin, assign its value to 'ch'. */
    	ch = getchar(); 
    	/*
    	 * Read a character from the stdin. If it is a newline, break out of the loop.
    	 * Otherwise, discard it value (don't assign it to anything).
    	 */
    	while (getchar() != '\n')
    		continue;
    	return ch;
    }
    [edit]
    >3) The program is then supposed to start over once you've added or subtracted, asking for two integers again, but it does not do this and simply starts over at the part where it asks if you want to add or subtract. How can I fix this?

    Put the calls to get_int() in the loop.
    [/edit]

    [edit too]
    This may be closer to what you want.
    Code:
    #include <stdio.h>
    
    int newline(void)
    {
       int c = getchar();
       while ( getchar() != '\n' )
          continue;
       return c;
    }
    
    int get_int(void)
    {
       int num;
       printf("Please enter an integer:\n");
       scanf("%d", &num);
       return num;
    }
    
    int get_choice(void)
    {
       int ch;
       printf("Please choose either of the following actions:\n");
       printf("a. add      s. subtract\n");
       ch = newline();
       while ( ch != 'a' && ch != 's' )
       {
          printf("Invalid answer. Please choose a or s:\n");
          ch = newline();
       }
       return ch;
    }
    
    int add(int num1, int num2)
    {
       int total = num1 + num2;
       printf("%d + %d = %d\n", num1, num2, total);
       return total;
    }
    
    int sub(int num1, int num2)
    {
       int total = num1 - num2;
       printf("%d - %d = %d\n", num1, num2, total);
       return total;
    }
    
    int main(void)
    {
       int n, m, ch;
       while ( (ch = get_choice()) != 'q' )
       {
          n = get_int();
          m = get_int();
          switch ( ch )
          {
          case 'a': add(n, m); break;
          case 's': sub(n, m); break;
          default : printf("That is invalid. Try again.\n");
          }
       }
       return 0;
    }
    [/edit]

    [edit yet again]
    Problems with scanf.
    Another FAQ.
    An FAQ with more details about obtaining a number from user input.
    [/edit]
    Last edited by Dave_Sinkula; 09-23-2003 at 12:12 PM.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  4. #4
    Registered User
    Join Date
    May 2003
    Posts
    49
    Thanks, guys!

    But Dave, with the code you gave, it still has one problem that it had before. It tells me that my input is invalid and then it's fine on the second try every time after the first round of the loop. In other words, I put in the letter and then the two numbers, it gives me the results, I enter a new letter (a or s, of course) and it tells me that's invalid and to try again, so I do and it accepts it, and it does this every round of the loop after the first. Why does it do this?

  5. #5
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Yeah, I knew this was coming. The last edits in my above post contain links that explain this. Basically, scanf leaves the newline in the stdin. You need to get rid of it.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  6. #6
    Registered User
    Join Date
    May 2003
    Posts
    49
    Sorry, I posted before you edited.

    I tried opening the first link but it wouldn't. Maybe I'll try with another browser. Thanks!

    EDIT:

    Sorry to edit, but I'm still not quite understanding something, and I forgot to ask one thing.

    With while (getchar() != '\n'), what exactly is going on here? Is the input that was assigned to ch somehow passing down to the getchar() here? Or is while (getchar() != '\n') going at the same time as ch getting a value? I still don't quite understand how using getchar() here works.

    Also, what do 1 and 2 mean? For instance,
    Code:
    while (scanf("%d", &num) != 1)
    I think that's all.
    Last edited by Tride; 09-23-2003 at 01:22 PM.

  7. #7
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Code:
    while (getchar() != '\n')
    The function getchar returns a value, an int. The value returned is not assigned. This return value is compared with '\n'.

    So, getchar returns a value of the character read from stdin. If this value is equal to '\n', the loop ends. Otherwise, the loop continues and the next character is read from the stdin and returned by getchar. Lather, rinse, repeat.

    >Also, what do 1 and 2 mean? For instance,
    Code:
    while (scanf("%d", &num) != 1)
    The return value of scanf is "the number of input items assigned". In this example, you request one conversion -- "%d", so you compare the return value to see if one value was assigned (to num).

    If you have more than one conversion specifier in the format string, you would test the return value to see that scanf assigned all the values you requested. For example,
    Code:
    int i,j;
    if(scanf("%d%d", &i, &j) == 2) { /* ... */ }
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  8. #8
    Registered User
    Join Date
    May 2003
    Posts
    49
    So, getchar returns a value of the character read from stdin. If this value is equal to '\n', the loop ends. Otherwise, the loop continues and the next character is read from the stdin and returned by getchar. Lather, rinse, repeat.
    But how does making a second getchar() achieve this? Why doesn't while ((ch = getchar()) != '\n') work the same way? And every input has a '\n' at the end of the line by default, correct? So if I type in the word "ramb", does
    Code:
    while (getchar() != '\n')
    look at the letter r, say it's OK since it's not the newline character, and keep on doing this until it comes to '\n'? And if this is what it does, I don't understand how it can only get the first character of the word and skip the rest. Where does the skipping of the rest of the word come in?

    One more thing, I sometimes see int variables being used for getchar() or something like that that I thought would need a char variable, like in the updated code you gave. What does it do when you make a variable like that (ch) an int rather than a char variable?

  9. #9
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    >>int variables being used for getchar() ...
    >>thought would need a char variable
    getchar() returns an int because EOF is an int. See here for full explanation:
    http://faq.cprogramming.com/cgi-bin/...&id=1043284351
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  10. #10
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    >But how does making a second getchar() achieve this?
    >Why doesn't while ((ch = getchar()) != '\n') work the same way?

    Would this help any?
    Code:
    #include <stdio.h>
    
    int get_first(void)
    {
       int ch, skip;
       ch = getchar();
       printf("ch = '%c'\n", ch);
       while( (skip = getchar()) != '\n')
       {
          printf("skip = '%c'\n", skip);
       }
       return ch;
    }
    
    int main(void)
    {
       int c;
       fputs("Enter some text: ", stdout);
       fflush(stdout);
       c = get_first();
       printf("c = '%c'\n", c);
       return 0;
    }
    
    
    /* my input/output
    Enter some text: some text
    ch = 's'
    skip = 'o'
    skip = 'm'
    skip = 'e'
    skip = ' '
    skip = 't'
    skip = 'e'
    skip = 'x'
    skip = 't'
    c = 's'
    */
    If you don't do the printf in the while loop in get_first, then you don't need to store the result of getchar in skip. And then you don't even need the variable skip. So get_first shrinks to this.
    Code:
    int get_first(void)
    {
       int ch;
       ch = getchar();
       while( getchar() != '\n') { /* nothing to do */ }
       return ch;
    }
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  11. #11
    Registered User
    Join Date
    May 2003
    Posts
    49
    All right. Thanks

  12. #12
    Registered User
    Join Date
    Aug 2003
    Posts
    93
    sorry for butting in on your thread

    quote by Hammer

    getchar() returns an int because EOF is an int. See here for full explanation:
    http://faq.cprogramming.com/cgi-bin...0&id=1043284351

    as EOF is defined in my local stdio.h as -1, why does fgets return a char * ?

  13. #13
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    >as EOF is defined in my local stdio.h as -1, why does fgets return a char * ?

    When fgetc reaches end-of-file (or error) it returns EOF, which is a macro "which expands to an integer constant expression, with type int and a negative value".

    When fgets reaches end-of-file (or error) it returns NULL, which is a macro "which expands to an implementation-defined null pointer constant".
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  14. #14
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    And to add to that, read the man page (particularly the RETURNS section)
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  15. #15
    Registered User
    Join Date
    Aug 2003
    Posts
    93
    so is it an error, no not error, mistake to check for EOF with fgets() when it returns NULL ?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. questions....so many questions about random numbers....
    By face_master in forum C++ Programming
    Replies: 2
    Last Post: 07-30-2009, 08:47 AM
  2. A very long list of questions... maybe to long...
    By Ravens'sWrath in forum C Programming
    Replies: 16
    Last Post: 05-16-2007, 05:36 AM
  3. Several Questions, main one is about protected memory
    By Tron 9000 in forum C Programming
    Replies: 3
    Last Post: 06-02-2005, 07:42 AM
  4. Trivial questions - what to do?
    By Aerie in forum A Brief History of Cprogramming.com
    Replies: 23
    Last Post: 12-26-2004, 09:44 AM
  5. questions questions questions.....
    By mfc2themax in forum A Brief History of Cprogramming.com
    Replies: 1
    Last Post: 08-14-2001, 07:22 AM