c语言中比较特殊的输入格式
目录
一.%[ ] 格式说明符
1.基本用法
(1)读取字母字符:
(2)读取数字字符:
(3)读取所有字符直到遇到空格:
(4)读取直到换行符:
2.使用范围和组合:
3.^ 取反操作
4.注意事项
(1). 字符范围的正确表示
(2). 避免字符集中的特殊字符冲突
(3).避免空字符集
(4). 输入长度的控制
(5). 换行符和空格的处理
解决方法
修改后的代码
(6). 字符集的顺序和位置
(7). 检查返回值
二.%*抑制符
1.基本用法
用途
(1).跳过某些数据
(2).跳过特定格式的数据
(3).跳过特定字符
2.注意事项
三.%n 格式说明符
1.基本用法
(1)简单用法
(2)跟踪多个输入
(3)复杂输入的验证
2.注意事项
一.%[ ]
格式说明符
在C语言中,
scanf
函数中的%[ ]
格式说明符是一种非常灵活的方式,可以用来读取满足特定条件的一系列字符。%[ ]
格式说明符允许程序员定义一个字符集,scanf
会连续读取输入流中的字符,直到遇到不属于该字符集的字符为止。
ps:通常情况下,scanf
会自动跳过空白字符(包括换行符),但是%[ ]
这种格式说明符是一个例外。
1.基本用法
scanf("%[character_set]", string);
character_set
: 这是一个字符集,它可以是特定字符或字符范围。string
: 这是一个字符数组(字符串),用来存储读取到的字符。
举例说明:
(1)读取字母字符:
char str[100];
scanf("%[a-zA-Z]", str); // 只读取字母字符 (大小写)
printf("读取到的字母是: %s\n", str);
输入: abc123
输出: 读取到的字母是: abc
解释: scanf
会从输入流中读取所有属于 a-zA-Z
的字符,一旦遇到不属于该范围的字符(如数字 1
),它将停止读取。
(2)读取数字字符:
char numStr[100];
scanf("%[0-9]", numStr); // 只读取数字字符
printf("读取到的数字是: %s\n", numStr);
输入: 123abc
输出: 读取到的数字是: 123
解释: 这里 scanf
只会读取数字字符(0到9),直到遇到非数字字符。
(3)读取所有字符直到遇到空格:
char str[100];
scanf("%[^ ]", str); // 读取所有字符直到遇到空格
printf("读取到的内容是: %s\n", str);
输入: hello world
输出: 读取到的内容是: hello
解释: scanf
会读取所有字符,直到遇到空格(
)为止。^
表示“除指定字符之外的所有字符”。
(4)读取直到换行符:
char line[100];
scanf("%[^\n]", line); // 读取一整行,直到换行符
printf("读取到的行是: %s\n", line);
输入: Hello, world!
输出: 读取到的行是: Hello, world!
解释: scanf
会读取所有字符,直到遇到换行符 \n
为止。即回车
2.使用范围和组合:
- 范围: 可以通过
-
来表示一个字符范围,例如[a-z]
表示所有小写字母。- 多个范围和字符: 你可以结合多个字符集或字符范围,例如
"[a-zA-Z0-9]"
会匹配所有字母和数字。
char str[100];
scanf("%[a-zA-Z0-9]", str); // 读取字母和数字
printf("读取到的内容是: %s\n", str);
输入: abc123!@#
输出: 读取到的内容是: abc123
解释: 这里 scanf
读取了字母和数字,直到遇到非字母非数字字符。
3.^
取反操作
取反: 在字符集的开头加上
^
符号表示取反,即读取不属于该字符集的字符。
char str[100];
scanf("%[^,]", str); // 读取直到遇到逗号
printf("读取到的内容是: %s\n", str);
输入: Hello,world
输出: 读取到的内容是: Hello
解释: 这里 scanf
读取了所有字符,直到遇到逗号 ,
为止,因为 [^,]
表示“除逗号之外的所有字符”。
4.注意事项
(1). 字符范围的正确表示
范围表示法:
a-z
、A-Z
、0-9
这些范围表示法必须是有效的字符序列。a-z
表示小写字母从a
到z
的所有字符,A-Z
表示大写字母从A
到Z
的所有字符,0-9
表示所有数字字符。错误的表示:
z-a
、9-0
这样的表示是无效的,会导致意外的行为。
char str[100];
scanf("%[z-a]", str); // 无效:z-a不是有效范围
(2). 避免字符集中的特殊字符冲突
连字符
-
的使用:连字符-
用于指定范围,但如果它被放置在错误的位置,可能会引起解析错误或未定义行为。
- 正确:
[a-z]
,[0-9A-F]
。- 错误:
[-z]
(这里连字符和z
之间没有起始字符,这种用法可能会导致未定义行为)。特殊用法:
- 开始位置: 如果要包含
-
本身,可以把它放在范围的起始位置,如[-a-z]
,表示-
和a
到z
的所有字符。- 结束位置: 如果连字符在字符集的末尾,如
[a-z-]
,它表示a
到z
的所有字符和-
字符。
char str[100];
scanf("%[-a-zA-Z]", str); // 读取`-`或字母
(3).避免空字符集
空字符集:
scanf
的%[ ]
如果是空字符集,scanf
会直接返回而不做任何操作,因此要确保字符集内包含有效内容。错误:
char str[100];
scanf("%[]", str); // 空字符集,`scanf`什么都不会读取
(4). 输入长度的控制
缓冲区溢出:
scanf
使用%[ ]
时没有自动限制读取的字符数。如果输入的字符超过了数组的容量,可能会导致缓冲区溢出。因此,建议使用宽度限定符来限制读取的最大字符数。
char str[100];
scanf("%99[a-zA-Z0-9]", str); // 最多读取99个字符,保留1个字符给结束符`'\0'`
(5). 换行符和空格的处理
换行符问题:
%[ ]
读取字符时不会消耗换行符\n
。这可能会导致在之后的scanf
或getchar
调用中,直接读取到换行符。如果需要处理换行符,可以在之后使用getchar()
来消耗这个换行符。
可能大伙还是不懂,继续往下看:
假设你有以下代码:
char str[100];
scanf("%[a-zA-Z]", str);
- 输入:
hello\nworld
scanf("%[a-zA-Z]", str)
会读取并存储字符串"hello"
,但它不会读取或消耗换行符\n
。- 换行符
\n
仍然留在输入流中,等待下一次scanf
或其他输入函数处理。
如果你随后调用scanf
来读取另一个输入:
scanf("%d", &num);
- 因为之前的换行符
\n
还在输入流中,scanf("%d", &num)
会遇到这个换行符,并立即返回,通常会导致输入错误或跳过输入。
解决方法
为了避免这个问题,可以在调用scanf("%[ ]", ...)
后手动读取并消耗掉换行符,通常通过getchar()
来实现。
修改后的代码
char str[100];
scanf("%[a-zA-Z]", str);
getchar(); // 手动读取并消耗掉换行符
解释: 在读取完字符串后,getchar()
将读取并消耗掉输入流中的换行符,使得后续的scanf
调用不会受到影响。
空白字符的忽略:
scanf
的%[ ]
不会自动跳过空白字符(如空格、制表符、换行符等),除非在字符集中明确包含这些字符
char str[100];
scanf("%[a-zA-Z0-9 ]", str); // 允许读取空格字符
(6). 字符集的顺序和位置
顺序影响: 字符集的顺序不会影响
scanf
的行为,但是清晰的字符集顺序更易于理解和维护代码。例如[a-zA-Z0-9]
比[z-aZ-A9-0]
更易读。排除特殊字符: 如果你想排除特定字符集中的某些字符,可以使用
[^ ]
,如[^a-zA-Z0-9]
来读取非字母、数字的字符。
(7). 检查返回值
scanf
的返回值:scanf
返回成功读取的项目数。可以通过检查返回值来判断输入是否成功匹配。
char str[100];
int n = scanf("%99[a-zA-Z0-9]", str);
if (n == 1) {printf("读取成功: %s\n", str);
} else {printf("输入格式不匹配或读取失败\n");
}
ps:在scanf
的语境中,"项目"通常指的是一个成功读取并存储到对应变量中的数据单元。因此,str
在这个上下文中确实被视为一个项目。
二.%*抑制符
在C语言的
scanf
函数中,%*
被称为“抑制符”(或者“跳过符”)。它的作用是告诉scanf
函数读取数据但不存储它。换句话说,scanf
会解析输入数据并跳过该数据,而不将其赋值给任何变量。
1.基本用法
scanf("%*d"); // 读取并跳过一个整数
在这个例子中,scanf
会从输入中读取一个整数,但不会将其存储在任何变量中。%*
与任何有效的格式说明符结合使用,都会导致该数据被读取但不会存储。
用途
-
跳过不需要的数据:有时候你可能只需要读取输入中的部分数据,而对其他部分的数据不感兴趣。这时候可以使用
%*
来跳过不需要的数据。 -
处理复杂的输入:如果输入数据格式比较复杂,你可以通过
%*
来跳过一些无关的部分,只提取你感兴趣的数据。
示例
(1).跳过某些数据
#include <stdio.h>int main() {int a, c;scanf("%d %*d %d", &a, &c);printf("a = %d, c = %d\n", a, c);return 0;
}
输入: 1 2 3
输出: a = 1, c = 3
解释: 这个程序通过%d
读取了第一个整数1
并将其存储在a
中,然后通过%*d
读取了第二个整数2
但没有存储它,最后通过%d
读取了第三个整数3
并将其存储在c
中。
(2).跳过特定格式的数据
#include <stdio.h>int main() {char name[50];int age;scanf("%*s %d", &age);printf("Age: %d\n", age);return 0;
}
输入: John 25
输出: Age: 25
解释: 这里%*s
会跳过输入的第一个字符串(John
),然后%d
读取第二个整数(25
)并将其存储在age
中。
*
的多种组合使用
*
可以与任何scanf
的格式说明符结合使用,例如:
%*c
: 读取并跳过一个字符。%*f
: 读取并跳过一个浮点数。%*s
: 读取并跳过一个字符串。%*[]
: 读取并跳过一组符合特定字符集的字符。
(3).跳过特定字符
#include <stdio.h>int main() {int year, month, day;scanf("%d-%*d-%d", &year, &day);printf("Year: %d, Day: %d\n", year, day);return 0;
}
输入: 2024-08-13
输出: Year: 2024, Day: 13
解释: 这里%d
读取年份2024
,%*d
跳过月份08
,然后%d
读取日期13
。
2.注意事项
不会增加返回的项目数: 被
%*
抑制符忽略的数据不会被计入scanf
返回的成功读取项目数。例如,如果scanf
成功读取两个变量而跳过一个数据,它的返回值是2
,而不是3
。格式匹配问题:
scanf
依然会验证被跳过的数据是否符合指定格式,如果输入数据不符合指定的格式,scanf
会停止读取。输入缓冲区影响: 即使数据被跳过,输入缓冲区中的数据仍然会被消耗掉,因此后续的
scanf
调用不会再看到这些数据。
三.%n 格式说明符
%n
是C语言中scanf
函数的一种特殊格式说明符。它用于将到目前为止已经读取的字符数存储到一个整数变量中。与其他格式说明符不同,%n
并不会从输入中读取数据并与其对应的数据类型匹配,而是直接记录scanf
已经成功处理的字符数量。
1.基本用法
scanf("%d%n", &value, &num_chars);
在这个例子中,scanf
会读取一个整数并将其存储在value
中,接着,它会把读取到该整数为止所消耗的字符数存储在num_chars
中。
scanf
中的%n
格式说明符
-
不消耗输入:
%n
本身不消耗输入字符。它只是在内部计算并存储从输入流中已经读取的字符数。 -
存储读取字符的数量:
%n
会将到达它的位置为止读取的总字符数存储在其对应的参数中。这个参数必须是指向int
类型的指针。 -
多个
%n
: 如果在一个scanf
调用中出现多个%n
,每个%n
都会记录到目前为止从输入流中读取的字符数。因此可以用它来跟踪输入过程中的不同点。
示例
(1)简单用法
#include <stdio.h>int main() {int value, num_chars;scanf("%d%n", &value, &num_chars);printf("Value: %d, Characters read: %d\n", value, num_chars);return 0;
}
输入: 12345
输出: Value: 12345, Characters read: 5
解释: 在输入12345
之后,scanf
将12345
存储在value
中,而%n
记录并存储了读取字符的数量(5个字符)。
(2)跟踪多个输入
#include <stdio.h>int main() {int a, b;int num_chars1, num_chars2;scanf("%d%n %d%n", &a, &num_chars1, &b, &num_chars2);printf("a = %d, b = %d\n", a, b);printf("Characters read for a: %d, total characters read: %d\n", num_chars1, num_chars2);return 0;
}
输入: 12 34
输出:a = 12, b = 34
Characters read for a: 2, total characters read: 5
解释:
- 在读取完第一个整数
12
后,num_chars1
存储了已经读取的字符数(2个字符)。 - 在读取完第二个整数
34
后,num_chars2
存储了总的字符数(5个字符,包括中间的空格)。
(3)复杂输入的验证
#include <stdio.h>int main() {int day, month, year;int chars_read;scanf("%2d/%2d/%4d%n", &day, &month, &year, &chars_read);if (chars_read == 10) {printf("Valid date: %02d/%02d/%04d\n", day, month, year);} else {printf("Invalid date format.\n");}return 0;
}
输入: 15/08/2024
输出: Valid date: 15/08/2024
解释:
- 这个程序读取日期并确保输入格式为
dd/mm/yyyy
(总共10个字符)。 - 如果读取的字符数正好是10个字符,那么输入是有效的,否则输出无效格式。
2.注意事项
安全性问题: 使用
%n
时,确保对应的参数是有效的int*
指针,否则会导致未定义行为。这也是它不常用于现代C编程的原因之一,因为如果误用会导致潜在的安全漏洞。
scanf
返回值不包含%n
:scanf
返回的成功读取项目数不包括%n
。所以,即使%n
在scanf
中使用,它也不会影响scanf
的返回值。与其他格式说明符的组合:
scanf
会按照顺序解析格式说明符,如果在使用%n
之前的格式说明符解析失败,%n
就不会被执行。可能的用途:
- 输入格式检查: 可以通过检查读取的字符数来确保输入符合预期格式。
- 精确输入解析: 当你需要知道输入的精确位置(如进行复杂的文本处理)时,可以使用
%n
。
完
相关文章:

