我正在从格式化的文件中读取和保存字符串,由于某种原因,我发现sscanf()
更改了testa_e->ident
内容。
我已经放了一些printf
,我发现问题在sscanf()
之后立即发生。我也通过打印检查了temp2
,temp5
和testa_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);
}
}
这里的代码重现了完全相同的问题。启动后,在终端上并在
addent firstword
附近写addent secondword
和sscanf
,它应该显示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 );
为什么在函数中使用了指向head的指针?
首先,如果要更改原始磁头,则需要通过引用传递它。其次在循环中
while ( *head != NULL ) head = &( *head )->next;
指针再次指向最后一个节点的数据成员
next
。因此,我们不像在函数实现中那样更改局部变量curs
,而是最后一个节点的数据成员next
。因此,我们正在更改列表本身。注意将这样的typedef定义为
typedef const char* identifier;
是一个坏习惯。
关于c - 为什么此sscanf会修改一些我不想修改的数据?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57433549/