Home > Blockchain >  One of my scanf inputs is not being stored despite everything else storing
One of my scanf inputs is not being stored despite everything else storing

Time:09-13

I am extremely new to working in C so forgive me if I have just made a simple error but I am extremely confused. My code is as follow:

#include <stdio.h>
#include <string.h>
int
main ()
{
  char first[10],last[10],address[20],city[10],state[3],zipcode[5];
  printf("\n\nPart 3:\n");
  printf("Please enter your name and address:\n");
  printf("First Name: ");
  scanf("%s", first);
  printf("Last Name: ");
  scanf("%s", last);
  printf("Address: ");
  fgetc(stdin);
  fgets(address, 20, stdin);
  address[strcspn(address,"[/r/n]")] = 0;
  printf("City: ");
  scanf("%s", city);
  printf("State: ");
  scanf("%s", state);
  printf("Zipcode: ");
  scanf("%s", zipcode);
  printf("%s %s\n%s%s, %s,  %s",first,last,address,city,state,zipcode);

  return 0;
}

Everything works except when the final print statement is read first is not output, it just begins with last name. Example:

For the input

Please enter your name and address:
First Name: Ben
Last Name: Johnson
Address: 1234 Smith St
City: Townsville
State: CA
Zipcode: 12345

I get the following output:

 Johnson
1234 Smith St
Townsville, CA, 12345

Just not sure where it is going wrong as my first is being inputted the exact same way as my other variables that are working.

CodePudding user response:

You are writing to the arrays city and zipcode out of bounds, which causes undefined behavior.

The input string Townsville is 10 characters long, so it requires 11 characters including the terminating null character. However, the array city only has space for 10 characters, so it is not large enough to store that string. Therefore, when scanf attempts to store Townsville into city, it will overflow the buffer.

The array zipcode has the same problem. For the stated input 12345 it requires 6 characters (including the terminating null character), but you only gave the array space for 5 characters.

In order to prevent this kind of problem in the future, I recommend that that you use fgets for all data, as fgets will never overflow the buffer, provided that you pass the correct size of the buffer (which you are doing in your posted code). However, this would mean a lot of extra code, because you would also have to write code to remove the newline character every time you call fgets. For this reason, it would probably be best to write your own function. This function could also verify that the entire line was read in, and print an error message if the buffer was not large enough.

I have rewritten your code to use such a function:

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

void get_line_from_user( char *buffer, int buffer_size );

int main( void )
{
    char first[10],last[10],address[20],city[10],state[3],zipcode[5];

    printf("Part 3:\n");
    printf("Please enter your name and address:\n");

    printf("First Name: ");
    get_line_from_user( first, sizeof first );

    printf("Last Name: ");
    get_line_from_user( last, sizeof last );

    printf("Address: ");
    get_line_from_user( address, sizeof address );

    printf("City: ");
    get_line_from_user( city, sizeof city );

    printf("State: ");
    get_line_from_user( state, sizeof state );

    printf("Zipcode: ");
    get_line_from_user( zipcode, sizeof zipcode );

    printf("%s %s\n%s%s, %s,  %s",first,last,address,city,state,zipcode);

    return 0;
}

//This function will read exactly one line of input from the
//user. On failure, the function will never return, but will
//print an error message and call "exit" instead.
void get_line_from_user( char *buffer, int buffer_size )
{
    char *p;

    //attempt to read one line of input
    if ( fgets( buffer, buffer_size, stdin ) == NULL )
    {
        printf( "Error reading from input\n" );
        exit( EXIT_FAILURE );
    }

    //attempt to find newline character
    p = strchr( buffer, '\n' );

    //make sure that entire line was read in (i.e. that
    //the buffer was not too small to store the entire line)
    if ( p == NULL )
    {
        //a missing newline character is ok if the next
        //character is a newline character or if we have
        //reached end-of-file (for example if the input is
        //being piped from a file or if the user enters
        //end-of-file in the terminal itself)
        if ( getchar() != '\n' && !feof(stdin) )
        {
            printf( "Line input was too long!\n" );
            exit( EXIT_FAILURE );
        }
    }
    else
    {
        //remove newline character by overwriting it with
        //null character
        *p = '\0';
    }
}

Now the program will give you a proper error message if the input is too long, instead of overflowing the buffer:

Part 3:
Please enter your name and address:
First Name: Ben
Last Name: Johnson
Address: 1234 Smith St
City: Townsville
Line input was too long!
  • Related