初步了解I/O以及相关的API函数想把每个问题都细究,发现什么都解决不了。关于此部分,我先了解相关概念,懂得输入输出在linux操作系统是如何运作,以及如何调用相关的I/O函数即可,更为深入的以后在项目中碰到再说。
1、什么是标准 I/O
标准 I/O 指的是 ANSIC 中定义的用于 I/O 操作的一系列函数。
只要操作系统中安装了 C 库,标准 I/O 函数就可以调用。换句话说,如果程序中使用的是标准 I/O 函数,那么源代码不需要修改就可以在其他操作系统下编译运行,具有更好的可移植性。
2、I/O干什么用的(输入输出用的)
IO在计算机中指Input/Output,也就是输入和输出。由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘、网络等,就需要IO接口。
2、什么是标准 I/O下一个重要概念——流的含义
标准 I/O 的核心对象就是流。当用标准 I/O 打开一个文件时,就会创建一个 FILE 结构体描述该文件( 或者理解为创建一个 FILE 结构体和实际打开的文件关联起来)。我们把这个FILE 结构体形象地称为流。标准 I/O 函数都基于流进行各种操作。
4、流的相关函数
a、fopen();//流的开启
(b)fclose();//流的关闭
程序结束时会自动关闭所有打开的流。
(c)perror();错误处理:标准 I/O函数执行时如果出现错误,会把错误码保存在全局变量 errno中。程序员可以通过相应的函数打印错误信息。
代码解析
如果文件 1.txt 不存在,程序执行时会打印 fopen: No such file or directory
#include <stdio.h>
int main(int argc, const char *argv[])
{
FILE *fp; // 定义流指针
if ((fp = fopen("1.txt", "r")) == NULL) // fopen失败返回NULL
{
perror("fopen"); // 输出错误信息
return -1;
}
fclose(fp);//关闭流
return 0;
}
(d)strerror()函数语法要点:
(e)按字符(字节)输入
int getc(FILE * stream);
int fgetc(FILE * stream);
int getchar(void);
getc()和fgetc ()从指定的流中读取一个字符(节), getchar()从stdin中读取一个字符(节)。
(f)字符输出函数
int putc(int c, FILE * stream);
int fputc(int c, FILE * stream);
int putchar(int c);
putc()和 fputc()向指定的流输出一个字符(节), putchar()函数向 stdout 输出一个字符(节)。
编写fput.c文件
#include <stdio.h>
int main(int argc, const char *argv[])
{
int c;
while (1)
{
c = fgetc(stdin); // 从键盘读取一个字符
if ((c >= '0') && (c <= '9')) fputc(c, stdout); // 若输入的是数字,输出
if (c == '\n') break; // 若遇到换行符,跳出循环
}
return 0;
}
//stdin、stdout是什么?暂时不知。
运行结果如下。
linux@ubuntu:~$ ./fput
hello12345world
123452.
(g)按行输入
如果文件 1.txt 不存在,程序执行时会打
char * gets(char *s)
char * fgets(char * s, int size, FILE * stream)
s:存放输入字符串的缓冲区首地址
size:输入的字符串长度
stream:对应的流
gets 函数容易造成缓冲区溢出,不推荐大家使用。
fgets 从指定的流中读取一个字符串,当遇到\n 时,会读取\n 或读取 size-1 个字符后返回。
注意: fgets 不能保证每次都能读出一行。
(h) 行输出函数
int puts(const char *s)
int fputs(const char * s, FILE * stream)
s:存放输出字符串的缓冲区首地址
stream:对应的流
下面以 fgets()为例计算一个文本文件的行数。
fgets.c
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
int line = 0;
char buf[128];
FILE *fp;
if (argc < 2)
{
printf("Usage : %s <file>\n", argv[0]);
return -1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("fail to fopen");
return -1;
}
while(fgets(buf, 128, fp) != NULL)
{
if (buf[strlen(buf)-1] == '\n')
line++;
}
printf("The line of %s is %d\n", argv[1], line);
return 0;
}
(i) 以指定大小为单位读写文件
在文件流被打开之后,可对文件流按指定大小为单位进行读写操作。
(j) 每个打开的流内部都有一个当前读写位置。流在打开时,当前读写位置为 0,表示文件的开始位置。每读写一次后,当前读写位置自动增加实际读写的大小。在读写流之间可先对流进行定位,即移动到指定的位置再操作。
下面的例子为获取一个文件的大小。
ftell.c
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
if (argc < 2)
{
printf("Usage : %s <file>\n", argv[0]);
return -1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("fail to fopen");
return -1;
}
fseek(fp, 0, SEEK_END);
printf("The size of %s is %ld\n", argv[1], ftell(fp));
return 0;
}
(k)标准化输入输出函数
4、演示案例详解
a.实验目的
通过对文件进行复制,掌握流的基本操作。
b.实验内容
在程序中分别打开源文件和目标文件。循环从源文件中读取内容并写入目标文件。
c.实验步骤
(1)设计流程。
检查参数→打开源文件→打开目标文件→循环读写文件→关闭文件
(2)编写代码。
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define N 64
int main(int argc, char *argv[])
{
int n;
char buf[N];
FILE *fps, *fpd;
if (argc < 3)
{
printf("Usage : %s <src_file> <dst_file>\n", argv[0]);
return -1;
}
if ((fps = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "fail to fopen %s : %s\n", argv[1], strerror(errno));
return -1;
}
if ((fpd = fopen(argv[2], "w")) == NULL)
{
fprintf(stderr, "fail to fopen %s : %s\n", argv[2], strerror(errno));
fclose(fps);
return -1;
}
while((n = fread(buf, 1, N, fps)) >= 0)
{
fwrite(buf, 1, N, fpd);
}
fclose(fps);
fclose(fpd);
return 0;
}
跟着例程一个一个字的敲,便对该部分知识有着两三层的理解,大致知道有哪些函数,该如何用。具体用到的时候在返回来研究。