c程序设计语言 by K&R(四)输入与输出
一、标准输入、输出
1. 简单的输入\输出机制
- 从标准输入中一次读取一个字符:
int getchar(void) - 将字符c送到标准输出中:
int putchar(int)
2. 输入重定向
- 如果程序prog中使用了getchar函数,那么
prog < infile,将使得程序prog从输入文件infile中读取字符。 - 如果输入通过管道来自另一个程序,那么这种输入切换也是不可见的。如命令
otherprog | prog将程序的otherprog的标准输出通过管道重定向到程序prog的标准输入中。
3. 输出重定向
- 如果程序prog中使用了putchar函数,那么
prog > file, 将使得程序prog的标准输出重定向到file文件。 - 如果系统支持管道,那么
prog | anotherprog将把程序的标准输出通过管道重定向到程序anotherprog的标准输入中。
二、格式化输出——printf函数
1. 完整形式
int printf(char* format, arg1, arg2, arg3,....);
- '-',负号。指定被转换的参数按左对齐的形式输出。
- 数(小数点之前)。指定最小字段宽度。字符长度不足,则填充空格。
- 小数点。将字段宽度和精度分开。
- 数(小数点之后)。指定字符串中要打印的最大字符数、浮点数小数点后的位数、整形最少输出的数字数目。
2. 基本的转换说明
| 字符 | 输出形式 |
|---|---|
| d,i | int,十进制数 |
| o | int,无符号八进制数 |
| x | int,无符号十六进制数 |
| u | int,无符号十进制数 |
| c | int类型,单个字符 |
| s | char* 类型,直到'\0'或打印了精度指定的字符数 |
| f | double类型,十进制小数,[-]m.dddddd ,d个数由精度指定 |
| e,E | double类型,[-]m.ddddd E [+-] xxx ,d个数由精度指定 |
| g,G | double类型,如果指数小于-4或大于等于精度,则使用%e、%E输出,否则用%f输出 |
| p | void* 类型;指针 |
int main() {
double a = 100;
printf("%e\n", a);
return 0;
}
输出为:
1.000000e+002
3. 字符串输出的精度控制
#include
#include
int main(void) {
char* s = "hello, world"; //12 char
printf("-%s-\n",s); //用-指示宽度边界
printf("-%10s-\n",s);
printf("-%.10s-\n",s);
printf("-%-10s-\n",s); // - 左对齐
printf("-%15s-\n",s);
printf("-%-15s-\n",s);
printf("-%15.10s-\n",s);
printf("-%-15.10s-\n",s);
int max = 5;
printf("-%.*s-\n", max, s); //宽度或精度可通过星号*表示,其值可通过转换下一参数(必须为int类型)来计算。
return 0;
}
输出
-hello, world-
-hello, world-
-hello, wor-
-hello, world-
- hello, world-
-hello, world -
- hello, wor-
-hello, wor -
-hello-
4. sprintf函数
int sprintf(char* string, char* format, arg1, arg2, ...);
按照format格式格式化序列参数arg1,arg2,...,将输出结果存放到string中。string的空间需要大到足以容纳结果。
三、 变长参数表
1. 几个va_宏定义
- va_list :
va_list ap;用于声明一个变量ap(arg pointer),依次引用各参数。 - va_start:
va_start(ap, namedArg);将ap初始化为第一个无名参数的指针。使用ap之前,该宏必须被调用依次。参数表必须至少包含一个又名参数,va_start将最后一个有名参数作为起点。 - va_arg:
va_arg(ap, int)该函数将返回一个参数,并将ap指向下一个参数。va_arg使用一个类型名来决定返回的对象类型、指针移动的步长。 - va_end:
va_end(ap);最后在函数返回之前,需调用va_end来完成一些必要的清理工作。
2. 实现一个miniprintf
void minprintf(char* fmt, ...){
va_list ap;
char* p, *sval;
int ival;
double dval;
va_start(ap, fmt);
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);
}
3. 实现一个可变参数累加函数
long long int sum(int num, ...) 其中num为累加整数的数量。
#include
#include
long long int sum(int num, ...){
long long int result = 0;
va_list ap;
va_start(ap, num);
while(num--){
result += va_arg(ap, int);
}
va_end(ap);
return result;
}
int main() {
printf("%lld", sum(3,2,3,4));
return 0;
}
输出为:
9
四、格式化输入——scanf函数
scanf和sscanf的所有参数都必须是指针。
1. scanf: 从标准输入中读取字符序列。
int scanf(char* format, ...)
-
其返回值可以用来确定已匹配的输入项的个数。
-
如果达到文件的末尾,返回EOF。
-
如果返回0, 表示下一个输入字符与格式串中的第一个格式说明不匹配。
2. sscanf: 从一个字符串而不是标准输入中读取字符序列。
int sscanf(char* string, char* format, arg1, arg2...)
按照格式参数format中规定的格式扫描字符串string,并把结果保存到arg1, arg2, ...