c语言中比较特殊的输入格式
目录 一.%[ ] 格式说明符 1.基本用法 (1)读取字母字符: (2)读取数字字符: (3)读取所有字符直到遇到空格: (4)读取直到换行符: 2.使用范围和组合: 3.^ 取反操作 4.注意事项 (1). 字符范围的正确表示 (2). 避免字符集中的特殊字符冲突 (3).避免空字符集 (4). 输入长…...

远程命令行控制SSH
第一次接触SSH是ROS小车作为服务端,通过ubuntu电脑客户端访问。因为机器人接键盘和屏幕操作起来不方便,所以使用SSH进行连接,方便对小车的操作。 1.服务端安装 打开终端查看ssh是否安装 sudo service ssh status 如果未安装 sudo apt upd…...

钢铁百科:A572Gr60和SA572Gr60材质分析、A572Gr60和SA572Gr60简介
A572Gr60和SA572Gr60是两种常用的结构钢板,它们在材质、执行标准、化学成分、力学性能、交货状态、应用范围和常用规格方面有所不同。 材质: A572Gr60:属于美国材料与试验协会(ASTM)标准下的A572系列高性能结构钢&…...

一次sql请求,返回分页数据和总条数
日常搬砖,总少不了需要获取分页数据和总行数。 一直以来的实践是编码两次sql请求,分别拉分页数据和totalCount。 最近我在思考: 常规实践为什么不是 在一次sql请求中中执行多次sql查询或多次更新,显而易见的优势: ① 能…...

