Thread: basic input and output with printf and fgets

  1. #1
    Unregistered
    Guest

    basic input and output with printf and fgets

    I would like to get 2 numbers and display them back to the console. Seems easy and i can do it a different way but am trying to learn how to use printf and fgets. Should i use scanf? I am also trying to learn how to write portable code. Keep in mind that i am a newb.

    #include <stdio.h>

    #define max 2

    int main()
    {

    char a[max] , b[max];

    printf("Enter two numbers:\n");
    fgets(a,max,stdin);
    printf("\n");
    fgets(b,max,stdin);

    printf("%s, %s",a,b);

    fgets(a,max,stdin);

    return 0;

    }

  2. #2
    Unregistered
    Guest
    The problem is that it accepts only the first input and prints it back incorrectly. example: i enter 12 and it does not take a second input but prints out 1, 2. I do not know what is wrong. please help.

  3. #3
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >Should i use scanf?
    Not if you can avoid it without bending over backwards.

    >I am also trying to learn how to write portable code.
    Bravo! This should be everyone's goal. I've worked with some people who couldn't care less about portability. This usually translates into the quality of their code as well, so you can tell who is good and who isn't by their attitude on portability. (From my experience)

    You really don't need two arrays, just have the input formatted into one array and use sscanf to read the values into integer variables:
    Code:
    #include <stdio.h>
    /*
    ** Macros are traditionally upper case so we
    ** can tell them apart from variables and functions.
    */
    #define MAX 100 /* Some arbitrary value */
    
    int main ( void )
    {
      char a[MAX];
      int ia, ib;
    
      printf ( "Enter two numbers:\n" );
      /*
      ** Check all return values in case something ugly happened.
      */
      if ( fgets ( a, MAX, stdin ) != NULL ) {
        /*
        ** Ditto, especially with user input. :)
        */
        if ( sscanf ( a, "%d %d", &ia, &ib ) != 2 )
          printf ( "Hmm, did you enter it correctly?" );
        else
          printf ( "Your numbers were: %d and %d\n", ia, ib );
      }
      return 0;
    }
    [suggestion]
    Also take note of whitespace in between tokens, such as your line here:

    >fgets(b,max,stdin);

    It is widely accepted that no whitespace between tokens is harder to read than well placed spacing. Some of the more popular styles for this are:

    /* Separate the arguments and the argument list */
    fgets (b, max, stdin);

    /* Separate everything */
    fgets ( b, max, stdin );

    /* Separate only the arguments */
    fgets( b, max, stdin );

    C is cryptic enough without our adding difficult to read code through bad formatting. Look into some style guides that can be found online for further information. The best style is the one that is easy to read and consistent, despite what some people will say.
    [/suggestion]

    -Prelude
    My best code is written with the delete key.

  4. #4
    Unleashed
    Join Date
    Sep 2001
    Posts
    1,765
    [EDIT]
    ROFL ... Prelude got it
    [/EDIT]
    The world is waiting. I must leave you now.

  5. #5
    Unregistered
    Guest
    Thank you prelude. If you don't mind, could you explain to me what &ia and &ib are in ( sscanf ( a, "%d %d", &ia, &ib ) != 2 ). also what is going on in this statement. As i said before i am new and self taught with no formal training. I would settle for a link in the wright direction. thanks

  6. #6
    Registered User moi's Avatar
    Join Date
    Jul 2002
    Posts
    946
    Originally posted by Unregistered
    Thank you prelude. If you don't mind, could you explain to me what &ia and &ib are in ( sscanf ( a, "%d %d", &ia, &ib ) != 2 ). also what is going on in this statement. As i said before i am new and self taught with no formal training. I would settle for a link in the wright direction. thanks
    sscanf takes a few arguments.

    the first one, a is the string we got from input using fgets()

    the second one is a format that sscanf() tries to use to get meaningful data out of a, in this case two ints.

    all remaining arguments are pointers to the the variables we want sscanf() to store meaningful data in. in this case since int ia and ib were declared as ints and not pointers to ints, we need to use the & infront of them to pass their addresses to sscanf().

    the != 2 is testing against the return value of sscanf(), which tells how many meaningful variables were assigned. we want it to be exactly two here.

    i am also a self taught C programmer like yourself. i very strongly reccomend a libc refrence doc for your libc and a basic programming in C book (others will have good book titles)

  7. #7
    Unregistered
    Guest
    I dont think i will ever understand pointers. I just dont get why you have to pass the address of ia and ib. And why cant i just assign values to ia and ib. This is a major block for me for a lot of thing i read about and then try to figure out by example. One day the light bulb will come on... I hope.

  8. #8
    Registered User moi's Avatar
    Join Date
    Jul 2002
    Posts
    946
    fgets() gets a string. your code gets two strings and prints them back. if you want to get two numbers and print them back, then you have to use sscanf and sprintf like shown (there are alternatives for sscanf though)

    you have to pass the addresses of ia and ib to sscanf() because it is programmed to expect pointers, so you need to give it the memory address which points to the memory location containing the values of ia and ib.

    i'm sure that wasnt very helpful, maybe someone else can elaborate.
    hello, internet!

  9. #9
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >And why cant i just assign values to ia and ib.
    All function arguments are passed by value, this means that a copy is made of the original and you change the copy in the function:
    Code:
    #include <stdio.h>
    
    int f ( int copy )
    {
      copy++;
    }
    
    int main ( void )
    {
      int i = 5;
      f ( i );
      printf ( "%d\n", i );
      return 0;
    }
    Since i is passed by value, the copy is incremented by one, but i remains unchanged. The output of this program is 5.

    Now, one can simulate pass by reference and modify the original object by passing it as a pointer:
    Code:
    #include <stdio.h>
    
    int f ( int *copy )
    {
      *copy++;
    }
    
    int main ( void )
    {
      int i = 5;
      f ( &i );
      printf ( "%d\n", i );
      return 0;
    }
    The output of this program is 6 because the address of i was passed by value. The pointer in f was a copy of the address of i, so when it increments the object it points to, the value of i changes. This change is obvious when f returns and i has the value of 6.

    The scanf family does something similar, to read from input is simple, but if you pass scanf the copy of a variable it will not place the input in the correct place and your copy of i will remain empty:
    Code:
    #include <stdio.h>
    
    void f ( int copy )
    {
      copy = 10;
    }
    
    int main ( void )
    {
      int i;
      f ( i )
      printf ( "%d\n", i );
      return 0;
    }
    The output of this program is undefined, it is dependent on the random value placed in i when you declared it. Let's try this again with the address of i:
    Code:
    #include <stdio.h>
    
    void f ( int *copy )
    {
      *copy = 10;
    }
    
    int main ( void )
    {
      int i;
      f ( &i )
      printf ( "%d\n", i );
      return 0;
    }
    Since you pass the address of i to f, the value of 10 is placed at the address that i rests in. So the output of this program is 10. The scanf family works the same way and for the same reasons.

    -Prelude
    My best code is written with the delete key.

  10. #10
    Unregistered
    Guest
    I expand just a little on prelude's example. In his example it would allow you to enter as many numbers as you wanted but would only print 2 of them out. But if you didnt enter enough it would tell you. I added an extra variable to check if too many numbers were entered. Is this an exceptable way of checking for this situation?


    #include <stdio.h>
    /*
    ** Macros are traditionally upper case so we
    ** can tell them apart from variables and functions.
    */
    #define MAX 100 /* Some arbitrary value */

    int main ( void )
    {
    char a[MAX];
    int ia, ib, ic;

    printf ( "Enter two numbers:\n" );
    /*
    ** Check all return values in case something ugly happened.
    */
    if ( fgets ( a, MAX, stdin ) != NULL ) {
    /*
    ** Ditto, especially with user input.
    */
    if ( sscanf ( a, "%d %d %d", &ia, &ib, &ic) != 2 )
    printf ( "Hmm, did you enter it correctly?" );
    else
    printf ( "Your numbers were: %d and %d\n", ia, ib);


    }
    scanf("%c", a);

    return 0;
    }

  11. #11
    Unregistered
    Guest
    Thank you prelude for the explanation. That makes some sence.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. customer input
    By buckwheat88 in forum C Programming
    Replies: 6
    Last Post: 11-21-2005, 08:01 PM
  2. 'const int' vs. #define and ouput issues
    By silverback011 in forum C Programming
    Replies: 14
    Last Post: 12-31-2004, 03:48 PM
  3. Simple message encryption
    By Vicious in forum C++ Programming
    Replies: 10
    Last Post: 11-07-2004, 11:48 PM
  4. Buffering??
    By Brain Cell in forum C Programming
    Replies: 15
    Last Post: 09-21-2004, 06:57 AM
  5. Very odd segmentation fault/core dump.
    By ChristianTool in forum C Programming
    Replies: 19
    Last Post: 04-26-2004, 06:38 AM