C 格式化输入输出与字符读写

将格式化的数据发送到标准输出设备 语法:int printf(const char format, ...); 参数: format:格式化字符串,指定输出的格式。 ...:可变参数列表,根据格式化字符串中的格式说明符,提供要输出的数据。 printf() 可以在输出文本中指定占位符 占位符的含义指的是:这个位置可以用其他的值代入 C printf("%s will be better","tomorrow");

printf()

  • 将格式化的数据发送到标准输出设备 语法:int printf(const char *format, ...); 参数:
  • format:格式化字符串,指定输出的格式。
  • ...:可变参数列表,根据格式化字符串中的格式说明符,提供要输出的数据。

printf 的占位符

printf() 可以在输出文本中指定占位符 占位符的含义指的是:这个位置可以用其他的值代入

EXAMPLE

printf("%s will be better","tomorrow");

占位符的第1个字符一律用百分号%,第2个字符表示占位符的类型 %d表示这里代入的值必须是一个整数。

在文本中使用占位符的数量没有限制

占位符汇总

ABSTRACT: ⚡ 高频常用速查 (The “Big Five”) 日常开发中 90% 的情况只需要用到这五个:

  • %d ➔ 十进制整数 (int)
  • %f ➔ 浮点小数 (float / double)
  • %c ➔ 单个字符 (char)
  • %s ➔ 字符串 (char*)
  • %p ➔ 指针/内存地址

🔢 1. 整数家族 (Integer)

