C语言中从键盘输入字符串时的一些问题[通俗易懂]

C语言中从键盘输入字符串时的一些问题[通俗易懂]C语言中从键盘输入字符串时的一些问题1.scanf()scanf()在输入字符串时有很大的弊端,例如:1).scanf()在从键盘读入字符时并不会根据所定义的字符数组的大小来控制读入多少个,而是从scanf()中传入的地址开始一直访问下一个元素的内存,碰见空格符或者回车符时才停止读入并存入结束符’\0’,这就有可能造成了一个在C中非常严重的问题,访问非法内存.如果…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

C语言中从键盘输入字符串时的一些问题

1.scanf()

scanf()在输入字符串时有很大的弊端, 例如:
1). scanf()在从键盘读入字符时并不会根据所定义的字符数组的大小来控制读入多少个 , 而是从scanf( ) 中传入的地址开始一直访问下一个元素的内存 , 碰见空格符或者回车符时才停止读入并存入结束符’\0’ , 这就有可能造成了一个在C中非常严重的问题 , 访问非法内存 . 如果所输字符数量大于字符数组的长度 , 当scanf()将把字符存入字符数组的最后一个元素后 , scanf()还会继续往后访问内存 , 将接收的字符继续存入 , 但之后的内存是我们未申请的非法内存 , 会发生未知错误 , 例如以下代码:
2). 第二点也就是第一点中的遇到空格符停止读入并存入结束符’\0’, 也就是说scanf()存不了空格符

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define N 10
void main() { 
   
	char str1[N];
	printf("请输入字符串str1\n");
	scanf("%s", str1);
	printf("str1为:\n%s\n",str1);
	system("pause");
}

Jetbrains全家桶1年46,售后保障稳定

代码中 , 字符数组最多存十个元素 , 结果却输出了超过十个的字符并发生了错误程序异常终止
在这里插入图片描述

2.gets()

gets(char* str)函数 , gets()函数与scanf()类似 , 但读入时只碰见 ‘\n’才停止读入并自动加上 ‘\0’,也存在和scanf()一样的访问非法内存的可能 .

最新版本的C标准(2011年)最终将该功能从其规范中删除。该函数在C ++中已弃用(截至2011年标准,遵循C99 + TC3)。所以不建议使用gets()函数

3.fgets()

fgets(char* str, int n,stdin )函数在输入字符串时是从标准输入流中读取一个长度为(n – 1)的字符串 , 并存放到字符数组str中
其中n是要求得到的字符个数 , 但实际上只会读入(n – 1)个,在最后加一个’\0’ . 如果在读取完(n – 1)个字符之前碰见换行符’\n’ ,读入即结束, 但’\n’ 也会作为有效字符存入字符串中,然后在’\n’后再存入’\0’
1). fgets( )函数的优点是不会再像scanf()函数一样发生访问非法内存的问题 , 也可以存如scanf()存不了的空格符
2). 说起缺点 , fgets在取完(n – 1)个字符之前碰见换行符’\n’ ,’\n’ 也会作为有效字符存入字符串中,然后在’\n’后再存入’\0’
在很多时候我们都不希望有这个换行符的出现 , 只能再写代码消去这个’\n’
3). fgets()函数在连续输入多个字符串时(也不能算是fgets()函数的缺点) , 但有时也会给我们带来麻烦) , 例如:
char str1[10];
char str2[10];
在输入str1时输入了超过9个的字符如 : abcdefghigklm\n
这时我们会发现 , str2根本不需要我们重新在键盘输入 , 而是存入了 abcdefghijklm’\n’ 中的 jklm\n
此时
字符串str1是”abcdefghi”
字符串str2是”jklm”
这是因为输入str1的函数在读取标准输入流中的字符时读到 i 时读取完成 , 此时剩下的jklm\n还在缓存区静静地等待被读取
此时fgets()在输入str2时直接读取了缓冲区的 jklm\n由于遇到了’\n’(或者读入了(n – 1)个字符)再存入’\0’,此时str2的输入已经完成 , 并不需要我们再次输入 .
让我们举个例子来看一下这几个特点 :

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define N 10
#include<string.h>
void main() { 
   
	char str[N];
	char str1[N];
	char str2[N];
	printf("请输入字符串str\n");
	fgets(str, N, stdin);
	printf("请输入字符串str1\n");
	fgets(str1, N, stdin);
	printf("请输入字符串str2\n");
	fgets(str2, N, stdin);
	printf("str为:\n%s\n", str);
	printf("str1为:\n%s\n", str1);
	printf("str2为:\n%s\n", str2);
	system("pause");
}

运行时并未像scanf()那样出现越界问题导致程序异常终止的情况 , 但也输出了我们不想看到的 ‘\n’ , str2也并不是从我们再次输入的 , 而是从缓存区直接读取的
在这里插入图片描述

4. 我们也可以利用输入单个字符的函数与循环来输入一个字符串

举个例子 , 如以下代码 :

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define N 10
void main() { 
   
	char str1[N];
	printf("请输入字符串str1\n");
	for (int i = 0, ch;; ++i) { 
   
		ch = getchar();
		if (i == N - 1 || ch == '\n') { 
   
			str1[i] = '
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define N 10
void main() { 

char str1[N];
printf("请输入字符串str1\n");
for (int i = 0, ch;; ++i) { 

ch = getchar();
if (i == N - 1 || ch == '\n') { 

str1[i] = '\0';
break;
}
str1[i] = ch;
}
printf("str1为:\n%s\n", str1);
system("pause");
}
'
; break; } str1[i] = ch; } printf("str1为:\n%s\n", str1); system("pause"); }

