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 ...
随机推荐
- ABC352
A link \(x\)停不到,\(y\)能停到. 要先判断是从前往后还是从后往前. 点击查看代码 #include<bits/stdc++.h> using namespace std; ...
- 搭建lnmp环境-nginx(第一步)
建议: 本次lnmp采用yum形式安装,编译安装过于繁琐,操作不好还不如yum安装,所以不推荐. 全部安装在宿主机上,如果需要安装多个版本的软件才使用docker nginx无所谓版本了 刚安装好系统 ...
- “智能体风”吹进体育圈 粉丝手搓上百个智能体为中国健儿应援 太有AI了!粉丝手搓上百个智能体为中国健儿打CALL
智能体的风吹进了体育竞技圈.近日,在百度文心智能体平台,出现了上百个充满"AI"的运动明星粉丝应援智能体,比如支持中国女子乒乓球运动员孙颖莎的"孙颖莎的小迷妹" ...
- 模型推理batch inference速度无明显提升、耗时线性增长问题排查
模型推理batch inference速度无明显提升.耗时线性增长问题排查 现象描述 当模型在推理阶段使用batch inference时,推理速度并无明显提升,相比单帧多次推理收益不大.如笔者在Xa ...
- Android studio报错:Failed to allocate a 3213123 byte allocation with 31231 free bytes and 189MB ontil 0OM
这个问题是运行内存超了 在AndroidManifest中加入 android:hardwareAccelerated="false"android:largeHeap= &quo ...
- 【Maxwell】03 定向监听&全量输出
一.定向监听 定向监听,即只监听某一个特定的表,或者库 1.创建样本案例 -- 创建监听的库(演示样本) CREATE DATABASE `test-db-2` CHARACTER SET 'utf8 ...
- 【Vue】Re05 操作数组的API
一.响应式处理的操作: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...
- 【转载】 TensorFlow - 框架实现中的三种 Graph图结构
原文地址: https://zhuanlan.zhihu.com/p/31308381 -------------------------------------------------------- ...
- 如何在 Ubuntu18.04 server 服务器版本的操作系统下 配置IP
如题,现有需求,为一个server版本的Ubuntu18.04配置 IP . 在网上查到了 Ubuntu18.04 桌面版本 的配置方法: https://www.cnblogs.com/ ...
- ubuntu系统conda下运行pytorch报错:ImportError: libopenblas.so.0: cannot open shared object file
如题: ubuntu系统conda下运行pytorch报错:ImportError: libopenblas.so.0: cannot open shared object file 网上找了一些资料 ...