占位符 对应数据类型 格式与显示说明
%d / %i int 有符号十进制(两者在 printf 中用法一致)
%u unsigned int 无符号十进制
%o int 八进制(输出不带 0 前缀)
%x int 十六进制(字母小写,如 1a
%X int 十六进制(字母大写,如 1A
%hd short int 短整型(有符号)
%hu unsigned short 短整型(无符号)
%ld long int 长整型(有符号)
%lu unsigned long 长整型(无符号)
%lld long long int 超长整型(有符号)
%llu unsigned long long 超长整型(无符号)
%zd size_t 专用于输出 sizeof() 的结果

📊 2. 浮点数家族 (Floating Point)

占位符 对应数据类型 格式与显示说明
%f float / double 标准小数(默认保留 6 位小数)
%Lf long double 长双精度小数
%e float / double 科学计数法(指数带小写 e
%E float / double 科学计数法(指数带大写 E
%g float / double 智能适配(自动在 %f%e 中选择较短的,最多 6 位有效数字,小写 e
%G float / double 智能适配(同上,但使用大写 E
%a float / double 十六进制浮点(P 计数法,小写字母,C99 标准)
%A float / double 十六进制浮点(P 计数法,大写字母,C99 标准)

🔤 3. 字符与字符串 (Character & String)

占位符 对应数据类型 格式与显示说明
%c char 输出单个字符
%s char* (字符数组/指针) 输出字符串(直到遇到结束符 \0 为止)

🛠️ 4. 特殊功能 (Special)

占位符 功能描述 注意事项
%p 打印指针地址 通常以十六进制显示,并自动带 0x 前缀(因编译器而异)
%n 统计输出字符数 ⚠️ 此符号不输出任何内容! 它会将当前已打印的字符总数,赋值给传入的 int* 指针变量
**`:输出一个百分号
## 定制占位符的输出格式
### 限定宽度
_限定占位符的**最小宽度。**_
```C
#include <stdio.h>
int main()
{
    printf("%5d\n",123);
	return 0;
}
//结果为“  123”(前面空两格)

%5d 表示这个占位符的宽度至少是5位。如果不满5位,对应的值在前面会添加空格。输出的值 默认是右对齐,即输出内容前面会有空格,如果希望改为左对齐,在输出内容后面添加空格。可以在占位符的百分号的后面插入一个 - 号。

总是显示正负号

让正数也输出+号,可以在占位符的%后面加一个+

#include <stdio.h>
int main()
{
  printf("%+d\n"12);//输出 +12	
  printf("%+d\n"-12);//输出 -12	
  return 0;
}

限定小数位数

举例来说,希望小数点后面只保留两位,占位符可以写成 %.2f

#include <stdio.h>
int main()
{
    printf("Number is %.2f\n",0.5);	
    return 0;
}
//结果输出为:Number is 0.50

与限定宽度展位符混用

#include <stdio.h>
int main()
{
    printf("%6.2f\n", 0.5); 
    return 0;
}
//输出结果为:“  0.50”

上面示例中,%6.2f 表示输出字符串最小宽度为6,小数位数为2。所以,输出字符串的头部有两个空格。

最小宽度和小数位数这两个限定值,都可以*代替,通过printf()的参数传入

#include <stdio.h>
int main()
{
    printf("%*.*f\n",6,2,0.5);//等同于printf("%6.2f\n",0.5);
    return 0;
}

上面示例中,%*.*f 的两个星号通过printf()的两个参数6和2传入

输出部分字符串

scanf()

语法:int scanf(const char *format, ...); 参数:

  • format:格式化字符串,指定输入的格式。
  • ...:可变参数列表,根据格式化字符串中的格式说明符,提供存储输入数据的变量地址。

Tip: 延伸阅读 标准输入输出掌握后,可以继续看 c-file-operations,理解 stdin/stdout 与文件流读写的关系。

一般格式:

scanf(格式控制,地址列表)

格式控制字符串

基础转换说明符 (Conversion Specifiers)

这些符号告诉编译器:“我要读入什么类型的数据?”

符号 对应的变量类型 说明
%d int 有符号十进制整数
%f float 单精度浮点数
%lf double 双精度浮点数(注意: scanf 必须加 l
%c char 单个字符(包括空格、换行符)
%s char[] (字符串) 字符串,读取到空格、制表符或换行符处停止
%u unsigned int 无符号十进制整数
%x / %X int 十六进制整数
%o int 八进制整数
%p void* 指针(地址值)

长度修饰符 (Length Modifiers)

用于匹配特定位宽的整数或浮点数。

  • h: 短整型。例如 %hd 用于 short

  • l: 长类型。例如 %ld 用于 long%lf 用于 double

  • ll: 超长整型。例如 %lld 用于 long long

  • L: 长双精度。例如 %Lf 用于 long double

特殊格式控制语法

域宽 (Width)

% 和说明符之间加上数字,限制读取的最大字符数。

示例:scanf("%5d", &num); —— 最多读取 5 位数字。如果输入 1234567num 只会得到 12345

赋值抑制符 (*)

表示读取该项但不保存到任何变量中,直接跳过。

示例:scanf("%d %*d %d", &a, &b); —— 如果输入 10 20 30a 得到 1020 被跳过,b 得到 30

扫描集 (Scan Set) [ ]

用于匹配特定的字符集。

  • %[a-z]:只读取小写字母。

  • %[^0-9]:读取除数字以外的所有字符(^ 表示取反)。


常见的“坑”与注意事项

  1. 取地址符 &:除了字符串数组名(%s)本身就是地址外,其他变量必须加 &

  2. 空格问题

    • %c 会读取任何字符,包括你上次输入留下的回车符(\n)。建议写成 " %c"(前面加个空格),可以跳过前面的所有空白符。

    • 除了 %c%[],其他说明符都会自动跳过前面的空格、制表符和换行符。

  3. 非格式字符

    • 如果你写 scanf("age=%d", &a);,那么你在键盘上必须精准输入 age=18 才能读取成功。
  4. 不要在格式字符串中加\n,在使用scanf时,格式控制应该尽量的简单

参数

规定符

  • %d 十进制有符号整数
  • %u 十进制无符号整数
  • %f 浮点数
  • %s 字符串
  • %c 单个字符
  • %p 指针的值
  • %e 指数形式的浮点数
  • %x, %X 无符号以十六进制表示的整数
  • %o 无符号以八进制表示的整数
  • %g 把输出的值按照 %e 或者 %f 类型中输出长度较小的方式输出
  • %p 输出地址符
  • %lu 32位无符号整数
  • %llu 64位无符号整数
  • %% 输出百分号字符本身。

除了格式化说明符之外,printf() 函数还支持一些标志和选项,用于控制输出的精度、宽度、填充字符和对齐方式等。例如:

  • %-10s:左对齐并占用宽度为 10 的字符串;
  • %5.2f:右对齐并占用宽度为 5,保留两位小数的浮点数;
  • %#x:输出带有 0x 前缀的十六进制数。

printf() 函数也支持变长参数列表,可以使用省略号 … 来表示,用于指定要输出的多个值。


字符数据的输入输出

putchar()

 <stdio.h> 头文件中的原型为:int putchar(int c); 输出一个字符

putchar() 函数接受一个 int 类型的参数,但实际上它会被转换为一个无符号字符(范围 0~255),这意味着:

  • 虽然参数类型是 int,但只有低 8 位会被使用;
  • 可以直接传入字符字面量,如 ‘A’;
  • 可以传入 ASCII 码值,如 65(对应 ‘A’)。

putchar() 函数的返回值也是 int 类型:

  • 如果字符成功输出,返回该字符的 ASCII 码值。
  • 如果发生错误,返回 EOF(通常定义为 -1)。

putchar() 函数的主要作用是将一个字符写入到标准输出流中,并在调用后自动刷新缓冲区,确保字符立即显示在屏幕上。

putchar() 可以输出所有 ASCII 字符,包括不可见的控制字符。

putchar('A');          //输出A
putchar(65);           //输出A
int a = putchar('A');  //a的值为65
printf("%d\n",a);
putchar('\101');       ////输出A,\101是八进制
putchar('\x41');       ////输出A,\x41是十六进制

getchar()

<stdio.h> 头文件中的原型为:int getchar(void); 输入一个字符

从原型可以看出,getchar() 不接受任何参数,返回值类型为 int

尽管 getchar() 用于读取字符,但它的返回值类型是 int 而不是 char。这是因为 getchar() 需要能够表示所有可能的字符值(0 到 255)以及一个额外的值 EOF(通常定义为 -1)来表示输入结束。

  • 如果成功读取到字符,getchar() 返回该字符的 ASCII 值。
  • 如果到达文件末尾或发生读取错误,getchar() 返回 EOF。
int ch
ch = getchar();   //读取单个字符

int ch
while ((ch = getchar()) != '\n' && ch != EOF) {
	putchar(ch);  //读取多个字符直到遇到换行符
}

 int age;
    char name[50];
    
    printf("请输入你的年龄:");
    scanf("%d", &age);
    
    // 清除输入缓冲区中的换行符
    while (getchar() != '\n');
    
    printf("请输入你的名字:");
    fgets(name, sizeof(name), stdin);
    
     printf("你好,%s你的年龄是 %d 岁。\n", name, age);
     return 0;

相关笔记