可以看出输入也可以不越界
在这里插入图片描述
而且也不会像fgets()函数一样输入的字符串小于数组长度(n – 1)时有换行符 ‘\n’ 的问题
在这里插入图片描述
当然 , 循环形式和输入字符的函数还有其他, 例如, 用scanf(“%c”,ch) 也可以 , 这里就不一 一 举例 .

总之 , 对库函数不满意的话 , 自己也可以写一个符合自己要求的函数或代码来实现 .

例如 :

#include<stdio.h>
#include<stdlib.h>
#define N 10
void fun(char* str) { 
   
	for (int i = 0, ch = '
#include<stdio.h>
#include<stdlib.h>
#define N 10
void fun(char* str) { 

for (int i = 0, ch = '\0'; ch != '\n'; ++i) { 

ch = getchar();
if (i >= N) { 
//当超出字符串长度时, 继续接受键盘输入的字符,直到输入\n为止
//这是为了防止字符串输入完成后输入的字符会被下一个需要输入的数据接收
continue;
}
if (ch == '\n' || i == N - 1) { 

str[i] = '\0';
continue;
}
str[i] = ch;
}
}
void main() { 

char str[N];
char str1[N];
char str2[N];
printf("请输入字符串str\n");
fun(str);
printf("请输入字符串str1\n");
fun(str1);
printf("请输入字符串str2\n");
fun(str2);
printf("str为:\n%s\n", str);
printf("str1为:\n%s\n", str1);
printf("str2为:\n%s\n", str2);
system("pause");
}
'
; ch != '\n'; ++i) { ch = getchar(); if (i >= N) { //当超出字符串长度时, 继续接受键盘输入的字符,直到输入\n为止 //这是为了防止字符串输入完成后输入的字符会被下一个需要输入的数据接收 continue; } if (ch == '\n' || i == N - 1) { str[i] = '
#include<stdio.h>
#include<stdlib.h>
#define N 10
void fun(char* str) { 

for (int i = 0, ch = '\0'; ch != '\n'; ++i) { 

ch = getchar();
if (i >= N) { 
//当超出字符串长度时, 继续接受键盘输入的字符,直到输入\n为止
//这是为了防止字符串输入完成后输入的字符会被下一个需要输入的数据接收
continue;
}
if (ch == '\n' || i == N - 1) { 

str[i] = '\0';
continue;
}
str[i] = ch;
}
}
void main() { 

char str[N];
char str1[N];
char str2[N];
printf("请输入字符串str\n");
fun(str);
printf("请输入字符串str1\n");
fun(str1);
printf("请输入字符串str2\n");
fun(str2);
printf("str为:\n%s\n", str);
printf("str1为:\n%s\n", str1);
printf("str2为:\n%s\n", str2);
system("pause");
}
'
; continue; } str[i] = ch; } } void main() { char str[N]; char str1[N]; char str2[N]; printf("请输入字符串str\n"); fun(str); printf("请输入字符串str1\n"); fun(str1); printf("请输入字符串str2\n"); fun(str2); printf("str为:\n%s\n", str); printf("str1为:\n%s\n", str1); printf("str2为:\n%s\n", str2); system("pause"); }

如图, 即可以输入空格, 也不会越界 , 也没有从缓存区读取字符存入字符数组的问题
这里是引用

小结 :

在C语言中输入一个字符串时应该根据实际情况 , 灵活运用输入方法 , 并不是有缺点就不能用 .
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/234561.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • goland 2021.11.4激活_最新在线免费激活

    (goland 2021.11.4激活)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.html4M7HSKPBXS-eyJsaWNlbnNlSW…

  • 学习vb语言「建议收藏」

    学习vb语言「建议收藏」第一天:昨天完成了安装vb环境今天大概了解了一下vb语言的一些语法,但是把所学的整理出来,一时间却又不知道如何整理。换一个方式,我来看看接下来要学什么。1.vb变量的作用域2.常用的内部函数3.数据的输入和输出4.常用的标准控件5.vb结构控制6.键盘过程7.菜单和对话栏8.数据文件学习这些的基础是今天所学的或者所了解到的1.建立一个vb程序的大致流…

  • 1g的树莓派4b能做什么_树莓派4B开发板简介

    1g的树莓派4b能做什么_树莓派4B开发板简介树莓派简介RaspberryPi(中文名为“树莓派”,简写为RPi,(或者RasPi/RPI)是为学生计算机编程教育而设计,只有信用卡大小的微型电脑,其系统基于Linux,随着Windows10IoT的发布,我们也将可以用上运行Windows的树莓派,别看其外表“娇小”,内“心”却很强大,视频、音频等功能通通皆有,可谓是“麻雀虽小,五脏俱全。树莓派由注册于英国的慈善组织“Raspber…

  • vim 的各种用法,很实用哦,都是本人是在工作中学习和总结的

    vim 的各种用法,很实用哦,都是本人是在工作中学习和总结的

    2021年10月11日
  • 微信自动发送消息

    微信自动发送消息前提:今天加入微信辅助大军,奈何要一直去群里发广告,又懒又烦!!!于是乎,想到能不能自动去打广告~可以的~哈哈方案:最近在看api文档,就最先想到能不能java模拟发送信息,但是又没头绪(放弃)然后百度了相关信息,得出①脚本精灵录制(直接趴,这不是自己编程该有的风格)②微信网页版(js脚本)大致思路:1、遍历好友列表(避免发错

  • flutter 存储_map根据key获取value

    flutter 存储_map根据key获取valueFlutter持久化存储之key-value存储

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号