嵌入式成长轨迹18 【Linux应用编程强化】【Linux下的C编程 下】【标准输入输出】

 

一   标准输入输出的基本操作
文件控制结构中包含处理文件所需的全部信息,例如文件名、文件当前的读写位置、用于该文件读写的内存缓冲区位置等。打开文件时,系统会在内存中自动建立该文件的控制结构。关闭文件时,文件控制结构被释放。在对文件进行操作之前,要首先获取文件的指针,即指向文件控制结构的指针,后续操作都通过该指针进行。标准输入输出时,有3个比较特殊的文件,它们是:标准输入文件(stdin):一般为键盘;

标准输出文件(stdout):一般为显示器;

标准错误输出文件(stderr):一般为显示器。

1 文件的打开
操作文件之前要打开文件,打开文件主要是在系统中分配一些资源用于保存该文件的状态信息,并获取文件的指针,以后调用其它函数对文件进行读写操作时都要提供这个指针。

2 文件的关闭

  FILE *fopen(const char *filename, const char *modes);
对文件操作完成后,应该关闭文件,进而释放文件所占用的系统资源。文件关闭之后,文件指针将不再有效,用户也就无法通过该指针操作文件。

 int fclose(FILE *fp);

 1 /* example1.c */
2 #include <stdio.h>
3 #include <stdlib.h>
4 int main()
5 {
6 FILE *fp; /* 定义文件指针 */
7 fp = fopen("./hello.c", "r"); /* 打开文件 */
8 if (fp == NULL) /* 如果文件打开失败,输出错误信息并退出 */
9 {
10 printf("Open hello.c failed.\n");
11 exit(1);
12 }
13 printf("Open file succeed.\n");
14 fclose(fp); /* 关闭文件 */
15 return 0;
16 }

3 缓冲区的刷新
刷新操作是指将缓冲区中的数据清除,这项工作可以由fflush或fpurge函数完成。

 int fflush(FILE *fp);
 int fpurge(FILE *fp);
4 缓冲区属性的设置
缓冲区的大小和类型等都可以通过函数来设置,缓冲区的类型有下面三种:

全缓冲:缓冲区被填满后才执行输入输出操作,将数据写入到磁盘文件或输出到用户终端;

行缓冲:缓冲区中填入换行符时,执行输入输出操作;

无缓冲:不对数据进行缓存,标准错误输出stderr一般就是无缓冲的,这可以使错误信息尽快地显示出来。

 

int setvbuf(FILE *fp, char *buf, int mode, size_t size);

_IOFBF、_IOLBF、_IONBF

 

二  非格式化输入输出
非格式化输入输出包括单个字节输入输出、字符串(行)输入输出以及数据块输入输出

1  单个字节输入输出
在进行单个字节的输入输出操作时,可以使用fgetc函数和fputc函数。

文件输入输出单个
 int fgetc(FILE *fp);
 int fputc(int c, FILE *fp);

标准输入单个 int getchar();

 int fgetc(stdin);

标准输出单个
 int putchar(int c);

 int fputc(c, stdout);

 1 /* example2.c */
2 #include <stdio.h>
3 #include <stdlib.h>
4 int main()
5 {
6 FILE *fp; /* 定义文件指针 */
7 int ch;
8 fp = fopen("./tmp", "w+"); /* 打开文件 */
9 if (fp == NULL)
10 {
11 perror("Open tmp failed "); /* 如果文件打开失败,输出错误信息 */
12 exit(1);
13 }
14 while ((ch=getchar()) != '!') /* 从键盘读入字符,直到输入“!”结束 */
15 {
16 fputc(ch, fp); /* 将读入的字符写到文件之中 */
17 }
18 rewind(fp); /* 重设读写位置 */
19 while ( (ch=fgetc(fp)) != EOF) /* 将文件内容一个字节一个字节地读出来,直到文件结束 */
20 {
21 putchar(ch); /* 将读出的字符输出到屏幕 */
22 }
23 fclose(fp);
24 return 0;
25 }

 

 1 /* example4.c */
2 #include <stdio.h>
3 #include <stdlib.h>
4 #define BUFFER_SIZE 256
5 int main()
6 {
7 char buffer[BUFFER_SIZE]; /* 定义缓冲区 */
8 int c;
9 FILE *fp; /* 定义文件指针 */
10 fp = fopen("./hello.c", "r"); /* 打开文件 */
11 if (fp == NULL)
12 {
13 perror("Open hello.c failed "); /* 如果文件打开失败,输出错误信息 */
14 exit(1);
15 }
16 c = 1;
17 while (fgets(buffer, BUFFER_SIZE, fp) != NULL) /* 逐行读取文件内容 */
18 {
19 printf("%d: %s", c++, buffer); /* 输出各行内容 */
20 }
21 fclose(fp); /* 关闭文件 */
22 return 0;
23 }

 

 1 /* example5.c */
