简体   繁体   中英

C - return variable always blank if max length is greater than 50

I'm really stumped on this one.

I have written a simple program in c to retrieve first name, last name and YOB (year of birth) from the user keyboard input (i haven't got around to parsing age into an integer yet) and I set a maximum number of characters for the input.

But whenever I allow the max characters for a field to be 50 or greater, the return value is always blank.

This is the code (60 lines), output to follow. The function causing trouble is the second to last function, getInputNoNewLine:

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

void flushBuffer();
char *getInput(int max, char message[]);
char *getInputNoNewline(int max, char message[]);

typedef struct Person {
    char *firstName;
    char *lastName;
    int yob;
} Person;

void flushBuffer() {
    int ch; 
    while ((ch = getchar()) != '\n' && ch != EOF); //flush the input buffer
}

char *getInput(int max, char message[]) {
    char in[max];
    char *input;
    do {
        printf("%s", message);
        input = fgets(in, max + 2, stdin); //max + 2 accounts for characters fgets adds
        if (input[strlen(input)-1] != '\n') {
            printf("Sorry, maximum %d characters\n", (max));
            flushBuffer();
        }
    } while (input[(strlen(input)-1)] != '\n');
    printf("input: %s", input); //debug
    return input;
}

//OFFENDING FUNCTION
char *getInputNoNewline(int max, char message[]) {
    char *input;
    input = getInput(max, message);
    printf("raw input : %s", input); //debug
    if (input[strlen(input) - 1] == '\n') { //strip new line character
        input[strlen(input) - 1] = '\0';
    }
    printf("final input: '%s'\n", input); //debug
    return input;
}

int main(int argc, char *argv[]) {
    int numPlayers = 3;
    char *intIn;
    int i = 0;
    Person players[numPlayers]; 
    printf("Hello world Game\n");
    for (i = 0; i < numPlayers; ++i) {
        players[i].firstName = getInputNoNewline(50, "What is your first name: "); //50 will return blank
        players[i].lastName = getInputNoNewline(49, "What is your last name: "); //49 will return fine
        intIn = getInputNoNewline(4, "What is your YOB: "); //TODO: convert number to integer with sscanf
        printf("-----------------------------------\n");
    }
    printf("Finished\n");
    return 0;
}

This is the output, as you can see the first input of jim is received from fgets, but the return value is blank (raw input : ). If I was to reduce the max value from 50 to 49, as per the case for the last name field, it works perfectly fine. Any thoughts?

Hello world Game
What is your first name: jim
input: jim
raw input : final input: ''
What is your last name: smith
input: smith
raw input : smith
final input: 'smith'
What is your YOB: 1984
input: 1984
raw input : 1984
final input: '1984'
-----------------------------------

Your code has an Undefined behavior .
You are returning a pointer to a locally allocated array.

char *getInput(int max, char message[])
{
    char in[max];
    ....
    ....
    return input;
}

in is a array local the function and is guaranteed to be alive only till the function scope {``} . To be able to access the contents of this array beyond the scope of function you need to increase the lifetime of the array by:

  • Allocating it dynamically using malloc or
  • Making it static or global

If you use malloc do not forget to deallocate the array after use by calling free or you end up with a memory leak.

Since you allocate in to be 50 character long, and you allow 52 characters to be read, you will run into trouble! You want to use

static char* in;
if(in!=NULL) free(in);
in = (char*)malloc(max + 2);

This addresses both the point that Alok raised (about local scope pointer not being defined once function returns), and the fact that your function allows fgets to write max+2 characters into the buffer in .

You have a number of memory management issues going on. The fgets call is begging for a crash since you're passing in a length 2 bytes greater than the allocated memory. You are also returning the char * returned from fgets and treating it like it's allocated memory.

You should copy the buffer returned from fgets and store it in your Person struct.

Really, I think you should review basic C memory allocation and destruction.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM