Runtime Error with Printing Double Pointer Char Array

636 views Asked by At

I am working on creating a system for entering student names and scores into arrays and printing the same information to the screen, unfortunately I keep getting the weird output.

I stepped through my program using a debugger and it showed that everything runs smooth until I get to the function that prints the student's information, there the double pointer char arrays have messed up values.

Here's an image of what I see when I run the program. (http://s28.postimg.org/nv29feawt/Error.png)

Note: Although I am aware that there are better and easier ways of doing this I am required to complete this assignment using dynamically allocated memory and arrays.

int main(void)
{
    char **firstNames;
    char **lastNames;
    float *scores;

    int recordsLength;
    printf("Please indicate the number of records you want to enter: ");
    scanf("%d", &recordsLength);
    printf("\n\n");

    firstNames = (char **)malloc(recordsLength * sizeof(char *));
    lastNames = (char **)malloc(recordsLength * sizeof(char *));
    scores = (float *)malloc(recordsLength * sizeof(float));

    int i = 0;
    while(i < recordsLength)
    {
        createNewEntry(i, firstNames, lastNames, scores);
        i++;
    }

    printEntry(0, firstNames, lastNames, scores);
    free(firstNames);
    free(lastNames);
    free(scores);
    return 0;
}

void clearScreen()
{
#ifdef _WIN32 
    system("cls");
#elif _unix_ 
    system("clear");
#endif
}

void printEntry(int entryID, char *firstNames[], char *lastNames[], float scores[])
{
    clearScreen();
    printf("|-------------------------------------------------------------------------|\n");
    printf("|                           Student Entry                                 |\n");
    printf("|-------------------------------------------------------------------------|\n|\n");
    printf("|   First Name: %s   Last Name: %s   Score: %.1f\n|\n|\n|\n", firstNames[entryID], lastNames[entryID], scores[entryID]);
    printf("|-------------------------------------------------------------------------|\n");
    printf("|                                                                         |\n");
    printf("|-------------------------------------------------------------------------|\n\n");
}

void createNewEntry(int index, char *firstNames[], char *lastNames[], float scores[])
{
    printf("Please input the records of the new student.\n\n\n");
    char first[20];
    char last[20];
    float score = 100.0f;

    printf("Please enter the student's first name: ");
    scanf("%s", &first);
    printf("\n\n");

    printf("Please enter the student's last name: ");
    scanf("%s", &last);
    printf("\n\n");

    printf("Please enter the student's score: ");
    scanf("%f", &score);
    printf("\n\n");

    firstNames[index] = (char *)malloc((strlen(first)) * sizeof(char));
    firstNames[index] = first;

    lastNames[index] = (char *)malloc((strlen(last)) * sizeof(char));
    lastNames[index] = last;
    printf("first name: %s", firstNames[index]);
    printf("last name: %s", lastNames[index]);
    scores[index] = score;
}
2

There are 2 answers

1
Mohit Jain On BEST ANSWER
firstNames[index] = (char *)malloc((strlen(first)) * sizeof(char));
firstNames[index] = first;  /* You are missing your allocated memory block and assigning local */

Above lines are incorrect. You can not assign c-strings with assignation = operator. You should use strcpy for that.

You are assigning local array to firstnames, which has no life after the function ends. This invokes an undefined behavior. (You are seeing the strange characters, but it can be even worse).

Should be Re-written as (Similar for last name also)

firstNames[index] = malloc((strlen(first) + 1) * sizeof(char)); /* +1 for \0 */
if(firstNames[index] == NULL) {
  /* Malloc failed, error handling */
  ...
}
/* else */
strcpy(firstNames[index], first);  /* Use strcpy to copy contents */

Live example here

Before freeing firstNames and lastNames, you should free all the member of firstNames and lastNames in a loop.

1
Achyuta Aich On

I agree with the answer of Mohit Jain, adding to that you can even use sprintf.