2 #include <stdio.h>
3 #include <stdlib.h>
4 #define BUFFER_SIZE 256
5 int main(int argc, char **argv)
6 {
7 char buffer[BUFFER_SIZE]; /* 定义缓冲区 */
8 FILE *fp1, *fp2; /* 定义文件指针 */
9 if(argc != 3)
10 {
11 printf("Too few arguments.\n");
12 }
13 fp1 = fopen(argv[1], "r"); /* 打开源文件 */
14 if (fp1 == NULL)
15 {
16 perror("Open file1 failed "); /* 如果文件打开失败,输出错误信息 */
17 exit(1);
18 }
19 fp2 = fopen(argv[2], "w"); /* 打开目标文件 */
20 if (fp2 == NULL)
21 {
22 perror("Open file2 failed "); /* 如果文件打开失败,输出错误信息 */
23 exit(1);
24 }
25 while (!feof(fp1)) /* 测试是否读到文件末尾 */
26 {
27 fgets(buffer, BUFFER_SIZE, fp1); /* 逐行读取源文件内容尾 */
28 fputs(buffer, fp2); /* 逐行写入到目标文件之中 */
29 }
30 fclose(fp1); /* 关闭源文件 */
31 fclose(fp2); /* 关闭目标文件 */
32 printf("Done!\n");
33 return 0;
34 }

rewind函数
 
 void rewind(FILE * fp);

fseek函数
 
 int fseek(FILE *fp, long offset, int whence); fseek(fp, 0, SEEK_SET);

 fseek(fp, 0, SEEK_END);

ftell函数
 
 long ftell(FILE *fp);

 1 /* example3.c */
2 #include <stdio.h>
3 #include <stdlib.h>
4 int main()
5 {
6 FILE *fp; /* 定义文件指针 */
7 int i, ch, n;
8 fp = fopen("./tmp", "r"); /* 打开文件 */
9 if (fp == NULL)
10 {
11 perror("Open tmp failed "); /* 如果文件打开失败,输出错误信息 */
12 exit(1);
13 }
14 for (i=0; i<=7; i+=2)
15 {
16 fseek(fp, i, SEEK_SET); /* 重设读写位置 */
17 n = ftell(fp); /* 获取当前的读写位置 */
18 printf("Position : %ld\n", n+1);
19 ch=fgetc(fp); /* 从文件读入一个字节 */
20 printf("Character : ");
21 putchar(ch); /* 将字符输出到屏幕 */
22 printf("\n");
23 }
24 fclose(fp); /* 关闭文件 */
25 return 0;
26 }

3  数据块输入输出
对文件进行输入输出操作,也可以以数据块为单位进行。所谓数据块,是指一串固定长度的字节,例如一个整型数据、一个结构体,或一个固定长度的数组等。

 size_t fread(void *ptr, size_t size, size_t n, FILE *fp); size_t fwrite(void *ptr, size_t size, size_t n, FILE *fp);

 1 /* example6.c */
2 #include <stdio.h>
3 #include <stdlib.h>
4 #define N 3
5 struct student /* 定义结构体 */
6 {
7 int id;
8 int score;
9 };
10 int main()
11 {
12 struct student array[N]; /* 定义结构体数组 */
13 int i, n;
14 FILE *fp; /* 定义文件指针 */
15 fp = fopen("./test.dat", "w"); /* 打开文件 */
16 if (fp == NULL)
17 {
18 perror("Open test.dat failed "); /* 如果文件打开失败,输出错误信息 */
19 exit(1);
20 }
21 for(i=0; i<N; i++) /* 初始化结构体 */
22 {
23 printf("ID : ");
24 scanf("%d", &array[i].id);
25 printf("Score : ");
26 scanf("%d", &array[i].score);
27 }
28 n = fwrite(array, sizeof(struct student), N, fp); /* 将结构体数组写入到文件之中 */
29 if (n != N)
30 {
31 printf("Write file error"); /* 如果写入失败,输出信息 */
32 }
33 fclose(fp); /* 关闭文件 */
34 return 0;
35 }

 

 1 /* example7.c */
