Search code examples
cscanfc-strings

Bizarre characters in scanf output


I am writing a function for use in a small C program. The function is supposed to prompt the user for n 7-digit alphanumeric course code strings, and return those strings as an array. I have written a function that I believe should do that, however I have experienced some errors.

char ** getNCourses(int n) {
    char **courses;
    courses = malloc(n * sizeof(char));

    for (int i=0; i<n; i++) {
        printf(INQUIRY_COURSE_CODE"\n", i);
        courses[i] = malloc(8);
        scanf("%7s", courses[i]);
        flush();
    }

    return courses;
}

I have a few lines of code to print the result of said array:

// prompt the user for course codes
char **pCourses;
pCourses = getNCourses(MAX_COURSES);

for (int i=0; i<MAX_COURSES; i++) {
    printf("%s ", pCourses[i]);
}

And here is an output of the program being run. As can be seen, the outputted course codes are "corrupted":

Registering 10 courses.
Please enter the 7-digit course code for course 0: 
CST8101
Please enter the 7-digit course code for course 1: 
CST8102
[...]
CST8109
Please enter the 7-digit course code for course 9: 
CST8110
�@�� CST8102 �@�� �@�� �@�� CST8106 CST8107 CST8108 CST8109 CST8110 % 

I am unsure as to why some of the course codes have no problem appearing, yet others are entirely incorrect. I believe it is not an issue with reading the data, but actually allocating the memory and returning the array, but I am at a loss.


Solution

  • char **courses;
    courses = malloc(n * sizeof(char));

    courses points to char *. Each char * requires sizeof (char *) bytes, not sizeof (char) bytes. n of them require n * sizeof (char *) bytes.

    You can avoid errors like this by always writing Pointer = malloc(n * sizeof *Pointer);. Then sizeof *Pointer always produces the size of the type being pointed to; you never have to deduce the type. It also automatically adjusts to declaration changes: If the code is edited to change the declaration of the pointer, the sizeof will still be correct because it uses the pointer to get the type, rather than a hard-coded type.