【问题标题】:strings in linked list are overlapping with each other C链表中的字符串相互重叠 C
【发布时间】:2019-04-26 11:40:54
【问题描述】:

我正在尝试创建一个结构来记录一群人。出于某种原因,每当我输入此人的房间名称时,房间名称都会替换此人的名字。这在 addResi 函数中的测试 5 中显示。

struct resi {
    char *firstname;
    char *lastname;
    double stnscore;
    char *roomName;
    struct resi *next;
};
struct resi *head = NULL;
struct resi *current = NULL;

void printAll() {
    struct resi *outer = head;
    if (outer == NULL) {
        printf("Empty\n"); fflush(stdout);
    }
    while (outer != NULL) {
        printf("First Name: %s, Last Name: %s, Score: %lf, roomName: %s\n", outer->firstname, outer->lastname, outer->stnscore, outer->roomName); fflush(stdout);
        outer = outer->next;
    }
}
void addResi(char *firstname, char *lastname, double stnscore, char *roomName) {
    printf("test 0\n"); fflush(stdout);

    struct resi *link = (struct resi*) malloc(sizeof(struct resi));
    printf("test 1 %s\n", firstname); fflush(stdout);

    strcpy(link->firstname, firstname);
    printf("test 2 %s\n", link->firstname); fflush(stdout);

    strcpy(link->lastname, lastname);
    printf("test 3\n"); fflush(stdout);

    link->stnscore = stnscore;
    printf("test 4\n"); fflush(stdout);

    strcpy(link->roomName, roomName);
    printf("test 5 %s %s\n", link->firstname, link->roomName); fflush(stdout); //they shouldn't be the same.

    link->next = head;
    head = link;
}

int main (void)
{
    int totalStud, tempX = 0;
    char firTemp[21], lasTemp[21], roomTemp[21];
    double scrTemp;

    printf("How many residences?\n"); fflush(stdout);
    scanf("%d", &totalStud);
    if (totalStud < 5) {
        printf("The number %d is less than 5, please type a different number\n",
            totalStud); fflush(stdout);
    }
    while (totalStud < 5) {
        scanf("%d", &totalStud);
    }

    printf("type the residences with following format\nfirst name last name score room\n"); fflush(stdout);

    for (tempX = 0; tempX < totalStud; tempX++) {
        scanf("%20s %20s %lf %20s", firTemp, lasTemp, &scrTemp, roomTemp);
        printf("test mid %s %s %lf %s\n", firTemp, lasTemp, scrTemp,
            roomTemp); fflush(stdout);
        addResi(firTemp, lasTemp, scrTemp, roomTemp);
        printAll();
    }
}

如果我输入“5”,然后输入“Bob Billy 45.5 Jackson”,最后的输出应该看起来像“First Name: Bob, Last Name: Billy, Score: 45.500000, roomName: Jackson”,但它显示为“First姓名:杰克逊,姓:比利,分数:45.500000,房间名:杰克逊”

【问题讨论】:

  • 你从哪里想到要到处写fflush(stdout)
  • 如果你真的想要无缓冲的输出,最好在程序开头使用setvbuf(stdout, NULL, _IONBF, 0);

标签: c string memory linked-list


【解决方案1】:

resi 实际上并不保存名称的空间 - 它只是保存指向它们的指针。我所知道的最小更改是将char *firstname 更改为char firstname[256],同样适用于resi 中的其他char * 字段。

resi 中的指针在内存中保存字符所在的位置,而不是字符本身。当您malloc 时,这些位置是未指定的 - 它们可以是任何东西。因此,strcpy 调用将字符放在内存中的某个位置,但我们不确定在哪里!

由于您还没有定义将这些字符放在哪里,我怀疑内存中的一些随机位置是重叠的,所以几个strcpy 调用将数据放在内存的同一部分。这可能会导致您看到的行为。

【讨论】:

  • 嗯,我试试看。但是如果我删除 roomName,为什么它会正常工作?
  • @BryanRosen 纯属运气:)。 (或者,更准确地说,是你的操作系统/编译器/库的内部结构。)
【解决方案2】:

幸运的是它没有崩溃。该行为是未定义的,因为您正在复制到任何内存 firstname、lastname 和 roomname 所指向的内容,而这些从未设置为任何有意义的内容。每当您使用 malloc 分配内存时,该内存的内容基本上是随机的,直到您对其进行初始化。如前所述,您可能可以通过使用数组定义(例如 firstname[256])来进行更改,但另一种解决方案是使用 strdup 而不是 strcpy,这将复制字符串。如果您删除该结构的一个实例以避免内存泄漏,则需要稍后释放此内存。

【讨论】:

    猜你喜欢
    • 2018-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    • 2018-07-11
    • 1970-01-01
    • 2020-12-08
    相关资源
    最近更新 更多