2 #include <stdio.h>
3 #include <stdlib.h>
4 #define N 3
5 struct student /* 定义结构体 */
6 {
7 int id;
8 int score;
9 };
10 int main()
11 {
12 struct student x[N]; /* 定义缓冲区 */
13 int i, n;
14 FILE *fp; /* 定义文件指针 */
15 fp = fopen("./test.dat", "r"); /* 打开文件 */
16 if (fp == NULL)
17 {
18 perror("Open test.dat failed "); /* 如果文件打开失败,输出错误信息 */
19 exit(1);
20 }
21 n = fread(x, sizeof(struct student), N, fp); /* 从文件中读取N个结构体 */
22 if (n != N) /* 如果实际读取长度小于N,输出具体原因 */
23 {
24 if(feof(fp)) /* 测试是否读到文件末尾 */
25 {
26 printf("End of file.");
27 }
28 else
29 {
30 printf("Read file error"); /* 输出错误信息 */
31 }
32 }
33 printf("ID\tScore\n");
34 for (i=0; i<N; i++)
35 {
36 printf("%d\t%d", x[i].id, x[i].score); /* 输出各结构体数组 */
37 printf("\n");
38 }
39 fclose(fp); /* 关闭文件 */
40 return 0;
41 }

三  格式化输入输出
格式化输出的函数

 int fprintf(FILE *fp, const char *format, ... );
 int printf(const char *format, ... );

 int fprintf(stdout, const char *format, ... );

format: % [+/-] [0] [m.n] [l] 转换字符
1.转换字符

2.指定输出精度 l

3. m.n
指定输出长度
如: 
 double x=0.123;
 printf("%9.4f\n", x);
  0.1230
9是总长度
这里空位补空格

4.空位填零 0
  int x=123;
  printf("%06d\n", x);
  000123

5.指定输出位置 + -
默认右对齐,加入-则可左对齐

char c[]=“ABCD”;
printf("%-5.3s\n", a);
printf("%+5.3s\n", a);

ABC
  ABC
 

格式化输入的函数

 int fscanf(FILE *fp, const char *format, ... );

 
 int scanf(const char *format, ... );
 
 int fscanf(stdin, const char *format, ... );
 

 scanf("%d %d", &x, &y);
 
 scanf("%d, %d", &x, &y);
 
 scanf("%10s", s); 10是读入总长度

 1 /* example13.c */
2 #include <stdio.h>
3 #include <stdlib.h>
4 int main()
5 {
6 int x;
7 int sum = 0;
8 while (scanf("%d", &x) == 1) /* 读入整数,赋给变量x */
9 {
10 sum += x; /* 累加 */
11 printf("\t%3d\n", sum); /* 输出结果 */
12 }
13 return 0;
14 }

其它应用

 1 /* example14.c */
2 #include <stdio.h>
3 #include <stdarg.h>
4 int sum(int num, ...) /* 求和 */
5 {
6 int v, i;
7 int sum = 0;
8 va_list vp; /* 定义指向可变参数列表的指针 */
9 va_start(vp, num); /* 使指针指向参数列表中的第一个可选参数 */
10 i = num;
11 while(i > 0)
12 {
13 v = va_arg(vp, int); /* 返回指针所指向的参数,并将其后移 */
14 sum += v;
15 i--;
16 }
17 va_end(vp);
18 return sum;
19 }
20 int main()
21 {
22 printf("%d\n", sum(2, 2, 3)); /* 输出计算结果 */
23 printf("%d\n", sum(4, 1, 2, 3, 4));
24 return 0;
25 }

 

 1 /* example15.c */
2 #include <stdio.h>
3 #include <stdarg.h>
4 int myprintf(char *format, ...) /* 定义可变参数函数 */
5 {
6 va_list vp; /* 定义指向可变参数列表的指针 */
7 int n;
8 va_start(vp, format); /* 使指针指向参数列表中的第一个可选参数 */
9 n = vprintf(format, vp); /* 调用vprintf函数,通过va_list传入输入参数 */
10 va_end(vp);
11 return n;
12 }
13 int main(void)
14 {
15 int x = 30;
16 float y = 0.36;
17 char *z = "abc";
18 myprintf("x = %d\ny = %g\nz = %s\n", x, y, z); /* 调用前面定义的printf函数,将数据输出到屏幕 */
19 return 0;
20 }

四   常见面试题
常见面试题1:调用fgets函数从文件中读取字符时,函数在满足什么条件时返回?

常见面试题2:调用fprintf函数进行格式化输出时,如何指定输出的长度和对齐方式?

原文链接: https://www.cnblogs.com/zeedmood/archive/2012/03/25/2417019.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    嵌入式成长轨迹18 【Linux应用编程强化】【Linux下的C编程 下】【标准输入输出】

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/45229

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 下午9:46
下一篇 2023年2月8日 下午9:47

相关推荐