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 <stdio.h>
#include <stdlib.h>
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 <stdio.h>
#include <stdarg.h>
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, ...
五、文件访问
1. 文件指针:
- 在读写一个文件之前,必须通过库函数fopen打开该文件。
fopen利用文件名建立与操作系统必要的连接和通信,返回一个可用于文件读写操作的指针FILE*。它指向一个包含文件信息的结构,这些信息包括:缓冲区的位置、缓冲区当前字符的位置、文件的读写状态等、是否出错或是否已经达到文件末尾等。
FILE* fopen(char* name, char* mode);
- name是文件名,mode是访问模式,包括
读(r)、写(w)、追加(a)。某些系统用b来区分文本文件和二进制文件。
2. 对文件的读写方法
int getc(FILE* fp) : 从文件指针fp指向的文件中中获取一个字符。
int putc(int c, FILE* fp) : 向指针写入一个字符c。
3. 启动c程序时,操作系统打开的文件
启动一个c语言程序时,操作系统负责打开三个文件,并将这三个文件的指针提供给该c程序。三个文件分别是标准输入、标准输出和标准错误,对应的指针为
stdin、stdout、stderr,包含在<stdio.h>。通常,
stdin指向键盘、stdout和stderr指向显示器。由前述可知,
stdin、stdout可以重定向到管道。
4. 文件的格式化输入、输出
可以使用fscanf()、fprintf(),比scanf()和printf()相比,多了一个文件指针参数FILE* fp作为第一个参数。
- 格式化输入
int fscanf(FILE* fp, char* format, ...);
- 格式化输出
int fprintf(FILE* fp, char* format, ...);
- 实现简单的cat程序: 将多个文件的内容输出。
cat.c
#include <stdio.h>
void filecopy(FILE* ifp, FILE* ofp){
int c;
while((c = getc(ifp)) != EOF){
putc(c, ofp);
}
}
int main(int argc, char* argv[]) {
FILE* fp;
if(argc == 1){
filecopy(stdin, stdout);
}else{
while(--argc > 0){
if((fp = fopen(*++argv, "r")) == NULL){
printf("cat: can't open %s\n", *argv);
return 1;
}else{
filecopy(fp, stdout);
fclose(fp);
}
}
}
return 0;
}
1.txt
hello
2.txt
world
编译运行:
gcc cat.c -o cat
./cat 1.txt 2.txt
输出:
hello
world
六、错误处理——stderr和exit
1. 刚刚实现的cat程序错误处理并不完善。
如果因为某种原因造成某个文件无法访问,相应的诊断信息要在输出末尾打印出来,输出到屏幕可以接受,但输出到另一个文件或重定向到另一个程序时,就无法接受了。为了更好地处理这种情况,另一个输出流stderr以与stdin和stdout相同的方式分派给程序。即使对标准输出进行了重定向,写到stderr的输出通常也会显示在屏幕上。
对cat程序进行修改,将错误信息写到标准错误文件中。
#include <stdio.h>
#include <stdlib.h>
void filecopy(FILE* ifp, FILE* ofp){
int c;
while((c = getc(ifp)) != EOF){
putc(c, ofp);
}
}
int main(int argc, char* argv[]) {
FILE* fp;
char* prog = argv[0];
if(argc == 1){
filecopy(stdin, stdout);
}else{
while(--argc > 0){
if((fp = fopen(*++argv, "r")) == NULL){
fprintf(stderr, "%s: can't open %s\n", prog, *argv);
exit(1);
}else{
filecopy(fp, stdout);
fclose(fp);
}
}
}
if(ferror(stdout)){
fprintf(stderr, "%s: error writing stdout\n", prog);
exit(2);
}
exit(0);
}
2. fprintf()函数将产生的诊断信息输出到stderr中
3. 使用exit()函数终止调用程序的执行。
在主程序main中,语句return expr相当于exit(expr)。但是exit函数的优点是可以在其他函数中调用。
4. ferror(FILE* fp)函数
int ferror(FILE* fp)
如果流fp中出现错误,该函数将返回一个非0值。
5. feof(FILE* fp)函数
如果指定的文件达到文件末尾,它将返回一个非0值。
七、行输入和行输出
1. fgets
char *fgets(char* line, int maxline, FILE* fp) 从fp指向的文件中读取下一个输入行,将它存在字符数组line中(以'\0'结尾),最多可读取maxline-1个字符。遇到文件结尾或发生错误,会返回NULL。
2. fputs
int fputs(char* line, FILE* fp) 将一个字符串line写入到fp指向的文件。发生错误时,返回EOF,否则返回一个非负值。
八、其它函数
1. 字符串
| 函数 | |
|---|---|
| strcat(s,t) | |
| strcat(s, t, n) | |
| srcmp(s, t) | |
| strcmp(s, t, n) | |
| strcpy(s, t) | |
| strcpt(s, t, n) | |
| strlen(s) | |
| strchr(s, c) | 在字符串s中查找c,若找到返回第一次出现的位置的指针,否则返回null |
| strrchr(s, c) | 在字符串s中查找c,若找到返回最后一次出现的位置的指针,否则返回null。(反向查找) |
2. 字符串测试和转换函数
| 函数 | |
|---|---|
| isalpha(c) | |
| isupper(c) | |
| islower(c) | |
| isdigit(c) | |
| isalnum(c) | |
| isspace(c) | |
| toupper(c) | |
| tolower(c) |
3.ungetc函数
int ungetc(int c, FILE* fp) 将字符c写回到文件fp中。如果执行成功,返回c,否则返回EOF。
4.命令执行函数
system(char* s)执行包含在字符串s中的命令,然后继续执行当前程序。比如system("date")将执行程序date, 在标准输出中打印当前的日期和时间。又比如system("pause")。
5.存储管理函数
函数malloc和calloc用于动态分配内存。
- malloc函数
void* malloc(size_t n), 分配成功时,返回一个指向n字节长度的未初始化的存储空间,否则返回NULL。
- calloc函数
void* calloc(size_t n, size_t size),分配成功时,该指针指向足以容纳由n个指定长度为size的对象组成的数组,否则返回NULL。
- 例子:
以下例子进行了类型转换。
int* ip;
ip = (int*)calloc(n, sizeof(int));
free(p)函数释放p指向的空间,p必须是此前通过调用malloc和calloc函数得到的指针。
6. 数学函数
sin(x) 、cos(x) 、atan2(x) 、exp(x) 、log(x) 、 log10(x) 、pow(x, y)、 sqrt(x)、 fabs(x)
7.随机数发生器函数
rand()生成介于0和RAND_MAX之间伪随机整数序列。
c程序设计语言 by K&R(四)输入与输出的更多相关文章
- C程序设计语言(K&R) 笔记2
(1) #include <stdio.h> main(){ int c; while((c = getchar()) != EOF){ putchar(c); } } 注意,因为 != ...
- C程序设计语言(K&R) 笔记1
当作复习... (1)将华氏度 换算成 摄氏度,公式: ℃=(5/9)(̧°F-32) #include <stdio.h> int transformTemprature(int F){ ...
- C语言中字符数据的输入和输出
字符的输出 C语言中使用putchar函数来输出字符数据 #include <stdio.h> int main() { char a,b,c,d; //定义字符变量a,b,c,d a = ...
- c语言笔记4数据的输入和输出
数据的输入和输出 知识点一 计算机的用途:数据的输入和输出. 分类: 字符:字符输入函数getchar().字符输出函数putchar(). 格式:格式输入函数scanf().格式输出函数printf ...
- 《c程序设计语言》读书笔记--首次输入不能是空符;最多10个字符
#include <stdio.h> #define Num 10 int main() { int wor = 0; int arr[Num] = {0}; int c,count = ...
- c程序设计语言_习题1-13_统计输入中单词的长度,并且根据不同长度出现的次数绘制相应的直方图
Write a program to print a histogram of the lengths of words in its input. It is easy to draw the hi ...
- javaIO流(四)--输入与输出支持
一.打印流 如果现在要想通过程序实现内容的输出,核心的本质一定要依靠OutputStream类来支持但是OutputStream类有一个最大的缺点,这个类的数据输出操作功能有限,所有的数据一定要转为字 ...
- C语言基础(9)-字符串格式化输入和输出
1.字符串在计算机内部的存储方式 字符串是内存中一段连续的char空间,以’\0’结尾 2.printf函数,putchar函数 putchar输出一个char printf是输出一个字符串 prin ...
- mybatis学习记录四——输入、输出映射
6 输入映射 通过parameterType指定输入参数的类型,类型可以是简单类型.hashmap.pojo的包装类型. 6.1.1 需求 完成用户信息的综合查询,需要传入查询条件很 ...
- C语言学习笔记4-数据输入和输出
本系列文章由jadeshu编写,转载请注明出处.http://blog.csdn.net/jadeshu/article/details/50752127 作者:jadeshu 邮箱: jades ...
随机推荐
- 全网最适合入门的面向对象编程教程:15 类和对象的 Python 实现-__slots__魔法方法
全网最适合入门的面向对象编程教程:15 类和对象的 Python 实现-__slots__魔法方法 摘要: 本文主要介绍了 Python 中创建自定义类时不同实例属性保存的基本原理和缺点,介绍了__s ...
- 2023/4/20 SCRUM个人博客
1.我昨天的任务 学习了PYQT5的部分控件,例如按钮,文本框,文本编辑框,并了解了一些基础布局以及部分对窗口的自定义实现 2.遇到了什么困难 无法理解信号和槽的概念 3.我今天的任务 学习信号和槽的 ...
- CCStheia添加include路径
一.在系统内找到该路径 二.复制该路径,并更改写法 C:\Users\c1519\workspace_ccstheia\OLED\user_lib 改为: C:/Users/c1519/workspa ...
- Mysql函数10-IF
IF函数用于判断条件是否成立,成立则执行命令1,不成立则执行命令2. 1.sql查询出一列create_time select create_time from goods where id=65 2 ...
- 【MySQL】30 备份与恢复
1.备份命令: mysqldump -u用户名 -p 密码 -h 服务主机IP -P 端口号 \ 数据库名称 \ > 指定备份的sql脚本文件位置 ↓ # 文件位置样例: # C:\Users\ ...
- FFmpeg开发笔记(四十四)毕业设计可做的几个拉满颜值的音视频APP
一年一度的毕业季就要到了,毕业设计算是大学生毕业前的最后一个大作业,尤其是计算机相关专业的毕业设计,通常要通过编程开发一个软件,比如开发一个图书馆管理系统,开发一个电商APP等等. 一个好的毕业设计 ...
- [COCI2015-2016#1] UZASTOPNI 题解
前言 题目链接:洛谷. 题意简述 一棵有根树,节点数 \(n \leq 10^5\),每个点有权值 \(v_i \leq 2000\),现在选出一些点,满足: 一个点的父亲点若未被选择则其不能被选择. ...
- udp协议实现组播功能
/*************************************************************************************************** ...
- [学习笔记] 丢番图方程 & 同余 & 逆元 - 数论
首先,他们几个有着极大的相似性.另外,他们的各自的思想都能够很好的服务于另外几个,有助于加深理解. 文中有些letax公式抽风了,全屏之后应该能看得见-- 线性丢番图方程 丢番图不是个图啊!他是个ma ...
- Meissel_Lehmer模板
复杂度 \(O(n^\frac 23)\),计算 \(1\sim n\) 的素数个数 #define div(a, b) (1.0 * (a) / (b)) #define half(x) (((x) ...