2.5 pyautogui 实现微信自动回复
第四节:实战微信自动回复 课程目标 学习如何通过pyautogui完成微信自动回复 课程内容 编码实现 import pyautogui as pg import time from pyautogui import ImageNotFoundException import pyperclip from cnocr import CnOcr import random ocr CnOcr() msg…...

观存储历史,论数据未来
数据存储 这几天我反复观看了腾讯云社区的《中国数据库前世今生》纪录片,每次的感受都大相径庭。以下是我在这段时间里对纪录片的两个不同感想,希望感兴趣的小伙伴们也能去观看一番。 一个是关于国产数据库的发展趋势的探讨:https://blog.c…...

linux:对目录的操作
一、对目录操作 1,打开目标目录 2.读取目录,, 3.关闭目录 目录 当文件看,只不过操作函数和操作文件函数不一样。 *1.opendir DIR *opendir(const char *name); 功能:打开一个目录获得一个目录流指针 参数:name:目录名 返回值…...

详解Redis 高可用的方式 Redis Cluster
Redis 高可用方式 Redis 提供了多种高可用性方案,主要包括以下几种方式: 主从复制(Replication) 主从复制是最基本的高可用性方案,通过将数据从一个主节点复制到多个从节点来实现数据的冗余和读写分离。主节点负责所…...

