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 ...
随机推荐
- Oracle 锁表查询和解锁方法
system登录 查询被锁表信息 select sess.sid, sess.serial#, lo.oracle_username, lo.os_user_name, ao.object_name, ...
- 防火防盗防CDN流量盗刷
没想到自己的小破站也逃不掉被攻击的命,分分钟就给我刷欠费了. 本来不想写这篇文章的,但看到好多大佬(小林coding. JavaGuide)近期cdn都被盗刷了. 还是来提醒下大家,防火防盗防cdn流 ...
- 还在困惑需要多少数据吗?来看看这份估计指南 | CVPR 2022
论文基于实验验证,为数据需求预测这一问题提供了比较有用的建议,详情可以直接看看Conclusion部分. 来源:晓飞的算法工程笔记 公众号 论文: How Much More Data Do I Ne ...
- Top monitor[2.1.11] 开源
说明 本项目将转为开源项目. \(\text{GitHub}\) 仓库下载链接 \(|\) 项目初始化下载 \(|\) 项目编辑文件下载. 项目说明 声明:此项目由 \(\text{So_noSlac ...
- 学习笔记--Java合集
学习笔记--Java合集 JDK8 基础篇 我的第一个Java程序 Java标识符 Java 字面值 Java中的变量 Java中的数据类型 Java 运算符 Java 控制语句 方法 Java方法基 ...
- 一款基于Fluent设计风格、现代化的WPF UI控件库
前言 今天大姚给大家分享一款基于Fluent设计风格.开源(MIT License).现代化的WPF UI控件库,它提供直观的设计.主题.导航和全新的沉浸式控件,全部都是原生且无缝地集成在一起:WPF ...
- 【转载】 关于tf.stop_gradient的使用及理解
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/u013745804/article/de ...
- Python 将Word转换为JPG、PNG、SVG图片
将Word文档以图片形式导出,既能方便信息的分享,也能保护数据安全,避免被二次编辑.文本将介绍如何使用Spire.Doc for Python 库在Python程序中实现Word到图片的批量转换. P ...
- SMU Autumn 2023 Round 4(Div.1+2)
SMU Autumn 2023 Round 4(Div.1+2) A. Access Denied 通过分析样例可以得知如果所猜字符串与答案字符串长度不同,则只要\(5ms\),且答案最多\(20\) ...
- SMU Summer 2023 Contest Round 11(2022-2023 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2022))
SMU Summer 2023 Contest Round 11(2022-2023 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2022 ...