标准IO常用API

函数的参数和返回值使用方法:

参数:

如果参数是指针,通常都是地址传参

如果参数是一个一级指针,定义一个普通变量取地址,

如果是一个二级指针,定义一个一级指针取地址,以此类推

注意:字符串除外

返回值:

返回值是什么类型,就定义什么类型的变量接收

  1. fopen()/fclose()

#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
功能:
打开或者创建一个文件
参数:
pathname:
要打开或者创建的文件名,可以跟路径,如果不跟路径,默认就是当前路径
mode:
操作权限
r   以只读的方式打开,如果文件不存在则报错,文件指针定位到文件的起始位置
r+  以读写的方式打开,如果文件不存在则报错,文件指针定位到文件的起始位置 
w   以只写的方式打开,如果文件存在则清空,文件不存在则创建,文件指针定位到文件的起始位置
w+  以读写的方式打开,如果文件存在则清空,文件不存在则创建,文件指针定位到文件的起始位置
a   以只写的方式打开,如果文件存在则追加,文件不存在则创建,文件指针定位到文件的起末尾位置
a+  以读写的方式打开,如果文件存在则追加,文件不存在则创建,文件指针定位到文件的起末尾位置
返回值:
成功:
文件指针
失败:
NULL
    
#include <stdio.h>
int fclose(FILE *stream);
功能:
关闭一个文件指针,如果关闭了文件指针,就无法再通过这个文件指针对文件进行操作了
参数:
stream:
文件指针,fopen的返回值
返回值:
成功:
0
失败:
EOF

  1. perror()/errno

#include <stdio.h>
void perror(const char *s);
功能:
输出一个函数调用失败之后的错误信息
参数:
s:
提示语句
返回值:
无

#include <errno.h>
int errno;
errno是一个全局变量,用于输出函数调用失败的错误码,
可以调用strerror函数通过errno值打印错误信息

#include <stdio.h>
#include <errno.h>

int main(int argc, char const *argv[])
{
    //使用fopen函数打开或者创建一个文件
    FILE *fp;
    //r:只读,如果文件不存在则报错
    //fp = fopen("file.txt", "r");
    //w:只写,如果文件不存在则创建,如果存在则清空
    //fp = fopen("file.txt", "w");
    //只写:如果文件不存在则创建,如果文件存在则追加
    fp = fopen("file.txt", "a");
    if(fp == NULL)
    {
        //errno是一个保存在errno.h中的全局变量,用于获取函数调用失败的错误码
        printf("errno = %d\n", errno);
        //使用perror函数打印函数调用失败的错误信息
        perror("fopen error");
        return -1;
    }

    //关闭文件指针
    fclose(fp);
    
    return 0;
}

3.fgetc()/fputc()

3.1 fgetc()

#include <stdio.h>
int fgetc(FILE *stream);
功能:
从文件中读取一个字符
参数:
stream:
文件指针
返回值:
成功:
读取的字节
失败:
EOF
如果文件内容读取完毕,也会返回EOF

#include <stdio.h>

int main(int argc, char const *argv[])
{
    //从终端读取一个字符
#if 0
    int a = fgetc(stdin);
    printf("a = %c %d\n", a, a);
#endif

    //从文件中读取一个字符
    FILE *fp;
    fp = fopen(argv[1], "r");
    if(fp == NULL)
    {
        perror("fopen error");
        return -1;
    }

    int a;
#if  0
    if((a = fgetc(fp)) == EOF)
    {
        perror("fgetc error");
        return -1;
    }
    printf("a = %c %d\n", a, a);

    if((a = fgetc(fp)) == EOF)
    {
        perror("fgetc error");
        return -1;
    }
    printf("a = %c %d\n", a, a);
#endif
    //文件中每一行的结尾都有一个结束标志换行符,fgetc可以读取到整个换行符
    while((a = fgetc(fp)) != EOF)
    {
        printf("a = %c %d\n", a, a);
    }

    fclose(fp);

    return 0;
}

3.2 练习:编写函数,获取文件的行数

#include <stdio.h>

