设为首页 加入收藏

TOP

最全的李慧芹APUE-标准IO笔记(一)
2023-09-23 15:43:31 】 浏览:705
Tags:全的李 APUE- 标准 笔记

标准 IO

: 李慧芹老师的视频课程请点这里, 本篇为标准IO一章的笔记, 课上提到过的内容基本都会包含

I/O (Input & Output): 是一切实现的基础

stdio (标准IO)

sysio (系统调用IO / 文件IO)

系统IO是内核接口, 标准IO是C标准库提供的接口, 标准IO内部使用了系统IO

标准IO会合并系统调用, 可移植性好, 因此在两者都可以完成任务的情况下, 优先使用标准IO

stdio 的一系列函数

详细参考man(3); FILE类型贯穿始终, FILE类型是一个结构体

fopen(): 产生FILE

fclose()


fgetc()

fputc()

fgets()

fputs()

fread()

fwrite()


pintf()一族

scanf()一族


fseek()

ftell()

rewind()


fflush()

打开操作

// 打开文件操作, 运行成功时, 返回FILE指针, 失败则返回NULL且设置errno
// params:
// @path: 要打开的文件
// @mode: 打开的权限(如: 只读/读写/只写...)
FILE *fopen(const char *path, const char *mode);

const char *

面试题:

char *ptr = "abc";
ptr[0] = 'x'; // 语句2

问: 能否通过语句2得到值为"xbc"的字符串?

gcc编译会报错(修改常量值), 但Turbo C一类的编译器编译出的程序会运行通过

errno

ubuntu22系统中, 可以执行vim /usr/include/errno.h来查看相关信息

errno曾经是一个全局变量, 但目前已被私有化, 新建test.c:

#include <errno.h>

errno;

执行gcc -E test.ctest.c进行预处理, 会得到:

// MacOS操作系统上的运行结果:
extern int * __error(void);
(*__error());
// Ubuntu22上的运行结果:
(*__errno_location ());

可以看到, errno已经被转化为宏 (而不是int类型全局变量)

再新建测试程序errno.c:

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

int main(void)
{
    FILE *fp;

    fp = fopen();
    if (fp == NULL)
    {   
        fprintf(stderr, "fopen() failed! errno = %d\n", errno);
        exit(1);
    }   
    puts("OK");

    exit(0);
}

编译并运行该程序, 输出结果:

fopen() failed! errno = 2

标准C中定义的errno类型:

类型 序号 含义
EPERM 1 Operation not permitted
ENOENT 2 No such file or directory
ESRCH 3 No such process
EINTR 4 Interrupted system call
EIO 5 I/O error
ENXIO 6 No such device or address
E2BIG 7 Argument list too long
ENOEXEC 8 Exec format error
EBADF 9 Bad file number
ECHILD 10 No child processes
EAGAIN 11 Try again
ENOMEM 12 Out of memory
EACCES 13 Permission denied
EFAULT 14 Bad address
... ... ...

根据上表中展示的errno类型, 可以得知, 2代表了文件或目录不存在

可以调用perror()strerror()来将errno转化为error message

mode

mode必须以表格中的字符开头

符号 模式
r 以只读形式打开文件, 打开时定位到文件开始处
r+ 读写形式打开文件, 打开时定位到文件开始处
w 写形式打开文件, 有则清空, 无则创建
w+ 读写形式打开文件, 有则清空, 无则创建
a 追加只写的形式打开文件, 如文件不存在, 则创建文件; 打开时定位到文件末尾处 (文件最后一个有效字节的下一个位置)
a+ 追加读写的形式打开文件, 如文件不存在, 则创建文件; 读位置在文件开始处, 而写位置永远在文件末尾处

注意:

  1. rr+要求文件必须存在

  2. mode可以追加字符b, 如rb/r+b, b表示二进制流, 在POSIX环境(包括Linux环境)下, b可以忽略

面试题:

FILE *fp;
fp = fopen("tmp", "r+write"); // 语句2

问: 语句2是否会报错?

并不会, fopen函数只会识别r+, 后面的字符会被忽略

FILE *

fopen返回的FILE结构体指针指向的内存块存在在哪里?

堆上

有逆操作的, 返回指针的函数, 其返回的指针一定指向上某一块空间

如无逆操作, 则有可能指向堆, 也有可能指向静态区

关闭操作

由于fopen返回的指针在堆上, 因此需要有一逆操作释放这一堆上的空间

int fclose(FILE *fp);

小例子

一个进程中, 打开的文件个数的上限?

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

int main()
{
        FILE *fp;
        int cnt = 0;

        while (1)
        {
                fp = fopen("tmp", "r");
                if (fp == NULL)
                {
                        perror("fopen()");
                        break;
                }
                cnt ++;
        }

        printf("count = %d\n", cnt);

        exit(0);
}

运行结果:

fopen(): Too many open files
count = 1021

在不更改当前默认环境的情况下, 进程默认打开三个流: stdin, stdout, stderr

ulimit -a可以查看当前默认环境的资源限制, 其中包括默认最多打开流的个数:

$ ulimit -a
real-time non-blocking time  (microseconds, -R) unlimited
core file size              (blocks, -c) 0
data seg size               (kbytes, -d) unlimited
scheduling priority                 (-e) 0
file size                   (blocks, -f) unlimited
pending signals                     (-i) 7303
max locked memory           (kbytes, -l) 251856
max memory size             (k
首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C语言 内存布局 下一篇alog一个日志库

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目