C语言中printf()与fprintf()使用%s参数时的异常行为
你遇到的这个多个字符串字段被自动拼接的问题,本质是结构体里的char数组没有以空字符\0结尾。C语言中,printf("%s")这类字符串处理函数是依靠\0来识别字符串结束位置的——如果数组里没有这个终止符,函数会持续向后读取内存,直到碰到某个\0为止,这就导致了相邻字段的内容被连在一起输出。
结合你的结构体定义来看,比如fname[10]这个字段:如果你给它赋值时填满了10个字符(比如输入了10个字母),数组里就没有多余空间存放\0了,printf就会继续读取后面lname数组的内容,直到找到终止符,最终出现你看到的拼接现象。
下面是几个针对性的解决方法:
手动添加字符串终止符
不管是通过哪种方式给char数组赋值,都要确保数组的最后一个位置被设为\0。比如你手动给fname赋值后,直接设置终止符:// 假设手动赋值了9个字符,第10个位置设为终止符 d.fname[9] = '\0';使用安全的字符串复制函数
用strncpy代替strcpy,它可以限制复制的字符长度,避免数组溢出,之后再手动添加终止符。以fname为例:strncpy(d.fname, source_string, sizeof(d.fname) - 1); d.fname[sizeof(d.fname) - 1] = '\0';这样就算源字符串长度超过数组容量,也只会复制前9个字符,最后一个位置强制设为
\0,保证字符串正常终止。限制输入长度(针对scanf等输入方式)
如果用scanf读取字符串到结构体字段,一定要用带长度限制的格式符,避免输入内容填满数组导致没有\0的位置。比如针对fname[10],要用%9s:scanf("%9s", d.fname);这样
scanf最多读取9个字符,然后自动在末尾添加\0,刚好适配数组的10个空间。
需要注意的是,你结构体里所有的char数组字段(lname、address等)都要遵循这个规则——每个数组都要预留一个位置给\0,赋值或输入的内容长度不能超过数组长度减1。
比如按照正确方式处理后,打印代码就能输出预期的结果:
// 示例赋值 d.id = 1; strncpy(d.fname, "Kalpesh", sizeof(d.fname)-1); d.fname[sizeof(d.fname)-1] = '\0'; strncpy(d.lname, "Rawal", sizeof(d.lname)-1); d.lname[sizeof(d.lname)-1] = '\0'; // 打印 printf("\nData is as follow:\n"); printf("\nID:%d",d.id); printf("\nfname:%s",d.fname); printf("\nlname:%s",d.lname);
此时fname和lname会分别独立输出,不会出现拼接问题。
内容的提问来源于stack exchange,提问作者Kalpesh Rawal