int GetLine(const char *filename)
{
    FILE *fp;
    if((fp = fopen(filename, "r")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    //通过fgetc函数读取文件内容,比较行结束符的个数
    int ch, num = 0;
    while((ch = fgetc(fp)) != EOF)
    {
        if(ch == '\n')
        {
            num++;
        }
    }

    return num;
}

int main(int argc, char const *argv[])
{
    int len;
    len = GetLine(argv[1]);
    if(len >= 0)
    {
        printf("%s文件一共有%d行\n", argv[1], len);
    }
    
    return 0;
}

3.3 fputc()

#include <stdio.h>
int fputc(int c, FILE *stream);
功能:
向指定的文件中写入一个字符
参数:
c:
要写入的字符
stream:
文件指针
返回值:
成功:
写入的字符
失败:
EOF

#include <stdio.h>

int main(int argc, char const *argv[])
{
    //向终端写入一个字符
#if 0
    fputc('w', stdout);
    fputc(10, stdout);
    int ch = 97;
    fputc(ch, stdout);
    fputc(10, stdout);
#endif

    //向文件写入一个字符
    FILE *fp;
    if((fp = fopen(argv[1], "w+")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    if(fputc('w', fp) == EOF)
    {
        perror("fputc error");
        return -1;
    }
    if(fputc('w', fp) == EOF)
    {
        perror("fputc error");
        return -1;
    }
    if(fputc('h', fp) == EOF)
    {
        perror("fputc error");
        return -1;
    }
    if(fputc('o', fp) == EOF)
    {
        perror("fputc error");
        return -1;
    }

    //如果先往文件中写数据,然后读数据,读的位置是最后写
    //完数据的下一个位置,因为写和读的文件指针定位的位置
    //是同一个
#if 0
    int ch;
    while((ch = fgetc(fp)) != EOF)
    {
        printf("ch = %c %d\n", ch, ch);
    }
#endif
    fclose(fp);

    return 0;
}

3.4 练习:实现cp功能

#include <stdio.h>

//使用fgetc和fputc函数实现命令cp的功能

int main(int argc, char const *argv[])
{
    //cp命令的功能为读取一个文件的内容写入另一个文件
    //打开或者创建这两个文件
    FILE *fp_r, *fp_w;
    if((fp_r = fopen(argv[1], "r")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    if((fp_w = fopen(argv[2], "w")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    //读取argv[1]文件的内容写入argv[2]文件
    int ch;
    while((ch = fgetc(fp_r)) != EOF)
    {
        fputc(ch, fp_w);
    }

    printf("cp done\n");

    fclose(fp_r);
    fclose(fp_w);

    return 0;
}

4.fgets()/fputs()

4.1 fgets()

#include <stdio.h>
char *fgets(char *s, int size, FILE *stream);
功能:
从文件中读取一个字符串
参数:
s:
保存读取的内容
size:
要读取的字节数
stream:
文件指针
返回值:
成功:
返回读取的内容
失败:
NULL
如果读到文件末尾,也返回NULL

#include <stdio.h>
#include <string.h>

int main(int argc, char const *argv[])
{
    //从终端读取一个字符串
#if 0
    //如果输入的数据的字节数小于第二个参数,会将回车符也当做是字符保存在第一个参数里面
    //如果输入的数据的字节数大于第二个参数n,则只会保存n-1个字节,最后一个位置补\0
    //注意需要保证第一个参数足够大,否则会内存越界
    char str[32] = {0};
    fgets(str, 32, stdin);
    //如果输入的字节数小于第二个参数,会多出一个换行符,所以我们需要处理整个垃圾字符
    //处理的方法是将\n替换成\0
    str[strlen(str) - 1] = '\0';
    printf("str = %s\n", str);
#endif

    //从文件中读取一个字符串
    FILE *fp;
    if((fp = fopen(argv[1], "r")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    //如果设置的第二个参数n的值小于一行内容,则只会读取n-1个字节,最后一个位置补\0
    //当fgets读取文件内容时,不管什么时候,只要读取的时候遇到行结束符,
    //就会立即结束本次的读取

    char buf[32] = {0};
    fgets(buf, 8, fp);
    printf("buf = [%s]\n", buf);
    
    char buf1[32] = {0};
    fgets(buf1, 8, fp);
    printf("buf1 = [%s]\n", buf1);

    return 0;
}

4.2 练习:使用fgets获取文件的行数

#include <stdio.h>
#include <string.h>

int GetLine(const char *filename)
{
    FILE *fp;
    if((fp = fopen(filename, "r")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    char buf[32] = {0};
    int num = 0;
    while(fgets(buf, 32, fp) != NULL)
    {
        //hello world\n\0]
        if(buf[strlen(buf) - 1] == '\n')
        {
            num++;
        }
    }

    return num;
}

int main(int argc, char const *argv[])
{
    int len = GetLine(argv[1]);
    if(len >= 0)
    {
        printf("%s文件一共有%d行\n", argv[1], len);
    }
    
    return 0;
}

4.3 fputs()

#include <stdio.h>
int fputs(const char *s, FILE *stream);
功能:
向文件写入一个字符串
参数:
s:
要写入的字符串
stream:
文件指针
返回值:
成功:
1
失败:
EOF

#include <stdio.h>

int main(int argc, char const *argv[])
{
    //向终端写入一个字符串
#if 0
    int n = fputs("hello world\n", stdout);
    printf("n = %d\n", n);
    n = fputs("nihao bei\0jing", stdout);
    printf("n = %d\n", n);
#endif

    //向文件写入数据
    FILE *fp;
    if((fp = fopen(argv[1], "w")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    int n = fputs("hello world\n", fp);
    printf("n = %d\n", n);

    return 0;
}

5.fprintf()/sprintf()

#include <stdio.h>
#include <string.h>

int main(int argc, char const *argv[])
{
    char name[32] = "zhangsan";

    FILE *fp;
    if((fp = fopen(argv[1], "w")) == NULL)
    {
        perror("fopen error");
        return -1;
    }
    // char buf[32] = "My name is ";
    // strcat(buf, name);
    // fputs(buf, fp);
    
    //将按照格式输出的字符串写入文件
    fprintf(fp, "My name is %s\n", name);

    char buf1[32] = {0};
    //将按照格式输出的字符串写入数组中
    sprintf(buf1, "My name is %s", name);
    printf("buf1 = %s\n", buf1);

    return 0;
}

作业:

在家目录下创建一个文件test.txt,每过一秒向文件里面写入一行内容,例如:

001. 2018-06-22 15:16:30

002. 2018-06-22 15:16:31

003. 2018-06-22 15:16:32

004. 2018-06-22 15:16:33

005. 2018-06-22 15:16:34

程序退出之后,下一次运行时接着之前的内容继续写,并且编号是连续的

006. 2018-06-22 15:17:23

007. 2018-06-22 15:17:24

提示:

使用time函数可以获取从1970年1月1日00:00:00到当前的所有的秒数

使用localtime将其转化为日期

#include <time.h>
time_t time(time_t *tloc);
功能:获取从1970年1月1日0时0分0秒到当前的所有秒数
参数:
    tloc:获取的秒数
返回值:
    成功:获取的秒数
    失败:-1
    
#include <time.h>
struct tm *localtime(const time_t *timep);
功能:将time函数获取的秒数转化为当前的日期和时间
参数:
    timep:通过time函数获取的秒数
返回值:
    成功:转化后的日期和时间
        struct tm {
               int tm_sec;    /* 秒 (0-60) */
               int tm_min;    /* 分 (0-59) */
               int tm_hour;   /* 小时 (0-23) */
               int tm_mday;   /* 日 (1-31) */
               int tm_mon;    /* 月 (0-11) */
               int tm_year;   /* 年 (-1900) */
               int tm_wday;   /* 星期 (0-6, Sunday = 0) */
               int tm_yday;   /* 一年的第几天 (0-365, 1 Jan = 0) */
               int tm_isdst;  /* Daylight saving time */
           };
    失败:NULL

#include <stdio.h>
#include <time.h>

int main(int argc, char const *argv[])
{
    //以后如果见到_t类型的数据类型,称之为类整形,
    //一般都是整数类型取别名得到的
    time_t mytime;
    time(&mytime);
    printf("mytime = %ld\n", mytime);

    //通过localtime函数获取日期和时间
    struct tm *mytm = localtime(&mytime);
    printf("%04d/%02d/%02d %02d:%02d:%02d\n", mytm->tm_year+1900, mytm->tm_mon+1, mytm->tm_mday,mytm->tm_hour, mytm->tm_min, mytm->tm_sec);

    return 0;
}

#include <stdio.h>
#include <time.h>
#include <unistd.h>

#define FILENAME "/home/stu/test.txt"

int main(int argc, char const *argv[])
{
    //现在家目录下创建一个文件test.txt
    FILE *fp;
    if((fp = fopen(FILENAME, "a+")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    //获取当前文件的行数
    int ch;
    int len = 0;
    while((ch = fgetc(fp)) != EOF)
    {
        if(ch == '\n')
        {
            len++;
        }
    }

    //循环将数据写入文件
    time_t mytime;
    struct tm *mytm;
    while(1)
    {
        len++;
        time(&mytime);
        mytm = localtime(&mytime);

        printf("%03d. %04d/%02d/%02d %02d:%02d:%02d\n",len, mytm->tm_year+1900, mytm->tm_mon+1, mytm->tm_mday,mytm->tm_hour, mytm->tm_min, mytm->tm_sec);

        fprintf(fp, "%03d. %04d/%02d/%02d %02d:%02d:%02d\n",len, mytm->tm_year+1900, mytm->tm_mon+1, mytm->tm_mday,mytm->tm_hour, mytm->tm_min, mytm->tm_sec);
        fflush(fp);
        //因为对文件操作是全缓冲,全缓冲刷新缓冲区的方法:1、程序正常结束 2、使用fflush函数 3、缓冲区满,因为要对文件进行实时写入,所以要调用fflush()进行刷新

        sleep(1);
    }

    return 0;
}

6.获取行缓冲和全缓冲大小

#include <stdio.h>

int main(int argc, char const *argv[])
{
    //stdout
    printf("hello world\n");
    printf("行缓冲大小:%ld字节\n", stdout->_IO_buf_end - stdout->_IO_buf_base);
    
    FILE *fp = fopen("file.txt", "w");
    fputc('w', fp);
    printf("全缓冲大小:%ld字节\n", fp->_IO_buf_end - fp->_IO_buf_base);

    return 0;
}

7.fread()/fwrite()

#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:
从文件中读取任意类型的内容
参数:
ptr:
保存的数据
size:
每一个块(对象)的长度
nememb:
块数(对象数)
stream:
文件指针
返回值:
成功:
实际读取的块数(对象数)
失败:
0
读取到文件末尾也返回0
    
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
功能:
向文件写入任意类型的内容
参数:
ptr:
要写入的数据
size:
每一个块(对象)的长度
nememb:
块数(对象数)
stream:
文件指针
返回值:
成功:
写入的块数(对象数),从第一个参数的首地址数据开始一直写指定的字节数
失败:
0

fwrite.c

#include <stdio.h>

int main(int argc, char const *argv[])
{
    if(argc < 2)
    {
        fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
        return -1;
    }
    FILE *fp;
    if((fp = fopen(argv[1], "w")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    //使用fwrite函数向文件写入内容

    //string
    // size_t n = fwrite("hello world", 2, 5, fp);
    // printf("n = %lu\n", n);

    //array
    // int a[6] = {100, 200, 300, 400, 500, 600};
    // size_t n = fwrite(a, 4, 6, fp);
    // printf("n = %lu\n", n);

    //struct
    typedef struct{
        int a;
        char b;
        char c[32];
    }MSG;
    MSG msg = {100, 'w', "hello world"};
    size_t n = fwrite(&msg, sizeof(msg), 1, fp);
    printf("n = %lu\n", n);

    return 0;
}

fread.c

#include <stdio.h>

int main(int argc, char const *argv[])
{
    if(argc < 2)
    {
        fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
        return -1;
    }
    FILE *fp;
    if((fp = fopen(argv[1], "r")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    //使用fread函数读取文件内容

    //string
    // char buf[32] = {0};
    // size_t n = fread(buf, 2, 100, fp);
    // printf("n = %lu, buf = %s\n", n, buf);

    //array
    // int a[6];
    // size_t n = fread(a, 4, 5, fp);
    // printf("n = %lu, a[0] = %d, a[1] = %d, a[2] = %d\n", n, a[0], a[1], a[2]);

    //struct
    typedef struct{
        int a;
        char b;
        char c[32];
    }MSG;
    MSG msg;
    size_t n = fread(&msg, sizeof(msg), 1, fp);
    printf("n = %lu, a = %d, b = %c, c = %s\n", n, msg.a, msg.b, msg.c);

    return 0;
}

8.fseek()/rewind()/ftell()

#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
功能:
定位文件指针的位置
参数:
stream:
文件指针
offset:
要偏移的位置,可正可负
whence:
相对位置
SEEK_SET
文件起始位置,为0
SEEK_CUR  
文件当前位置
SEEK_END   
文件末尾位置,最后一个字符的下一个位置
返回值:
成功:
0
失败:
-1
    
void rewind(FILE *stream);
功能:
将文件指针定位到起始位置
参数:
stream:
文件指针
返回值:
无
 
rewind(fp) <==> fseek(fp, 0, SEEK_SET);

long ftell(FILE *stream);
功能:
获取当前文件指针定位的位置
参数:
stream:
文件指针
返回值:
成功:
当前文件指针定位的位置
失败:
-1

#include <stdio.h>

int main(int argc, char const *argv[])
{
    if(argc < 2)
    {
        fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
        return -1;
    }

    FILE *fp;
    //如果fopen执行是权限设置为a或者a+,写操作的文件指针的位置
    //永远无法改变,只能在文件末尾,但是读操作没有影响
    if((fp = fopen(argv[1], "a+")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    //获取当前文件指针的位置
    printf("offset = %ld\n", ftell(fp));

    fputs("0123456789", fp);

    //获取当前文件指针的位置
    printf("offset = %ld\n", ftell(fp));

    //将文件指针的位置定位到起始位置
    // rewind(fp);
    //fseek(fp, 0, SEEK_SET);

    //通过fseek定位文件指针的位置
    //定位到第四个位置
    // fseek(fp, 4, SEEK_SET);
    //定位到文件倒数第四个位置
    fseek(fp, -4, SEEK_END);
    printf("offset = %ld\n", ftell(fp));

    fputs("abcdefg", fp);

    rewind(fp);
    char buf[64] = {0};
    fgets(buf, 32, fp);
    printf("buf = [%s]\n", buf);

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小徐的记事本

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值