Basic C question '\n'

This is a discussion on Basic C question '\n' within the C Programming forums, part of the General Programming Boards category; As a newbie to this language I throw myself on the mercy of the people who know what they are ...

  1. #1
    Registered User
    Join Date
    Jan 2002
    Posts
    9

    Unhappy Basic C question '\n'

    As a newbie to this language I throw myself on the mercy of the people who know what they are doing.

    I am trying to learn the basics of the C language and I have hit a bit of an annoyance.
    I wish to develop a small program that acts like a menu, but I seem to have problems catching the new line character. I am running on a Win 98 platform with the gcc complier. We used it extensively working on building mobile databases for the Palm PDA, Sorry started rambling. Here is a copy of the code I am playing with. I would like to have a menu appear and when the user makes a selection it goes to another function and runs, then return and display the menu again. It almost works but not quite. I hope this does not violate any board rules, I did not see any rules on postin code. Please let me know if I am in error. Thanks in advance for any advice.

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>

    char option;
    int value;

    void mainmenu();
    void option1();

    int main()
    {
    mainmenu();
    }

    void mainmenu()
    {
    printf("Select an option\n\n");
    printf ("1. Option.\n");
    printf ("Selection:");

    option=getc(stdin);

    value = atoi(&option);

    switch ( value )
    {
    case 1:
    option1();
    mainmenu();
    break;

    default:
    mainmenu();
    break;
    }
    }

    void option1()
    {
    printf ("\n\nYou selected Option 1\n\n");
    }

  2. #2
    Registered User
    Join Date
    Sep 2001
    Posts
    305
    "catching" the new line character? you mean like understanding it?

  3. #3
    Registered User
    Join Date
    Jan 2002
    Posts
    9
    Sorry Flikm

    I guess it was a bit vauge. It appears the new line character is causes the mainmenu routine to run twice. If you get a chance compile it and check it out. By just pressing the enter key, the menu should do nothing or just loop back to the start. When you make a selection in the current code, the called function workes but then the menu items get displayed twice like a return character was held in memory and then passed bak to the routine. I was under the impression that the getc call was supposed to wait on user input.

  4. #4
    Registered User
    Join Date
    Sep 2001
    Posts
    305
    i dont see why youre going throgh all the trouble and using atoi and things. replace getc with scanf and just input an int from the user.

  5. #5
    Registered User
    Join Date
    Sep 2001
    Posts
    752
    I'm not too sure of what you're asking really... but I can tell you that the code you have below is not very good. At the end of mainmenu() you reprint the main menu by calling mainmenu(), which isn't a good idea. For each call, you're pushing some information up on the stack. This is really the kind of thing you should do with a loop.

    Code:
    void mainmenu (void) // explicitly declare the function as void
    { 
     for (;;) // This for loop puts the menu into an loop.
     {
      printf("Select an option\n\n"); 
      printf ("1. Option.\n"); 
      printf ("Selection:"); 
    
      // I suggest scanf....
      // option=getc(stdin); 
      // value = atoi(&option); 
    
      scanf ("%d", &value);
      for (;getchar() != '\n';); // This flushes the buffer.
      // You might not want this, dunno.  Feel free to comment out.
    
      switch (value)
      {
       case 1:
        option1();
        break;
        // Don't worry about calling mainmenu().
        // After this switch, the program will loop back up to the for (;;)
        // statement.
    
       case 0:
        goto ex;
        // This is for escaping a loop from within a switch.
        // Don't use goto in any other situation.
    
       default:
        break;
      } // End Switch.
     } // End for.  Code will go back to top and redisplay menu at this
        //  point.
     ex:
     // After the goto ex; command, we jump to here, exiting 
     //  the for(;;) loop
     return;
    }
    Handling menus is actually pretty challenging untill you figure out a working standard method of handling them. If you just have a single menu, the template I put up above is really the way to go IMO. What you want to really avoid is recursion (calling mainmenu() within mainmenu()), your code does this. Recursion has it's places, but this isn't it.

    And about posting code... well, it's quite allowed. In fact, you're really supposed to post code whenever you have a problem, since it makes it a lot easier to see where the problem is.
    Last edited by QuestionC; 01-19-2002 at 06:28 PM.
    Callou collei we'll code the way
    Of prime numbers and pings!

  6. #6
    Registered User
    Join Date
    Jan 2002
    Posts
    9
    Flikm

    I changed the mainmenu to this bit of code. If I enter the value 1 then I get what I want but if I just press the enter key it does not return to the mainmenu routine. How can I catch just the press of the enter key and if no value or a character was entered return to the mainmenu routine? This is my main problem.

    void mainmenu()
    {

    printf("Select an option\n\n");

    printf ("1. Option.\n");

    printf ("Selection:");

    scanf("%i", &value);

    switch ( value )
    {
    case 1:
    option1();
    mainmenu();
    break;

    default:
    mainmenu();
    break;
    }

    }

  7. #7
    Registered User
    Join Date
    Jan 2002
    Posts
    9
    QuestionC
    Thanks for the code snippet, I really like the way it catches alpha and numerics not covered in the switch statement. If you do not mind, when I compiled the code and ran it, I could press the enter key and if I pressed the enter key enough the menu would scroll right off the top of the screen, how do I check for just the enter key and if nothing was entered return to the menu display. Thanks

  8. #8
    Registered User
    Join Date
    Sep 2001
    Posts
    752
    Hmm, that problem can be solved by just going back to basically the way that you were handling input before, with getc. The problem you were experiencing before was because when you press in a number and press enter, that's two characters you've put into the buffer... the number, and the '\n'. So, what you need to do is flush the buffer to get rid of the '\n' (and any other crap the user might have put in that he didn't need to, like spaces).
    Code:
    void mainmenu (void) // explicitly declare the function as void
    { 
     for (;;) // This for loop puts the menu into an loop.
     {
      printf("Select an option\n\n"); 
      printf ("1. Option.\n"); 
      printf ("Selection:"); 
    
      option=getc(stdin); 
      
      // We don't need value, look at the switch statement to see why
      // value = atoi(&option); 
    
      // Apprantly, scanf's not the tool for this job...
      //scanf ("%d", &value);
      
      
      for (;getchar() != '\n';); // This flushes the buffer.
    
      switch (option)
      {
       case '1':
        option1();
        break;
        // Don't worry about calling mainmenu().
        // After this switch, the program will loop back up to the for (;;)
        // statement.
    
       case '0':
        goto ex;
        // This is for escaping a loop from within a switch.
        // Don't use goto in any other situation.
    
       default:
        break;
      } // End Switch.
     } // End for.  Code will go back to top and redisplay menu at this
        //  point.
     ex:
     // After the goto ex; command, we jump to here, exiting 
     //  the for(;;) loop
     return;
    }
    I'm pretty sure that this code isn't gonna work right if you just press enter, since it's gonna try to flush the buffer after that, but you don't have any buffer to flush since you only put one character into it, the '\n', and your getc took that out. The solution is to check if the user typed in '\n', if he did, then we don't flush the buffer.
    Code:
    void mainmenu (void) // explicitly declare the function as void
    { 
     for (;;) // This for loop puts the menu into an loop.
     {
      printf("Select an option\n\n"); 
      printf ("1. Option.\n"); 
      printf ("Selection:"); 
    
      option=getc(stdin); 
      
      // We don't need value, look at the switch statement to see why
      // value = atoi(&option); 
    
      // Apprantly, scanf's not the tool for this job...
      //scanf ("%d", &value);
      
      
      if (option != '\n')
      {
       for (;getchar() != '\n';); // This flushes the buffer.
      }
    
      switch (option)
      {
       case '1':
        option1();
        break;
        // Don't worry about calling mainmenu().
        // After this switch, the program will loop back up to the for (;;)
        // statement.
    
       case '0':
        goto ex;
        // This is for escaping a loop from within a switch.
        // Don't use goto in any other situation.
    
       default:
        break;
      } // End Switch.
     } // End for.  Code will go back to top and redisplay menu at this
        //  point.
     ex:
     // After the goto ex; command, we jump to here, exiting 
     //  the for(;;) loop
     return;
    }
    Last edited by QuestionC; 01-19-2002 at 06:45 PM.
    Callou collei we'll code the way
    Of prime numbers and pings!

  9. #9
    Registered User
    Join Date
    Jan 2002
    Posts
    9
    QuestionC

    Thank you for your help. This is what I was after. I wrote a shell script and then a perl script that did what I wanted but this C program was a brain teaser. If you had a chance to read my profile you will see that at my work they are using Suse on an s/390 and we are using DB2. I wanted a program that would work on Windows and the Suse linux so I know I will have to be careful on what libraries I use in this program and may even have to change it a bit when I compile it on Suse. I hope not much as I am using the same compiler on my Win machine as we have on the s/390, ok maybe not exaclty the same but close enough that I may not have to make major changes.

    Once again thanks QuestionC and Flikm for your input on my problem.

  10. #10
    Registered User
    Join Date
    Sep 2001
    Posts
    752
    Incidentally, flushing the input buffer comes up an awful lot in some applications. It's probably worthwhile to use a macro for it, like...

    #define FLUSH { for (;getchar() != '\n';); }

    Since that saves on a good bit of typing if you have to flush the buffer often, and it lets you easily change how you flush the buffer if there's a different way you need to do it.

    And generally, this kinda code will probably work properly on any platform.
    Callou collei we'll code the way
    Of prime numbers and pings!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A basic math programming question
    By hebali in forum C Programming
    Replies: 38
    Last Post: 02-25-2008, 03:18 PM
  2. Basic question about GSL ODE func RK4
    By cosmich in forum Game Programming
    Replies: 1
    Last Post: 05-07-2007, 02:27 AM
  3. Basic question about RK4
    By cosmich in forum C++ Programming
    Replies: 0
    Last Post: 05-07-2007, 02:24 AM
  4. A very basic question
    By AshFooYoung in forum C Programming
    Replies: 8
    Last Post: 10-07-2001, 03:37 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21