个人主页:
一位搞嵌入式的 genius-CSDN博客https://blog.csdn.net/m0_73589512?spm=1010.2135.3001.5343点关注不迷路哟。你的点赞、收藏,一键三连,是我持续更新的动力哟!!!
目录
Day03:输入输出(上)
Day03→嵌入式开发输入输出(上)
知识纲要
数据输出
1)C 语言 IO 特性
2)字符输出函数(putchar)
例题:putchar 函数应用
3)编程应用
例题:ASCII 码值输出
格式输出函数(printf)
1)printf 函数基础
2)格式字符
3)应用案例
例题:整数打印格式
例题:各种类型数据输出
知识小结
Day03→嵌入式开发输入输出(下)
附加格式说明符
1. 域宽控制(m)
2. 精度控制(.n)
3. 对齐方式(-)
4. 符号显示(+)
5. 零填充(0)
输出函数格式字符应用实例
1. 例题:百分比符号与进制前缀(#)
2. 例题:整数与浮点数格式组合
3. 例题:字符串格式控制
格式输出函数的特殊场景
1. 零填充与符号位
2. 精度与宽度的优先级
总结与思考
知识小结
Day03:输入输出(下)
字符输入函数
1)字符输入函数 getchar
函数基本说明
返回值类型说明
例题:字符输入输出示例
错误处理机制
格式输入函数 scanf
1)scanf 基本用法
例题:scanf 基本用法
2)scanf 格式符应用
常用格式符
输入提示规范
3)scanf 返回值应用
4)scanf 修饰符应用
类型修饰符
宽度控制符(m)
抑制符(*)
5)字符变量输入注意
内容总结
1)字符输入函数 getchar
2)格式输入函数 scanf
3)学习建议
知识小结
Day03:输入输出(下)补充
一、嵌入式开发输入输出核心内容解析
1. 输入函数留下的 “垃圾” 及处理方法
2. 字符串输入输出函数
(1)输入函数gets
(2)输出函数puts
3. 应用案例:一元二次方程根的计算
二、知识小结与重点提示
三、思考问题解答
学习路径:从数据类型→常量变量→运算符→完整语句的递进过程,输入输出是连接程序与外部交互的核心环节。
语句重要性:输入输出语句是编程中最频繁使用的语句类型,例如经典的 "Hello World" 程序就是通过输出语句实现的。
实现机制:C 语言本身没有内置的 I/O 语句,所有输入输出操作都通过标准库函数(如printf
、putchar
)实现。
头文件:使用输入输出函数前必须包含头文件 #include
,否则会导致编译错误。
函数格式:putchar(c)
参数类型:接受字符常量、变量或表达式(实际参数类型为int
,对应字符的 ASCII 码值)。
功能:将单个字符输出到显示器(如控制台)。
返回值:成功时返回所输出字符的 ASCII 码值(实际开发中较少关注此返回值)。
#includeint main() { int c = 65; // 整型变量(对应'A'的ASCII码) char a = 'B'; // 字符变量 putchar(c); // 输出:A putchar(a); // 输出:B putchar('\n'); // 输出换行符(ASCII码10) putchar('a' + 1); // 表达式参数('a'+1='b'),输出:b return 0; }
参数多样性:
可直接使用整型变量(如int c=65
输出 'A');
可使用字符常量(如'\n'
实现换行);
可使用字符变量(如char a='B'
输出 'B')。
ASCII 知识:
大写字母 A-Z 的 ASCII 码为 65-90;
小写字母 a-z 的 ASCII 码为 97-122;
大小写转换可通过加减 32 实现(如'A' + 32 = 'a'
)。
开发习惯:学习新函数时应养成查阅手册的习惯(如 Linux 系统中使用man putchar
查看函数详情)。
类型转换:字符型参数会自动转换为对应 ASCII 码的整型值(因putchar
参数本质是int
)。
#includeint main() { putchar(65); // 输出字符'A'(65是'A'的ASCII码) putchar('B'); // 直接输出字符'B' putchar('\n'); // 换行 return 0; }
输出验证:整型 65 对应字符 'A',字符 'B' 直接输出,'\n'
实现换行。
函数格式:printf("格式控制串", 输出表)
组成要素:
格式控制串:包含普通字符(直接输出)和格式说明符(以%
开头,指定输出格式)。
输出表:要输出的数据列表(变量、常量或表达式),需与格式说明符的数量和类型一一对应。
类型 | 格式说明符 | 功能描述 |
---|---|---|
整型 | %d /%i |
以十进制整数形式输出 |
%x /%X |
以十六进制无符号整数形式输出(%x 用小写 a-f,%X 用大写 A-F) |
|
%o |
以八进制无符号整数形式输出 | |
%u |
以无符号十进制整数形式输出 | |
字符 | %c |
输出单个字符(按 ASCII 码解析) |
%s |
输出字符串(需以'\0' 结尾的字符数组) |
|
浮点型 | %f |
以小数形式输出(默认保留 6 位小数) |
%e /%E |
以指数形式输出(%e 用小写 e,%E 用大写 E) |
|
%g /%G |
自动选择%f 或%e (%G 对应%F 和%E )中更简洁的形式输出 |
|
特殊 | %% |
输出百分号本身(因% 是格式符前缀,需用%% 转义) |
#includeint main() { int num = 254; printf("十进制:%d\n", num); // 输出:十进制:254 printf("十六进制:%x\n", num); // 输出:十六进制:fe printf("八进制:%o\n", num); // 输出:八进制:376 return 0; }
进制转换技巧:
十六进制中,255 对应FF
,254 对应FE
(递减 1);
八进制中,1 位八进制数对应 3 位二进制数(如376
拆分为3
、7
、6
,对应二进制011 111 110
)。
#includeint main() { int a = 65; char ch = 'A'; float f = 3.1415926; char str[] = "Hello"; // 整型的多进制输出 printf("整型:%d(十进制) %o(八进制) %x(十六进制)\n", a, a, a); // 字符的两种输出形式 printf("字符:%c(字符形式) %d(ASCII值)\n", ch, ch); // 浮点型的多种输出 printf("浮点:%f(小数) %e(科学计数法) %g(自动选择)\n", f, f, f); // 字符串输出 printf("字符串:%s\n", str); return 0; }
输出结果:
整型:65(十进制) 101(八进制) 41(十六进制) 字符:A(字符形式) 65(ASCII值) 浮点:3.141593(小数) 3.141593e+00(科学计数法) 3.14159(自动选择) 字符串:Hello
知识点 | 核心内容 | 考试重点 / 易混淆点 | 难度系数 |
---|---|---|---|
字符输出函数(putchar) | 功能:输出单个字符;参数为字符的 ASCII 码值(int 类型);返回值为输出字符的 ASCII 码。 | 参数类型为int 而非char (因 ASCII 范围 0-255 可能超出signed char 的表示范围);特殊字符'\n' (换行)的使用。 |
⭐⭐ |
格式输出函数(printf) | 功能:格式化输出多类型数据;由格式控制串(含% 修饰符)和输出表组成。 |
格式符与参数的匹配规则(数量、类型必须一致);%d (十进制)、%x (十六进制)、%o (八进制)的区别。 |
⭐⭐⭐ |
数据类型与格式符对照 | 整型对应%d /%o /%x ;字符对应%c (字符)和%d (ASCII 值);浮点对应%f /%e /%g 。 |
%g 会自动省略无意义的小数位(如3.140000 用%g 输出为3.14 );字符与整型的互通性(字符变量可用%d 输出 ASCII 值)。 |
⭐⭐ |
输入输出函数头文件 | 必须包含#include 才能使用printf 、putchar 等函数。 |
易忽略头文件导致编译错误(如error: 'printf' undeclared )。 |
⭐ |
编程思维训练 | 学习函数的三步法:明确功能→理解参数→关注返回值;强调实践的重要性。 | 理解语法不等于掌握,需通过反复编码巩固(如手动实现不同类型数据的输出)。 |
格式说明符的通用形式为 %[修饰符]格式字符
,其中修饰符用于控制输出的宽度、精度、对齐方式等细节。
功能:指定输出数据的最小宽度(占 m 个字符位置)。
规则:
若数据实际长度 < m:不足部分补空格(默认右对齐)。
若数据实际长度 ≥ m:忽略宽度限制,按实际长度输出。
示例:
printf("%8d\n", 123); // 输出:" 123"(前补5个空格,共8位) printf("%8d\n", 123456789); // 输出:"123456789"(超长,按实际输出)
对实数(% f/% e/% g)
:指定小数点后保留 n 位小数(四舍五入)。
示例:printf("%.2f\n", 3.14159);
→ 输出:3.14
对字符串(% s)
:指定只输出前 n 个字符(截断)。
示例:printf("%.5s\n", "HelloWorld");
→ 输出:Hello
对整数(% d/% o/% x)
:指定最小输出位数,不足补 0(若 n=0 且数据为 0,则输出空)。
示例:printf("%.4d\n", 12);
→ 输出:0012
默认:右对齐(不足补空格在左侧)。
左对齐:
在域宽前加
-
,不足补空格在右侧。
示例:printf("%-8d\n", 123);
→ 输出:123
(后补 5 个空格)
功能:强制显示正数的正号(+
),负数仍显示 -
。
示例:
printf("%+d\n", 123); // 输出:"+123" printf("%+d\n", -123); // 输出:"-123"
功能:域宽不足时,用 0 填充(而非空格),零填充在符号位之后。
示例:printf("%08d\n", 123);
→ 输出:00000123
(共 8 位,前补 5 个 0)
输出百分号:
用
%%
表示(因
%
是格式符前缀,需转义)。
示例:printf("%.2f%%\n", 3.14);
→ 输出:3.14%
进制前缀:
#
修饰符为八进制(
%o
)加前缀
0
,为十六进制(
%x/%X
)加前缀
0x/0X
。
示例:
printf("%#o\n", 65); // 输出:"0101"(八进制前缀0) printf("%#x\n", 65); // 输出:"0x41"(十六进制前缀0x)
整数宽度与零填充:
printf("%8d\n", 1234); // 输出:" 1234"(右对齐,前补4空格) printf("%08d\n", 1234); // 输出:"00001234"(零填充,共8位)
浮点数宽度与精度:
// 总宽8位,保留1位小数(四舍五入),右对齐 printf("%8.1f\n", 123.456); // 输出:" 123.5"
截断与宽度:
// 总宽10位,截取前5个字符,右对齐(前补5空格) printf("%10.5s\n", "HelloWorld"); // 输出:" Hello" // 仅截断,不限制宽度 printf("%.3s\n", "Hello"); // 输出:"Hel"
零填充会在符号位之后填充,不影响符号显示:
printf("%08d\n", -123); // 输出:"-0000123"(符号位占1位,后补4个0) printf("%+08d\n", 123); // 输出:"+0000123"(+号占1位,后补4个0)
浮点数的精度(小数位数)优先级高于宽度:
// 宽度2 < 实际长度(至少5位:123.4),但仍保证1位小数 printf("%2.1f\n", 123.45); // 输出:"123.5"
核心函数:
putchar
:仅输出单个字符(参数为 ASCII 码)。
printf
:支持多类型数据的格式化输出,通过格式符控制细节。
格式符记忆技巧:
宽度 m
:控制 “占几位”(不足补空格 / 0)。
精度 n
:控制 “留几位”(小数位或字符串长度)。
修饰符 0
/+
/-
:改变填充方式(0 填充)、符号显示(强制 + 号)、对齐方式(左对齐)。
常见误区:
数据长度超过指定宽度时,宽度限制失效(按实际输出)。
浮点数精度指定会触发四舍五入(而非直接截断)。
类型不匹配会导致错误(如用 %d
输出浮点数,结果不可预测)。
知识点 | 核心内容 | 考试重点 / 易混淆点 | 难度系数 |
---|---|---|---|
格式说明符(m.n) | 控制输出宽度(m)和精度(n),如 %8d (补空格至 8 位)、%.2f (保留 2 位小数)、%.5s (截取前 5 字符) |
当数据长度 > m 时,m 失效(按实际输出);字符串截断优先级高于宽度限制 | ⭐⭐ |
附加格式符(0/+/-) | %08d (补 0 至 8 位)、%+d (显正负号)、%-8d (左对齐) |
零填充仅适用于数字,对字符串无效;+ 号会占用宽度(如 %+5d 中 +123 占 5 位) |
⭐⭐ |
浮点数精度控制 | %.nf 指定小数位(默认 6 位),四舍五入(如 3.456 用 %.2f 输出 3.46 ) |
宽度不足时优先保证精度(如 %2.3f 仍完整显示 3 位小数) |
⭐⭐ |
字符串截断与对齐 | %15.5s (总宽 15,截前 5 字符,右对齐),如 "hello" 输出为 "hello" |
若精度 n 大于字符串长度,按实际长度输出(不补空格) | ⭐⭐ |
类型匹配规则 | %d (整型)、%f (浮点)、%c (字符)、%s (字符串)必须严格匹配 |
类型错误导致未定义行为(如 %d 打印浮点数可能输出随机值) |
getchar
格式:int getchar(void);
功能:从键盘读取单个字符(包括空格、换行符等)。
返回值:
正常情况:返回读取字符的 ASCII 码值(范围 0-255)。
异常情况:出错或输入结束(如按下Ctrl+D
在 Linux/Unix,Ctrl+Z
在 Windows)时返回-1
(标准宏EOF
定义为-1
)。
使用要点:
必须用int
型变量接收返回值(而非char
),因char
无法表示-1
(signed char
范围 - 128~127,unsigned char
范围 0~255)。
与putchar
对应,是字符专用 I/O 函数,需包含头文件stdio.h
。
使用int
型的原因:
字符 ASCII 码范围为 0-255,但需额外表示错误状态-1
(EOF
),char
类型无法覆盖这一范围。
设计考量:
标准库需同时支持正常字符返回和错误状态标识,EOF
(-1)是统一的输入结束标志。
#includeint main() { int c; // 必须用int型 printf("Enter a character: "); c = getchar(); // 读取输入 // 输出字符的三种格式 printf("%c - %d -> hex %x\n", c, c, c); return 0; }
运行示例: 输入A
时输出:A - 65 -> hex 41
(说明'A'
的 ASCII 码十进制为 65,十六进制为 41)。
异常处理: 当用户按下Ctrl+D
(或Ctrl+Z
),getchar
返回-1
,表示输入结束。
验证方法:
#includeint main() { int ch; while (1) { printf("> "); ch = getchar(); // 循环读取 if (ch == EOF) break; // 遇EOF退出 printf("ch = %d\n", ch); } printf("ch = %d (EOF)\n", ch); // 输出-1 return 0; }
输入普通字符(如a
):显示ch=97
;
按Ctrl+D
:显示ch=-1
,验证了EOF
的行为。
scanf
scanf
基本用法函数格式:int scanf(const char *格式控制串, 地址表);
核心功能:按指定格式从键盘读入数据,存入地址表指向的变量,按回车键结束输入。
返回值机制:
正常情况:返回成功输入的数据个数(与地址表中变量数量一致)。
输入失败:返回 0(如类型不匹配)或EOF
(输入结束)。
地址表要求:必须用取地址运算符&
获取变量地址(如&num
),字符串数组名本身是地址,无需&
。
scanf
基本用法#includeint main() { int num; printf("请输入一个整数:"); int ret = scanf("%d", &num); // 读取整数 if (ret == 1) { printf("你输入的是:%d\n", num); } else { printf("输入失败!\n"); } return 0; }
scanf
格式符应用格式符 | 功能描述 | 示例(输入→存储值) |
---|---|---|
%d |
读取十进制整数 | 输入123 →存储123 |
%x |
读取十六进制整数(输入无需0x 前缀) |
输入11 →存储17 (16 进制 11=10 进制 17) |
%o |
读取八进制整数 | 输入10 →存储8 (8 进制 10=10 进制 8) |
%u |
读取无符号十进制整数 | 输入456 →存储456 |
%c |
读取单个字符(包括空白符) | 输入'a' →存储'a' (ASCII 97) |
%s |
读取字符串(遇空白符结束) | 输入"hello" →存储字符串"hello" |
%f |
读取小数形式浮点数(float 类型) |
输入3.14 →存储3.14f |
%lf |
读取小数形式浮点数(double 类型) |
输入3.14 →存储3.14 |
%e |
读取指数形式浮点数(如1.2e3 ) |
输入1e2 →存储100.0 |
错误示例:scanf("please input: %d", &num)
要求用户必须输入"please input: "
才能继续,极不友好。
正确做法:
先用
printf
单独输出提示,再调用
scanf:
printf("请输入一个整数:"); scanf("%d", &num); // 仅保留格式控制
scanf
返回值应用返回值应用场景:通过比较返回值与预期变量个数,检测输入是否成功。
#includeint main() { int n; printf("请输入整数:"); if (scanf("%d", &n) != 1) { // 若成功输入1个整数 printf("输入错误!\n"); return 1; } printf("输入的整数是:%d\n", n); return 0; }
典型错误:输入类型不匹配(如要求%d
却输入字母)时,返回值为 0,输入缓冲区保留错误数据。
scanf
修饰符应用h
:用于short
型(如%hd
读取short int
)。
l
:用于long
型(如%ld
读取long int
)或double
型(如%lf
)。
m
)指定读取的字符数(超过部分忽略,不足则读至结束)。
示例:
%4d%2d%2d
可拆分日期输入:
int year, month, day; scanf("%4d%2d%2d", &year, &month, &day); // 输入"19991015"→year=1999, month=10, day=15
*
)跳过对应输入项,不赋值给变量。
示例:
%2d%*3d%2d
跳过中间 3 位:
int a, b; scanf("%2d%*3d%2d", &a, &b); // 输入"1234567"→a=12, b=67(跳过345)
字符输入特性:
%c
会读取包括空格、换行符在内的所有字符(与数值输入忽略空白符不同)。
示例:
char c1, c2; scanf("%c%c", &c1, &c2); // 输入"a b"→c1='a', c2=' '(空格的ASCII为32)
混合输入建议
:数值与字符混合输入时,用空格分隔格式符(如
%d %c
),避免空白符干扰:
int num; char ch; scanf("%d %c", &num, &ch); // 输入"123 a"→正确读取num=123, ch='a'
getchar
用于读取单个字符,返回int
型(兼容ASCII
和EOF
)。
特点:每次读一个字符,包括空白符,适用于简单字符输入场景。
scanf
功能强大,支持多类型格式化输入,需用&
传递变量地址。
格式控制:通过格式符(%d
/%c
等)指定类型,修饰符(m
/*
等)控制读取规则。
注意:%c
读取空白符,数值输入忽略空白符,返回值可用于验证输入有效性。
多实践以熟悉函数细节,重点掌握常用格式符(%d
/%f
/%c
/%s
)。
不必死记所有规则,通过手册查阅低频用法,优先掌握输入验证和类型匹配。
知识点 | 核心内容 | 考试重点 / 易混淆点 | 难度系数 |
---|---|---|---|
字符输入函数 getchar |
读取单个字符,返回int 型(含ASCII 码和EOF =-1);需用int 变量接收。 |
必须用int 而非char 接收返回值;Ctrl+D 触发EOF (返回 - 1)。 |
⭐⭐ |
格式输入函数 scanf |
按格式读取输入,返回成功赋值的变量数;需用& 传递地址(字符串除外)。 |
数值输入忽略空白符,%c 读取空白符;返回值用于判断输入有效性(如ret != 1 表示失败)。 |
⭐⭐⭐ |
scanf 修饰符 |
%hd (short )、%ld (long )、%md (域宽)、%*d (跳过赋值)。 |
域宽控制对连续无分隔输入(如日期)有效;%*d 需输入合法数据但不赋值。 |
⭐⭐⭐⭐ |
输入验证技巧 | 通过scanf 返回值判断输入是否成功(如预期 1 个变量,返回值≠1 则失败)。 |
错误将提示语写入scanf 格式串(如scanf("输入:%d", &n) )。 |
⭐⭐ |
类型匹配问题 | getchar 返回int 的原因:覆盖ASCII 扩展值(>127)和EOF (-1)。 |
unsigned char 无法存储-1 , |
当使用输入函数(如scanf
输入整数)后,回车符(ASCII 码 10)可能会被后续的字符输入函数接收,导致输入错误。例如输入整数5
后回车,若接下来用%c
接收字符,会直接读取回车符而非预期字符。 处理方法有两种:
方法 1:用getchar()
清除
在输入整数后,调用
getchar()
手动读取并丢弃回车符。
示例:
int a; char c; scanf("%d", &a); getchar(); // 清除回车符 scanf("%c", &c); // 正确接收输入的字符
方法 2:在格式串中用空格或%*c
忽略
格式串中加空格:scanf("%d ", &a);
(空格会匹配任意空白字符,包括回车)。
使用%*c
:scanf("%d%*c", &a);
(%*c
表示读取一个字符但不存储,直接丢弃)。
gets
格式:char* gets(char *s)
功能:从键盘读取字符串,以回车结束,自动在末尾添加\0
(字符串结束标志)。
特点:不以空格作为结束标志(与scanf("%s")
不同,%s
遇空格停止)。
危险点:若输入字符串长度超过字符数组容量,会导致缓冲区溢出,可能使程序崩溃或被攻击,因此实际开发中建议用更安全的fgets
替代。
puts
格式:int puts(const char *s)
功能:向显示器输出字符串,并自动换行。
要求:字符数组必须以\0
结束,否则会输出乱码直到遇到\0
。
问题:输入a、b、c
,求解方程ax² + bx + c = 0
。
公式:
判别式Δ = b² - 4ac
。
若Δ > 0
,有两个不同实根:x₁ = [-b + √Δ]/(2a)
,x₂ = [-b - √Δ]/(2a)
。
若Δ = 0
,有两个相同实根:x = -b/(2a)
。
若Δ < 0
,无实根(有共轭复根)。
注意事项:
使用sqrt
函数(计算平方根)需包含头文件
。
编译时需加-lm
选项(链接数学库),例如:gcc equation.c -o equation -lm
。
知识点 | 核心要点 | 考试重点 / 易混淆点 | 难度 |
---|---|---|---|
输入垃圾处理 | 回车符对后续输入的影响 | 两种处理方法(getchar() 、格式串空格 /%*c ) |
★★★☆☆ |
gets 函数 |
输入字符串,自动加\0 ,但有缓冲区溢出风险 |
输入长度不可超过数组容量 | ★★★★★ |
puts 函数 |
输出字符串并自动换行,依赖\0 结束标志 |
与printf("%s", s) 的区别(puts 自动换行) |
★★★☆☆ |
一元二次方程求解 | 判别式计算、sqrt 函数使用、编译链接选项 |
-lm 的作用(链接数学库) |
★★★★☆ |
解决输入函数留下的垃圾有几种方法? 两种:①用getchar()
清除;②在scanf
格式串中用空格或%*c
忽略。
C 语言中,如何输入或输出一个字符串?
输入:可用gets(s)
(不推荐,有风险)或scanf("%s", s)
(遇空格停止),也可用fgets(s, n, stdin)
(安全,指定最大长度n
)。
输出:可用puts(s)
(自动换行)或printf("%s", s)
(需手动加\n
换行)。
通过以上梳理,能更清晰地掌握输入输出的关键细节,尤其是输入垃圾处理和字符串函数的使用注意事项,这在嵌入式开发中对数据交互的准确性至关重要。