首页 > 其他分享 >C语言:标准IO

C语言:标准IO

时间:2022-09-02 16:11:06浏览次数:56  
标签:fp 文件 ch 函数 getc 模式 C语言 标准 IO

标准I/O

C语言标准I/O有许多专门的函数简化了处理不同I/O的问题。例如,printf()把不同形式的数据转换成与终端相适应的字符串输出。第二,输入和输出都是缓冲的也就是说,一次转移一大块信息而不是一字节信息(通常至少512字节)。

一个简单例子

下面是用C语言标准I/O读取文件和统计文件中的字符数的代码:

#include <stdio.h>
#include <stdlib.h>    // 提供 exit()的原型

int main(){
    // 读取文件时,存储每个字符的地方
    int ch;
    // “文件指针”
    FILE *fp;
    unsigned long count = 0;
    char fName[] = "C:\\Users\\MSI-\\Desktop\\test.txt";
    if ((fp = fopen(fName, "r")) == NULL)
    {
        printf("Can't open %s\n", fName);
        exit(EXIT_FAILURE);
    }
    while ((ch = getc(fp)) != EOF)
    {
        //与 putchar(ch); 相同
        putc(ch, stdout);
        count++;
    }
    fclose(fp);
    printf("\nFile %s has %lu characters\n", fName, count);

    return 0;
}

文件内容:

image-20220902142011339

运行结果:

image-20220902142030821

fopen()函数

该程序使用fopen()函数打开文件。该函数声明在stdio.h中。它的第1个参数是待打开文件的名称,更确切地说是一个包含该文件名的字符串地址。第2个参数是一个字符串,指定待打开文件的模式。

模式字符串 含义
"r" 以读模式打开文件
"w" 以写模式打开文件,把现有文件的长度截为0,如果文件不存在,则创建一个新文件
"a" 以写模式打开文件,在现有文件末尾添加内容,如果文件不存在,则创建一个新文件
"r+" 以更新模式打开文件(即可以读写文件)
"w+" 以更新模式打开文件(即,读和写),如果文件存在,则将其长度截为0;如果文件不存在,则创建一个新文件
"a+" 以更新模式打开文件(即,读和写),在现有文件的末尾添加内容,如果文件不存在则创建一个新文件;可以读整个文件,但是只能从末尾添加内容
"rb"、"wb"、"ab"、"rb+"、"r+b"、"wb+"、"w+b"、"ab+"、"a+b" 与上一个模式类似,但是以二进制模式而不是文本模式打开文件
"wx"、"wbx"、"w+x"、"wb+x"、"w+bx" (C11)类似非x模式,但是如果文件已存在或以独占模式打开文件,则打开文件失败

像UNIX和Linux这样只有一种文件类型的系统,带b字母的模式和不带b字母的模式相同。

新的C11新增了带x字母的写模式,与以前的写模式相比具有更多特性。第一,如果以传统的一种写模式打开一个现有文件,fopen()会把该文件的长度截为0,这样就丢失了该文件的内容。但是使用带x字母的写模式,即使fopen()操作失败,原文件的内容也不会被删除。第二,如果环境允许,x模式的独占特性使得其他程序或线程无法访问正在被打开的文件。

如果使用任何一种"w"模式(不带x字母)打开一个现有文件,该文件的内容会被删除,以便程序在一个空白文件中开始操作。然而,如果使用带x字母的任何一种模式,将无法打开一个现有文件。

程序成功打开文件后,fopen()将返回文件指针,其他I/O函数可以使用这个指针指定该文件。文件指针(该例中是fp)的类型是指向FILE的指针,FILE是一个定义在stdio.h中的派生类型。

文件指针fp并不指向实际的文件,它指向一个包含文件信息的数据对象,其中包含操作文件的I/O函数所用的缓冲区信息。因为标准库中的I/O函数使用缓冲区,所以它们不仅要知道缓冲区的位置,还要知道缓冲区被填充的程度以及操作哪一个文件。标准I/O函数根据这些信息在必要时决定再次填充或清空缓冲区。fp指向的数据对象包含了这些信息(该数据对象是一个结构体)。