$clog2(1)=0
项目场景: 写ip 时, 使用参数化的方式实现2w1r 时,出现计算读返回index 时,减下溢! 问题描述 verilog中会使用parameter 参数化,例如使用dpth 和$clog2(dpth)addr 。 常见的写法没有什么问题。 module …...

开发学习日记1
用这个系列博客记录下学习开发的一些小收获 git的使用: 说来惭愧,学到了大二,git的使用还是一团糟,记录一下如何使用git进行团队合作开发 当要加入其他人的项目时首先你要创建自己的分支(克隆一下其他分支ÿ…...

孙宇晨领航波场TRON:引领数字资产迈向崭新纪元
在风起云涌的数字资产领域,孙宇晨这个名字始终与创新、突破和引领紧密相连。作为波场TRON的创始人,他不仅是一位远见卓识的领导者,更是推动数字资产迈向新纪元的坚实力量。 自波场TRON诞生以来,孙宇晨便以其敏锐的洞察力…...

python运维(twenty-four day)
一、python基础 1、环境python2、python3 [rootpython ~]# yum list installed | grep python #检查是否有python包 [rootpython ~]# yum list installed | grep epel #检查是否有epel包 [rootpython ~]# yum -y install epel-release [rootpython ~]# yum -y instal…...

Eureka原理实践
1. 简介 1.1. 概述 Eureka是Netflix开源的一个服务注册与发现框架,它在微服务架构中扮演着至关重要的角色。 Eureka由两个核心组件组成: Eureka Server(服务注册中心):负责存储、管理和提供服务实例信息,如服务名、IP地址、端口号等。Eureka Server通常采用集群部署以保…...

Ant-Design-Vue快速上手指南+排坑
1. 简介 1.1. 概述 Ant-Design-Vue是由阿里巴巴开源的一个基于Vue.js框架的企业级UI设计语言。它旨在帮助开发者构建设计优雅、体验流畅的企业级应用。Ant-Design-Vue提供了一系列高质量的Vue组件,包括表单、表格、布局、导航、图标等,可以帮助开发者快速搭建应用程序界面。…...

mysql5.7安装
1.创建一个software文件 2.先下载mysql的repo源 wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm 3安装源包 rpm -ivh mysql-community-release-el7-5.noarch.rpm 可能会报错 改成命令 rpm -ivh mysql-community-release-el7-5.noarch.rpm --nodeps…...

UE开发中的设计模式(三) —— 对象池模式
在FPS游戏中,射击会生成子弹,在命中敌人后子弹会被销毁,那么会导致子弹对象频繁地创建和销毁,会造成运行效率降低且会产生内存碎片问题,而对象池模式可以很好地解决这个问题。 文章目录 问题提出概述问题解决总结 问题…...

Mocha测试框架:JavaScript自动化测试的瑞士军刀
在JavaScript开发中,自动化测试是确保代码质量和可靠性的关键环节。Mocha是一个广泛使用的JavaScript测试框架,它支持多种断言库,允许开发者编写简洁、灵活的测试用例。Mocha特别适用于Node.js环境,但也可以在浏览器中运行。本文将…...

flask实现Streaming内容传输
当传输大量内存,以至于超出内存大小,一般http服务器会报500错误,这时可以使用Streaming流的方式来传输内容,类似ChatGPT和视频流那样的输出方式,flask里要用到生成器和直接响应。 from flask import stream_with_cont…...

seata的使用(SpringBoot项目整合seata)
文章目录 1、解压 seata-server-1.7.1.zip2、启动 双击 seata-server.bat3、启动 seata 控制台用户界面4、所有分布式事务相关数据库要有undo-log5、项目引入seata依赖6、项目添加seata配置7、代码实现: 1、解压 seata-server-1.7.1.zip 2、启动 双击 seata-server.…...

docker容器和宿主机网络不通
防火墙未开启,检查网络配置无异常 解决: [rootlocalhost ~]# vim /etc/sysctl.confnet.bridge.beidge-nf-call-iptables 1 net.bridge.beidge-nf-call-ip6tables 1[rootlocalhost ~]# sysctl -p [rootlocalhost ~]# systemctl restart docker 如果网…...

编程学习之旅:高效记录与整理笔记的艺术
引言:知识的海洋与导航的灯塔 在编程的浩瀚星空中,每一位学习者都像是勇敢的航海家,驾驶着知识的帆船,在无尽的信息海洋中探索未知的领域。然而,这片海洋既充满了机遇,也潜藏着挑战。信息的过载、知识的碎…...

dev c++中,在C++11模式下编译带M_PI宏的文件报错的解决办法
一、问题描述 当使用C11的模式,编译引用了math库中的M_PI的源文件时,报M_PI未声明的错误。 二、问题原因 因为M_PI是GNU扩展的宏,它不属于C11的标准,而-stdc11,表示以C11的标准进行编译,因此会产生以上问…...

【ubutnu24.04】k8s部署2:摸索修复问题
1.30.0 一直init失败有人说版本兼容问题重新安装了最新的1.31.0 版本kubeadm init 仍旧失败。安装依赖项 sudo apt-get install -y apt-transport-https ca-certificates curl gpgroot@PerfSvr:/home/zhangbin/perfwork/k8sadmin# sudo apt-get install -y apt-transport-https…...

处理JSON数据时遇到的解析错误:“Unexpected character (`“`)”
问题背景 在开发过程中,经常会遇到需要解析JSON数据的情况。然而,在某些情况下,可能会遇到类似“Unexpected character (")”这样的错误。本文将详细介绍该错误的原因、如何诊断以及解决方法。 错误示例 以下是一个典型的错误信息示例…...

RDKit|分子输入输出格式解析(如 SMILES、Mol、SDF)
2.3 分子输入输出格式解析(如 SMILES、Mol、SDF) 在化学信息学中,分子的表示方式有很多种,常见的包括 SMILES、Mol 文件、SDF 文件等。RDKit 支持对这些格式的分子数据进行解析和处理,这使得它在化学和药物设计领域得到了广泛应用。本节将介绍如何在 RDKit 中解析和操作这…...

【模电笔记】——反馈放大电路
tips:本章节的笔记已经打包到word文档里啦,建议大家下载文章顶部资源(有时看不到是在审核中,等等就能下载了。手机端下载后里面的插图可能会乱,建议电脑下载,兼容性更好且易于观看),…...

【面试题】Redis缓存问题全解:击穿、雪崩与穿透
文章目录 Redis缓存问题全解:击穿、雪崩与穿透引言1. 缓存击穿(Cache Penetration)2. 缓存雪崩(Cache Avalanche)3. 缓存穿透(Cache Penetration) 总结1. 缓存击穿(Cache Penetratio…...

676. 实现一个魔法字典
676. 实现一个魔法字典 题目链接:676. 实现一个魔法字典 代码如下: class MagicDictionary { public:MagicDictionary() {}void buildDict(vector<string> dictionary) {wordsdictionary;}bool search(string searchWord) {for(const auto&…...

Spring Boot 入门以及对微服务的理解
目录 1.Spring Boot 简介 1.1什么是自动装配 1.2什么是内嵌Tomcat 2.微服务 2.1单体应用系统 2.2分布式应用系统 2.3微服务 2.3.1什么是微服务 微服务有哪些优点 微服务有哪些缺点 2.3.2为什么选择微服务 1.Spring Boot 简介 Spring Boot 是简化 Spring 应用开发的…...

仿RabbiteMq实现简易消息队列正式篇(需求分析)
TOC 目录 MQ的实现方法 RabbitMq中的相关概念 消息队列系统模块划分 总体划分 服务端模块 数据管理模块 虚拟机数据管理模块 交换机路由模块 消费者管理模块 信道(通信)管理模块 连接管理模块 服务端BrokerServer模块 客户端模块 消费者管…...