gpt4 book ai didi

c - 为什么这个sscanf修改了一些我不想修改的数据?

转载 作者:行者123 更新时间:2023-12-01 01:29:05 25 4
gpt4 key购买 nike

我正在从格式化文件中读取和保存字符串,出于某种原因,我发现 sscanf() 更改了 testa_e->ident 内容。

我已经放置了一些 printf 并且我发现问题发生在 sscanf() 之后;我还通过打印检查了 temp2temp5testa_e 的地址,但它们是不同的。

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

#define string 30
#define line 100

typedef const char *identifier;

struct nodo_id {
identifier ident;
struct nodo_id *next;
};
typedef struct nodo_id nodo_id;

nodo_id *testa_e = NULL;

void addent(const char *id_ent) {
if (testa_e == NULL) {
testa_e = malloc(sizeof(nodo_id));
testa_e->ident = id_ent;
testa_e->next = NULL;
} else {
nodo_id *curs = testa_e;
while (curs != NULL) {
curs = curs->next;
}
curs = malloc(sizeof(nodo_id));
curs->ident = id_ent;
curs->next = NULL;
}
}

int main() {
char temp[line];
char temp2[string];
char temp5[string];

fgets(temp, line, stdin);
while (strncmp(temp, "end", 3) != 0) {
if (strncmp(temp, "addent", 6) == 0) {
if (testa_e != NULL)
printf("\nbefore sscanf: %s\n", testa_e->ident);
sscanf(temp, "%s %s", temp5, temp2);
if (testa_e != NULL)
printf("\nafter sscanf: %s\n", testa_e->ident);
addent(temp2);
}
fgets(temp, line, stdin);
}
}

这段代码重现了完全相同的问题;启动后,在终端和 sscanf 周围写入 addent firstwordaddent secondword 它应该会显示 testa_e->ident 内容已更改,我想知道为什么以及如何解决这个问题,因为我真的不知道...

最佳答案

在函数addent这个循环中

        while(curs!=NULL){
curs=curs->next;
}

迭代直到 curs 等于 NULL

那你就是在改变指针

    curs=malloc(sizeof(nodo_id));
curs->ident=id_ent;
curs->next=NULL;

列表本身没有改变。您只更改了局部变量 curs

按以下方式更改循环

        while ( curs->next != NULL ){
curs = curs->next;
}

然后

    curs->next = malloc( sizeof( nodo_id ) );
curs->next->ident = id_ent;
curs->next->next = NULL;

另一个问题是您正在使用指向本地数组的指针

char temp2[string];
//...
addent(temp2);

因此将存储在数组中的最后一个将被所有节点指向。您需要为将存储在列表中的每个字符串动态分配内存,并将地址分配给数据成员 ident。在这种情况下,您必须从其声明中删除限定符 const

考虑到使函数依赖于全局变量是个坏主意,

addent 函数的更好定义如下所示

struct nodo_id{
char *ident;
struct nodo_id* next;
};
typedef struct nodo_id nodo_id;

int addent( nodo_id **head, const char *id_ent )
{
nodo_id *new_nodo_id = malloc( sizeof( nodo_id ) );
int success = new_nodo_id != NULL;

if ( success )
{
new_nodo_id->ident = malloc( strlen( id_ent ) + sizeof( ( char )'\0' ) );

success = new_nodo_id->ident != NULL;

if ( ! success )
{
free( new_nodo_id );
}
else
{
strcpy( new_nodo_id->ident, id_ent );
new_nodo_id->next = NULL;

while ( *head != NULL ) head = &( *head )->next;

*head = new_nodo_id;
}
}

return success;
}

函数可以这样调用

addent( &testa_e, temo2 );

为什么在函数中使用指向头部的指针?

首先,如果我们想改变原来的头部,我们需要通过引用传递它。其次在循环中

while ( *head != NULL ) head = &( *head )->next;

指针再次指向最后一个节点的数据成员next。所以我们改变的不是函数实现中的局部变量 curs ,而是最后一个节点的数据成员 next 。所以我们正在更改列表本身。

注意定义这样一个typedef as

typedef const char* identifier;

是一种不好的做法。

关于c - 为什么这个sscanf修改了一些我不想修改的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57433549/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com