C语言输入输出与文件操作详解
立即解锁
发布时间: 2025-08-22 00:24:53 阅读量: 4 订阅数: 6 


C语言编程基础与实践
### C语言输入输出与文件操作详解
#### 1. 格式化输出 - printf
输出函数`printf`用于将内部值转换为字符。其基本声明如下:
```c
int printf(char *format, arg1, arg2, ...);
```
`printf`在`format`的控制下,对参数进行转换、格式化并打印到标准输出,同时返回打印的字符数。
格式字符串包含两种对象:
- 普通字符:直接复制到输出流。
- 转换说明:以`%`开头,以转换字符结尾,用于对后续参数进行转换和打印。在`%`和转换字符之间可能依次包含以下内容:
- 减号:指定转换后的参数左对齐。
- 数字:指定最小字段宽度。
- 句点:分隔字段宽度和精度。
- 数字(精度):对于字符串,指定最多打印的字符数;对于浮点数,指定小数点后的位数;对于整数,指定最小位数。
- `h`:表示将整数作为短整型打印;`l`:表示将整数作为长整型打印。
常见的转换字符及其作用如下表所示:
| 字符 | 参数类型;打印形式 |
| ---- | ---- |
| d, i | int;十进制数 |
| o | int;无符号八进制数(无前导零) |
| x, X | int;无符号十六进制数(无前导 0x 或 0X),用 abcdef 或 ABCDEF 表示 10 到 15 |
| u | int;无符号十进制数 |
| c | int;单个字符 |
| s | char *;打印字符串中的字符,直到遇到`\0`或达到精度指定的字符数 |
| f | double;`[-]m.dddddd`,d 的数量由精度指定(默认 6) |
| e, E | double;`[-]m.dddddde+/-xx` 或 `[-]m.ddddddE+/-xx`,d 的数量由精度指定(默认 6) |
| g, G | double;如果指数小于 -4 或大于等于精度,则使用`%e`或`%E`;否则使用`%f`,不打印尾随零和尾随小数点 |
| p | void *;指针(实现相关的表示形式) |
| % | 不转换参数;打印一个`%` |
宽度或精度可以指定为`*`,此时值通过转换下一个参数(必须为`int`类型)来计算。例如,要打印字符串`s`中最多`max`个字符,可以使用:
```c
printf("%.*s", max, s);
```
需要注意的是,`printf`根据第一个参数来确定后续参数的数量和类型。如果参数数量不足或类型错误,可能会导致结果错误。同时,要注意以下两种调用方式的区别:
```c
printf(s); /* 如果 s 包含 % 会失败 */
printf("%s", s); /* 安全 */
```
函数`sprintf`与`printf`的转换功能相同,但将输出存储在字符串中:
```c
int sprintf(char *string, char *format, arg1, arg2, ...);
```
下面是不同格式说明符对字符串 “hello, world” 打印效果的示例:
| 格式说明符 | 打印结果 |
| ---- | ---- |
| :%s: | :hello, world: |
| :%10s: | :hello, world: |
| :%.10s: | :hello, wor: |
| :%-10s: | :hello, world: |
| :%.15s: | :hello, world: |
| :%-15s: | :hello, world : |
| :%15.10s: | : hello, wor: |
| :%-15.10s: | :hello, wor : |
#### 2. 可变长度参数列表
为了展示如何以可移植的方式编写处理可变长度参数列表的函数,这里实现了一个简化版的`printf`函数`minprintf`。`minprintf`会处理格式字符串和参数,但调用真正的`printf`进行格式转换。
`printf`的正确声明为:
```c
int printf(char *fmt, ...)
```
其中`...`表示参数的数量和类型可以变化,且只能出现在参数列表的末尾。`minprintf`的声明如下:
```c
void minprintf(char *fmt, ...)
```
为了处理可变长度参数列表,需要使用标准头文件`<stdarg.h>`,其中包含一组宏定义,用于遍历参数列表。具体步骤如下:
1. 使用`va_list`类型声明一个变量(如`ap`),用于依次引用每个参数。
2. 使用`va_start`宏初始化`ap`,使其指向第一个未命名的参数。调用前必须至少有一个命名参数,`va_start`会使用最后一个命名参数来开始遍历。
3. 每次调用`va_arg`返回一个参数,并将`ap`指向下一个参数,`va_arg`使用类型名来确定返回的类型和步长。
4. 使用`va_end`进行必要的清理工作,必须在程序返回前调用。
以下是`minprintf`的实现代码:
```c
#include <stdarg.h>
/* minprintf: minimal printf with variable argument list */
void minprintf(char *fmt, ...)
{
va_list ap; /* points to each unnamed arg in turn */
char *p, *sval;
int ival;
double dval;
va_start(ap, fmt); /* make ap point to 1st unnamed arg */
for (p = fmt; *p; p++) {
if (*p != '%') {
putchar(*p);
continue;
}
switch (*++p) {
case 'd':
ival = va_arg(ap, int);
printf("%d", ival);
break;
case 'f':
dval = va_arg(ap, double);
printf("%f", dval);
break;
case 's':
for (sval = va_arg(ap, char *); *sval; sval++)
putchar(*sval);
break;
default:
putchar(*p);
break;
}
}
va_end(ap); /* clean up when d
```
0
0
复制全文
相关推荐









