C语言如何读取含空格字符串?fgets函数参数用法解析
fgets 函数用法说明(重点解释第三个参数)
fgets 的函数原型为 char *fgets(char *str, int n, FILE *stream);,三个参数的含义和传值要求如下:
- 第一个参数:存储读取内容的字符数组首地址,和你用
scanf读字符串时传入的数组名作用一致 - 第二个参数:最大读取字符数,注意 fgets 会自动在读取内容末尾补
\0作为字符串结束标记,因此实际最多读取n-1个有效字符,传值时直接传入目标字符数组的定义长度即可,比如你定义char nome_resp[50],这里就传 50,从根源避免数组越界 - 第三个参数:输入流指针,用来指定读取内容的来源。如果要读取键盘敲入的内容,直接传 C 标准库预置的标准输入流
stdin即可;如果是读取本地文件内容,就传fopen打开文件后返回的文件指针。
你现有代码的典型问题
你目前混用 scanf 和自定义 %[^\n]s 格式串读取带空格字符串,会触发几个常见的C语言输入坑:
scanf读取完输入后,会把你敲回车产生的\n换行符残留在输入缓冲区里,下一次用%[^\n]或者 fgets 读取时,会直接读到这个残留换行,表现为程序直接跳过某一步输入,不让你敲内容%[^\n]s格式串没有限制读取长度,输入过长时会直接写爆字符数组,造成内存溢出,而fgets自带长度限制,天然规避这个问题- 你代码里打印 CPF 时用了
%s格式符,但cpf_resp/cpf_edu定义为int类型,会直接打印乱码;且11位的CPF号码超过了普通int的存储范围(普通int最多存10位十进制数),用字符数组存储更合理,既不会溢出,也能保留号码前导0。
修正后的可运行参考代码
#include <stdio.h> #include <stdlib.h> #include <locale.h> #include <string.h> void funcCadastroDados(); // 工具函数:清空scanf残留在输入缓冲区的换行符 void clearInputBuffer() { int c; while ((c = getchar()) != '\n' && c != EOF); } int main(){ setlocale(LC_ALL, "Portuguese"); funcCadastroDados(); return 0; } void funcCadastroDados(){ system("cls"); char tipo_usuario[20], nome_resp[50], nome_crianca[50], transtorno_crianca[50], email_resp[50], nome_edu[50], nome_crianca_associada[50], email_edu[50]; // CPF、电话号码长度超过int存储范围,改用字符数组存储 char cpf_resp[15], tel_resp[15], cpf_edu[15], tel_edu[15]; printf("Você é pai/responsável da criança ou educador? \nDigite 'responsavel' ou 'educador' \n"); scanf("%s", tipo_usuario); clearInputBuffer(); if ((strcmp(tipo_usuario, "responsavel")) == 0){ printf("Insira o nome do responsável: \n"); fgets(nome_resp, 50, stdin); // fgets会把输入末尾的换行符也读入数组,手动替换为字符串结束符 nome_resp[strcspn(nome_resp, "\n")] = '\0'; printf("Insira o CPF do responsável: \n"); scanf("%s", cpf_resp); clearInputBuffer(); printf("Insira o nome da criança: \n"); fgets(nome_crianca, 50, stdin); nome_crianca[strcspn(nome_crianca, "\n")] = '\0'; printf("Insira o transtorno mental que a criança possui: \n"); fgets(transtorno_crianca, 50, stdin); transtorno_crianca[strcspn(transtorno_crianca, "\n")] = '\0'; printf("Insira o telefone do responsável: \n"); scanf("%s", tel_resp); clearInputBuffer(); printf("Insira o email do responsável: \n"); scanf("%s", email_resp); clearInputBuffer(); printf("\nSeus dados são: \n Nome do responsável: %s \n CPF do responsável: %s \n Nome da criança: %s \n Transtorno mental: %s \n " "Telefone do responsável: %s \n Email do responsável: %s \n", nome_resp, cpf_resp, nome_crianca, transtorno_crianca, tel_resp, email_resp); } else if ((strcmp(tipo_usuario, "educador")) == 0){ printf("Insira o nome do educador: \n"); fgets(nome_edu, 50, stdin); nome_edu[strcspn(nome_edu, "\n")] = '\0'; printf("Insira o CPF do educador: \n"); scanf("%s", cpf_edu); clearInputBuffer(); printf("Insira o nome da criança associada a este educador: \n"); fgets(nome_crianca_associada, 50, stdin); nome_crianca_associada[strcspn(nome_crianca_associada, "\n")] = '\0'; printf("Insira o telefone do educador: \n"); scanf("%s", tel_edu); clearInputBuffer(); printf("Insira o email do educador: \n"); scanf("%s", email_edu); clearInputBuffer(); printf("\nSeus dados são: \n Nome do educador: %s \n CPF do educador: %s \n Nome da criança associada: %s \n Telefone do educador: %s \n" "Email do educador: %s \n", nome_edu, cpf_edu, nome_crianca_associada, tel_edu, email_edu); } }
fgets 使用注意点
- 读取键盘输入时第三个参数固定传
stdin即可,不需要额外定义 - 每次用fgets读完内容后,记得把读入的末尾换行符替换为
\0,否则打印字符串时会多出不必要的空行 - 第二个参数永远不要超过目标字符数组的实际定义长度,否则会触发数组越界bug
内容的提问来源于stack exchange,提问作者arthursleite
相关产品推荐
相关产品推荐

