【问题标题】:Runtime Error with Printing Double Pointer Char Array打印双指针字符数组时出现运行时错误
【发布时间】:2014-11-14 05:57:29
【问题描述】:

我正在创建一个系统,用于将学生姓名和分数输入数组并将相同的信息打印到屏幕上,不幸的是,我不断收到奇怪的输出。

我使用调试器逐步完成了我的程序,它显示一切运行顺利,直到我到达打印学生信息的函数,那里的双指针 char 数组的值弄乱了。

这是我运行程序时看到的图像。 (http://s28.postimg.org/nv29feawt/Error.png)

注意:虽然我知道有更好、更简单的方法来做到这一点,但我需要使用动态分配的内存和数组来完成这项任务。

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;
}

【问题讨论】:

  • 永远不要从 malloc realloc, calloc 中转换返回值
  • firstNames[index] = first;lastNames[index] = last; 看起来很可疑。你正在做的是复制指针,而不是数组的内容。
  • 我希望您在原始作业中包含stdio.h。此外,如果您减少代码并发布更短的代码版本会更好(演示您的问题的最少代码。例如,只有名字而没有姓氏的版本。
  • 你需要strcpy from char first[20];到 firstNames[index] 等等,因为当您从 createNewEntry() 返回时,您的 "firstNames[index]" 变得无效
  • 当你这样做时:lastNames[index] = (char *)malloc((strlen(last)) * sizeof(char)); lastNames[index] = last; 你只需删除你的指针,它保留在前一行

标签: c arrays pointers double-pointer


【解决方案1】:
firstNames[index] = (char *)malloc((strlen(first)) * sizeof(char));
firstNames[index] = first;  /* You are missing your allocated memory block and assigning local */

以上行不正确。您不能使用分配 = 运算符分配 c-strings。你应该使用strcpy

您将本地数组分配给名字,函数结束后它没有生命。这会调用未定义的行为。 (您会看到奇怪的字符,但情况可能更糟)。

应该改写为(姓氏也类似)

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

在释放firstNameslastNames 之前,您应该循环释放firstNames 和lastNames 的所有成员。

【讨论】:

  • 或者你可以使用firstNames[index] = strdup(first);——如果有必要,写strdup()。它是 POSIX 函数,但不是标准 C 函数。此外,代码应该在使用分配的内存之前检查malloc() 是否成功。
【解决方案2】:

我同意 Mohit Jain 的回答,此外您甚至可以使用 sprintf

【讨论】:

  • 虽然你可以使用sprintf()——甚至snprintf()——但不清楚你为什么要这样做。你也可以使用memcpy()memmove() 而不是strcpy(),如果你小心地捕捉到strlen() 找到的长度——这可能会更好。
猜你喜欢
  • 2018-04-08
  • 1970-01-01
  • 1970-01-01
  • 2020-03-23
  • 2020-03-26
  • 1970-01-01
  • 2020-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多