getc()和putc()函数

getc()putc()函数与getChar()putChar()函数类似。所不同的是,要告诉getc()putc()函数使用哪一个文件,下面这条语句的意思是“从标准输入中获取一个字符”:

ch = getchar();

然而,下面这条语句的意思是“从fp指定的文件中获取一个字符”:

ch = getc(fp);

与此类似,下面语句的意思是“把字符ch放入FILE指针fpout指定的文件中”:

putc(ch, fpout);

putc()函数的参数列表中,第1个参数是待写入的字符,第2个参数是文件指针。

上面程序中把stdout作为putc()的第2个参数,putc(ch, stdout)putchar(ch)的作用相同。

实际上,putchar()函数一般通过putc()来定义。与此类似,getchar()也通过使用标准输入的getc()来定义。

文件结尾

从文件中读取数据的程序在读到文件结尾时要停止。如何告诉程序已经读到文件结尾?如果getc()函数在读取一个字符时发现是文件结尾,它将返回一个特殊值EOF。所以C程序只有在读到超过文件末尾时才会发现文件的结尾(一些其他语言用一个特殊的函数在读取之前测试文件结尾,C语言不同)。

为了避免读到空文件,应该使用入口条件循环(不是do while)进行文件输入。鉴于getc()(和其他C输入函数)的设计,程序应该在进入循环体之前先尝试读取。如下面设计所示:

// 设计范例 #1
int ch;               // 用int类型的变量存储EOF
FILE * fp;
fp = fopen("wacky.txt", "r");
ch = getc(fp);        // 获取初始输入
while (ch != EOF)
{
     putchar(ch);     // 处理输入
     ch = getc(fp);   // 获取下一个输入
}

以上代码可简化为:

// 设计范例 #2
int ch;
FILE * fp;
fp = fopen("wacky.txt", "r");
while (( ch = getc(fp)) != EOF)
{
     putchar(ch);    //处理输入
}

fclose()函数

fclose(fp)函数关闭fp指定的文件,必要时刷新缓冲区。对于较正式的程序,应该检查是否成功关闭文件。如果成功关闭,fclose()函数返回0,否则返回EOF

if (fclose(fp) != 0)
     printf("Error in closing file %s\n", argv[1]);

如果磁盘已满、移动硬盘被移除或出现I/O错误,都会导致调用fclose()函数失败。

指向标准文件的指针

stdio.h头文件把3个文件指针与3个标准文件相关联,C程序会自动打开这3个标准文件。如下表所示:

标准文件 文件指针 通常使用的设备
标准输入 stdin 键盘
标准输出 stdout 显示器
标准错误 stderr 显示器

这些文件指针都是指向FILE的指针,所以它们可用作标准I/O函数的参数,如fclose(fp)中的fp

实现拷贝文件的程序

下面程序实现拷贝文件:

#include <stdio.h>
#include <stdlib.h> 

int main() {
    FILE  * in, *out;

    int ch;

    char inName[] = "C:\\Users\\MSI-\\Desktop\\test.txt";
    char outName[] = "C:\\Users\\MSI-\\Desktop\\test2.txt";
    if((in = fopen(inName, "r")) == NULL) {
        printf("Can't open %s\n", inName);
        exit(1);
    }

    if((out = fopen(outName, "w")) == NULL) {
        printf("Can't create file %s\n", outName);
        exit(1);
    }

    while ((ch = getc(in)) != EOF) {
        putc(ch, out);
    }

    if(fclose(in) != 0 || fclose(out) != 0) {
        fprintf(stderr, "error");
    }
    return 0;
}

标签:fp,文件,ch,函数,getc,模式,C语言,标准,IO
From: https://www.cnblogs.com/wwjj4811/p/16650305.html

相关文章