C语言中向Token结构体value字段追加字符出现乱码求助
我是C语言新手,遇到了一个问题,希望能从根源解决:
我定义了如下Token结构体:
//Token struct struct Token { char type[16]; char value[1024]; };
我尝试从文件读取字符并追加到Token.value中,代码如下:
struct Token newToken; char ch; ch = fgetc(file); strncat(newToken.value, &ch, 1);
这段代码能运行,但Token.value开头会出现乱码,控制台打印为@�����TheCharactersIWantedToAppend。分析这些乱码字符,索引1-5依次是\330, \377, \377, \377, \177。我知道\377是十进制255,也就是EOF的特殊值,想知道这些值是不是内存地址?是不是因为strncat中用&ch导致把地址加到了Token.value里?如果是,该怎么避免?
另外,如果改成strncat(newToken.value, ch, 1)(把&ch换成ch)会触发段错误。
问题根源
strncat要求第二个参数是以'\0'结尾的字符串指针,但你传入的&ch只是单个字符的地址,后面的内存是未初始化的垃圾数据。strncat会一直读取直到遇到'\0',所以把ch后面的随机垃圾字符也追加到了newToken.value里。
另外,newToken.value本身是未初始化的局部变量,它的初始值也是内存里的随机垃圾——strncat是在原字符串的末尾追加,而原字符串没有被初始化为空字符串(第一个字符不是'\0'),所以strncat会从随机位置开始追加,甚至直接把垃圾和读取的字符混在一起,这就是开头乱码的核心原因。
解决步骤
初始化Token.value为空字符串
局部结构体变量在栈上默认未初始化,必须先清空或初始化:struct Token newToken; // 方法1:仅初始化字符串结束符,快速简单 newToken.value[0] = '\0'; // 方法2:清空整个结构体,更稳妥(需包含头文件<string.h>) memset(&newToken, 0, sizeof(struct Token));正确追加单个字符
避免用strncat处理单个字符,直接通过数组索引赋值更安全:char ch = fgetc(file); if (ch != EOF) { size_t len = strlen(newToken.value); // 确保不越界(value数组大小为1024,需留一个位置放'\0') if (len < 1023) { newToken.value[len] = ch; newToken.value[len + 1] = '\0'; // 手动添加字符串结束符 } }如果一定要用
strncat,可以把字符放到一个带'\0'的临时数组中:char temp[2] = {0}; temp[0] = ch; strncat(newToken.value, temp, 1);段错误的原因
当你写strncat(newToken.value, ch, 1)时,char类型的ch会被隐式转换成int,然后被当作内存指针使用——相当于把ch的ASCII值当成内存地址去读取,这个地址几乎肯定是无效的,因此触发段错误。
内容的提问来源于stack exchange,提问作者Andrew Estes

