Thread: printf printing twice?

  1. #1
    Registered User
    Join Date
    Mar 2011
    Posts
    25

    printf printing twice?

    I have a short main that interacts with the user, grabbing commands to call on files passed as arguments to the program. The program queries the user for a command, gets the command, and then processes. If the user types 'n' the program goes to the next file. On the second file, and I'm assuming the following files, the query printf prints twice. Anyone have an idea why that happened?

    2nd EDIT: Upon further investigation i've found that it is carrying out the command related the the user-entered char, and then for some reason it loops again and calls execute_option with a blank, perhaps the \n char, which calls the default case. Any idea how to avoid this? I've used a for(;; ) with a break or exit before with no trouble, but this while loop structure seems to be posing an issue.

    for example with "a.out wut huh" (n is next file, q is quit program).

    Code:
    for the file ``wut'': please enter a command command:
    n
    for the file ``huh'': please enter a command command:
    for the file ``huh'': please enter a command command:
    q

    Code below: I've chopped out includes. They are all fine. EDIT: I realize the bottom of main got chopped off, ignore that. The loops are the important parts.
    Code:
    int execute_choice(char c, char *filename)
    {
      switch(c)
      {
        case('c'): list_file(filename); return 1;
        case('d'): copy_file(filename); return 1;
        case('r'): rename_file(filename); return 1;
        case('u'): remove_file(filename); return 1;
        case('t'): truncate_file(filename); return 1;
        case('a'): append_file(filename); return 1;
        case('l'): tail_file(filename); return 1;
        case('m'): change_permissions(filename); return 1;
        case('x'): change_access(filename); return 1;
        case('n'): return 0;
        case('q'): exit(0);
        default: return 1;
      };
    }
    
    int main(int argc, char *argv[])
    {
      if(!(argc>1))
      {
        fprintf(stderr, "Usage: wash <file1> <file2>...\n");
        exit(-1);
      }
      int go_next = 1;
      for(argv++; *argv != NULL; )
      {
        char command;
        while(go_next == 1)
        {
          printf("for the file ``%s'': please enter a command command:\n", *argv);
          command = getchar();
          go_next = execute_choice(command, *argv);
        }
        argv++;
        go_next = 1;
      }
    Thanks folks.
    Last edited by drshmoo; 03-18-2011 at 11:17 PM.

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Welcome to the most common problem with scanf() and getchar(). They leave the newline char, still in the input buffer.

    Add this:
    (void) getchar();

    right after the getchar that you now have, and that will end the problem. That will remove one '\n' char from the input stream.

  3. #3
    Registered User
    Join Date
    Mar 2011
    Posts
    25
    Ah. Is there anyway to avoid that? Any other function that avoids the return on the buff?

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Code:
    char buff[BUFSIZ];
    if ( fgets( buff, sizeof buff, stdin ) != NULL ) {
      // parse buff to see what was input
    }
    If you use fgets for ALL input, then you always know what state the input stream is in, and you can have a meaningful go at parsing the buffer.

    scanf(), which attempts input and conversion all at the same time, is a PITA to get right when you try to implement full error checking and recovery.

    The key is, if you have a consistent approach which always works, then you can just do it, and start worring about something specific to your actual problem. As opposed to worrying about which new scanf trap you're going to fall into.
    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.

  5. #5
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Oh and you don't need that (void) in front of getchar().
    That's only for a certain anchient, outdated, dead, and irrelevant compiler, that a select few quirky people still drag along with them, whilst it kicks and screams "please let me die in peace!".
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  6. #6
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Truth be known, scanf() really stinks for user input. Every book uses it, so the teachers do as well, and it's fine for formatted input, but not good for user's input.

    fgets(), when you're ready, is definitely better for user input.

    And Malcolm, my Turbo C screams "please, don't let me die on the scrap heap!".

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 01-29-2011, 04:54 AM
  2. get keyboard and mouse events
    By ratte in forum Linux Programming
    Replies: 10
    Last Post: 11-17-2007, 05:42 PM
  3. segmentation fault upon reload
    By yabud in forum C Programming
    Replies: 8
    Last Post: 12-18-2006, 06:54 AM
  4. Simple C question: user input to repeat a loop
    By evernaut in forum C Programming
    Replies: 2
    Last Post: 11-18-2006, 09:23 AM
  5. Azbia - a simple RPG game code
    By Unregistered in forum Game Programming
    Replies: 11
    Last Post: 05-03-2002, 06:59 PM