C语言scanf("%s")读取字符串仅输出空格前内容的原因咨询
问题原因
scanf("%s", p_texto2)的默认读取规则是从当前输入位置开始读,遇到任意空白字符(空格、换行符、水平制表符等)就立刻终止读取,不会把空白字符及后面的内容写入目标内存。
你输入Hello world时,函数读到Hello后面的空格就停止了,所以p_texto2里只存了Hello,自然读不到带空格的完整内容。
你输出里出现两次Hello也很好解释:第一次printf("%s", p_texto2)打印了一次读到的Hello,后面的while循环逐字符遍历p_texto2又打印了一次Hello,和空格后的内容没有关系。
另外你的代码还有三个隐藏风险:
malloc(tamano)申请内存时没有给字符串末尾必须的\0终止符预留位置,输入长度接近tamano时会出现内存越界- 申请的堆内存使用完没有调用
free()释放,会造成内存泄漏 - 遍历字符串时直接移动了p_texto2的原始指针,后续如果要释放内存会因为指针指向错误触发异常
修正方案
要读取包含空格的整行输入,不要用scanf("%s"),优先替换为更安全的fgets()函数,这是读取含空格输入的标准写法。如果非要用scanf实现,可以用格式符%[^\n]指定读取直到换行符才停止,但这种写法默认不做输入长度限制,很容易触发内存溢出,不推荐在正式代码中使用。
修正后的参考代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> char *p_texto = "Prueba Raul"; char *p_texto2; int main(){ int tamano; printf("Pon el tamaño del string\n"); scanf("%i", &tamano); // 吃掉scanf读数字后留在输入缓冲区的换行符,避免后续fgets直接读到空行 getchar(); // 多申请1字节空间,用于存放字符串必须的'\0'终止符 p_texto2 = (char*)malloc(tamano + 1); printf("Escriba un texto\n"); // 用fgets读取整行输入,支持包含空格的内容,同时限制最大读取长度避免越界 fgets(p_texto2, tamano + 1, stdin); // 去掉fgets默认读入的行尾换行符 p_texto2[strcspn(p_texto2, "\n")] = '\0'; printf("%s\n", p_texto2); // 用临时指针遍历字符串,不修改p_texto2的原始指向,避免后续内存释放出错 char *p_temp = p_texto2; while(*p_temp != '\0'){ printf("%c", *p_temp); p_temp++; } // 释放申请的堆内存,避免内存泄漏 free(p_texto2); return 0; }
运行修正后的代码,输入Hello world即可正常打印包含空格的完整输入内容。
内容的提问来源于stack exchange,提问作者mrc
相关产品推荐
相关产品推荐

