5.1 引言
5.2 流和FILE对象
第三章中,所有I/O函数都是针对文件描述符的。
文件描述符,类似于键值对
文件描述符 | 文件指针 |
---|---|
3 | 0x00000024 |
而对于标准I/O库,他们的操作则是围绕着流进行的
为什么需要流呢,因为流无需考虑格式转化的问题
5.3 标准输入、标准输出和标准错误
对于一个进程预定义了三个流
标准输入、输出、错误分别对应0、1、2,这就是为什么文件描述符一般从3开始的原因
标准输入 | 0 | STDIN_FILENO | stdin |
---|---|---|---|
标准输出 | 1 | STDOUT_FILENO | stdout |
标准错误 | 2 | STDERR_FILENO | stderr |
简单展示
#标准输入
fyh@VM-16-14-ubuntu:~/note$ cat > ./true
aaa
bb
cc
^C
fyh@VM-16-14-ubuntu:~/note$ cat true
aaa
bb
cc
#标准输出
root@VM-16-14-ubuntu:~# tty
/dev/pts/4
root@VM-16-14-ubuntu:~# echo "Hello World" > /dev/pts/4
Hello World
#标准错误
fyh@VM-16-14-ubuntu:~/note$ ll a
ls: cannot access 'a': No such file or directory
fyh@VM-16-14-ubuntu:~/note$ ll a 2>./error
fyh@VM-16-14-ubuntu:~/note$ cat error
ls: cannot access 'a': No such file or directory
在 C 语言中,stdin
、stdout
和 stderr
是三个标准的文件指针,分别用于处理标准输入、标准输出和标准错误流。它们是由标准库 <stdio.h>
提供的。以下是它们的详细解释和使用示例:
- stdin(标准输入):
stdin
是标准输入流,通常从键盘读取数据。- 可以使用函数如
scanf
、fgets
等从stdin
读取数据。
- stdout(标准输出):
stdout
是标准输出流,通常用于向屏幕输出数据。- 可以使用函数如
printf
、fprintf(stdout, ...)
等向stdout
写入数据。
- stderr(标准错误):
stderr
是标准错误流,专门用于输出错误信息或诊断信息。- 可以使用函数如
fprintf(stderr, ...)
向stderr
写入数据。
5.4 缓冲
关于为什么要减少调用read和write的调用
关于标准I/O提供的3种类型的缓冲
- 全缓冲
- 当缓冲区存满的时候,才写入磁盘,减少缓冲次数,能明显带来的好处就是效率提升和磁盘的寿命
- 行缓冲
- 当缓冲区识别到换行后,将缓冲区的内容发送到输出设备
- 不带缓冲
- 每次输入输出都直接和硬件交互,不经过缓冲区
标准错误是不带缓存的
如果涉及终端设备的其他流,则它们是行缓存的;否则就是全缓存
setbuf
#include <stdio.h>
void setbuf(FILE *stream, char *buffer);
参数
#include <stdio.h>
int
main()
{
FILE *fp;
if ((fp = fopen("test.txt", "w")) == NULL)
printf("fopen test.txt error!");
char buff[1024];
//将文件流 fp 的缓冲区设置为 buff。这意味着对该文件的 I/O 操作将使用这个缓冲区,从而提高效率。
setbuf(fp, buff);
//把Hello,Wrold写入fp文件流
fprintf(fp, "Hello, World!\n");
fclose(fp);
return 0;
}
setvbuf
#include <stdio.h>
int setvbuf(FILE *stream, char *buffer, int mode, size_t size);
参数
-
stream
:指向要设置缓冲区的文件流。 -
buffer
:指向缓冲区的指针。如果为NULL
,则由系统自动分配缓冲区。 -
mode
:缓冲模式,可以是以下值之一:_IOFBF
:全缓冲,只有缓冲区满时才进行实际的 I/O 操作。_IOLBF
:行缓冲,当遇到换行符或缓冲区满时进行 I/O 操作。_IONBF
:无缓冲,所有 I/O 操作立即执行。
-
返回值
-
宽定向正值
-
字节定向负值
-
未定向0
#include <stdio.h>
int
main()
{
FILE *fp;
if ((fp = fopen("test.txt", "w")) == NULL)
printf("fopen test.txt error!");
char buff[1024];
//将文件流 fp 的缓冲区设置为 buff。这意味着对该文件的 I/O 操作将使用这个缓冲区,从而提高效率。
setvbuf(fp, buff, _IOFBF, sizeof(buff) != 0);
//把Hello,Wrold写入fp文件流
fprintf(fp, "Hello, World!\n");
fclose(fp);
return 0;
}
fflush
强制刷新流
#include <stdio.h>
int fflush(FILE *stream);
参数
5.5 打开流
fopen
#include <stdio.h>
FILE *fopen(const char *filename, const char *mode);
参数
-
filename
:要打开的文件的名称。 -
mode
:文件打开模式,如"r"
(只读)、"w"
(写入,文件不存在则创建,存在则清空)、"a"
(追加)等。
返回值
-
成功时,返回一个指向
FILE
结构的指针。 -
失败时,返回
NULL
。
freopen
#include <stdio.h>
FILE *freopen(const char *filename, const char *mode, FILE *stream);
参数
-
filename
:要重新打开的文件的名称。 -
mode
:文件打开模式,如"r"
(只读)、"w"
(写入,文件不存在则创建,存在则清空)、"a"
(追加)等。 -
stream
:要重新打开的文件流。 -
成功时,返回一个指向
FILE
结构的指针。 -
失败时,返回
NULL
。
#include <stdio.h>
int
main()
{
FILE *fp, *fp2;
if ((fp = fopen("test.txt", "w")) == NULL)
printf("fopen test.txt error!");
char buff[1024];
//将文件流 fp 的缓冲区设置为 buff。这意味着对该文件的 I/O 操作将使用这个缓冲区,从而提高效率。
setvbuf(fp, buff, _IOFBF, sizeof(buff) != 0);
//对于以打开的流先关闭,再打开
if ((fp2 = freopen("test.txt", "w", stdout)) == NULL)
printf("fopen test.txt error!");
//把Hello,Wrold写入fp文件流
//正常情况应该被fp流覆盖,但是文件的流已经被fp2打开
fprintf(fp2, "fp2 Hello, World!\n");
fprintf(fp, "fp Hello, World!\n");
fclose(fp);
fclose(fp2);
return 0;
}
fdopen
#include <stdio.h>
FILE *fdopen(int fd, const char *mode);
参数
mode的参数
mode | 说明 | 标志 |
---|---|---|
r 或 rb | 读打开 | O_RDONLY |
w 或 wb | 把文件截断至长度0长,写打开 | O_WRONLY | O_CREAT | O_TRUNC |
a 或 ab | 追加:为在文件尾写而打开,或为写而创建 | O_WRONLY | O_CREAT | O_APPEND |
r+ 或 r+b 或 rb+ | 读写打开 | O_RDWR |
w+ 或 w+b 或 wb+ | 把文件截断至长度0长,读写打开 | O_RDWR | O_CREAT | O_TRUNC |
a+ 或 a+b 或 ab+ | 追加读写 | O_RDWR | O_CREATE | O_APPEND |
“把文件截断至长度0长” 即为从文件起始处开始写, 覆盖
"追加:为在文件尾写而打开" 即为从文件末位处开始写, 追加
三者的区别
1、fopen
是打开路径上的一个文件,或者当前目录的一个文件,可以的形式为/tmp/test.txt或者test.txt。
2、freopen
这里简要说明就是如果流是被打开的,则会先关闭在打开,具体上面贴有代码。
3、fdopen
则可以打开一个以有的文件描述符指向的文件
fclose
关闭一个打开的流
#include <stdio.h>
int fclose(FILE *fp);
5.6 读和写流
getc
#include <stdio.h>
int getc(FILE *stream);
参数
-
stream
:指向FILE
结构的指针,表示要读取字符的文件流。
返回值
-
成功时,返回读取的字符(作为一个
unsigned char
转换为int
类型)。 -
失败或到达文件末尾时,返回
EOF
。
fgetc
#include <stdio.h>
int fgetc(FILE *stream);
参数
-
stream
:指向FILE
结构的指针,表示要读取字符的文件流。
返回值
-
成功时,返回读取的字符(作为一个
unsigned char
转换为int
类型)。 -
失败或到达文件末尾时,返回
EOF
。
#include <stdio.h>
int main() {
FILE *fp;
if ((fp = fopen("test.txt", "r")) == NULL)
perror("Failed to open file");
int ch;
while ((ch = fgetc(fp)) != EOF) {
putchar(ch);
}
fclose(fp);
return 0;
}
getchar
#include <stdio.h>
int getchar(void);
参数
#include <stdio.h>
int main() {
int ch;
printf("Enter some text (Ctrl+D to end):\n");
while ((ch = getchar()) != EOF) {
putchar(ch);
}
return 0;
}
ferror
用于检查文件流是否发生了错误。
#include <stdio.h>
int ferror(FILE *stream);
参数
feof
用于检查文件流是否到达了文件末尾。
#include <stdio.h>
int feof(FILE *stream);
参数
clearerr
用于清除文件流的错误和文件结束状态。
#include <stdio.h>
void clearerr(FILE *stream);
参数
stream
:指向FILE
结构的指针,表示要清除状态的文件流。
ungetc
用于将一个字符推回到文件流中,使得下次读取时可以重新读取该字符。它在处理文件流时非常有用,特别是在需要回退一个字符的情况下。
#include <stdio.h>
int ungetc(int ch, FILE *stream);
参数
-
ch
:要推回到文件流中的字符。它被解释为一个unsigned char
,然后被转换为int
类型。 -
stream
:指向FILE
结构的指针,表示要将字符推回的文件流。
返回值
-
成功时,返回推回的字符。
-
注意事项
-
ungetc
只能推回一个字符到文件流中。 -
如果文件流已经到达文件末尾,
ungetc
可以将文件流状态从文件末尾状态恢复。 -
推回的字符将在下次读取时首先被读取。
-
ungetc
可以连续调用多次,但具体能推回多少字符取决于实现。
putc
用于将一个字符写入到指定的文件流中。
#include <stdio.h>
int putc(int ch, FILE *stream);
参数
-
ch
:要写入的字符。它被解释为一个unsigned char
,然后被转换为int
类型。 -
stream
:指向FILE
结构的指针,表示要写入字符的文件流。
返回值
-
成功时,返回写入的字符。
-
失败时,返回
EOF
。
fputc
fputc
函数与 putc
类似,也是用于将一个字符写入到指定的文件流中。它们的功能几乎相同,但 fputc
通常是作为函数调用,而 putc
可能被实现为宏。
#include <stdio.h>
int fputc(int ch, FILE *stream);
参数
-
ch
:要写入的字符。它被解释为一个unsigned char
,然后被转换为int
类型。 -
stream
:指向FILE
结构的指针,表示要写入字符的文件流。
返回值
-
成功时,返回写入的字符。
-
失败时,返回
EOF
。
putchar
用于将一个字符写入到标准输出(通常是屏幕)。它实际上是 putc(ch, stdout)
的简写。
#include <stdio.h>
int putchar(int ch);
参数
5.7 每次一行的I/O
fgets
用于从指定的文件流中读取一行字符串,直到读取到换行符、到达文件末尾或读取了指定数量的字符为止。
#include <stdio.h>
char *fgets(char *str, int n, FILE *stream);
参数
-
str
:指向存储读取字符串的字符数组。 -
n
:要读取的最大字符数,包括终止的空字符('\0'
)。 -
stream
:指向FILE
结构的指针,表示要读取的文件流。
返回值
-
成功时,返回指向
str
的指针。 -
失败或到达文件末尾时,返回
NULL
。
gets
用于从标准输入读取一行字符串,直到读取到换行符或到达文件末尾为止。读取的字符串会自动添加终止的空字符('\0'
)。
#include <stdio.h>
char *gets(char *str);
参数
5.9 二进制I/O
fread
用于从文件流中读取数据块。
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参数
-
ptr
:指向存储读取数据的内存块的指针。 -
size
:每个数据块的大小(以字节为单位)。 -
nmemb
:要读取的数据块的数量。 -
stream
:指向FILE
结构的指针,表示要读取的文件流。
返回值
-
成功时,返回读取的完整数据块的数量。
-
失败或到达文件末尾时,返回值可能小于
nmemb
。
fwrite
fwrite
函数用于向文件流中写入数据块。
#include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
参数
-
ptr
:指向要写入数据的内存块的指针。 -
size
:每个数据块的大小(以字节为单位)。 -
nmemb
:要写入的数据块的数量。 -
stream
:指向FILE
结构的指针,表示要写入的文件流。
返回值
-
成功时,返回写入的完整数据块的数量。
-
失败时,返回值可能小于
nmemb
。
#include <stdio.h>
#include <string.h>
int main() {
FILE *fp = fopen("test.txt", "rb");
if (fp == NULL) {
perror("Failed to open file");
return 1;
}
FILE *fp2 = fopen("test1.txt", "wb");
if (fp2 == NULL) {
perror("Failed to open file");
return 1;
}
int buffer[5];
size_t bytesRead = fread(buffer, sizeof(int), 5, fp);
size_t bytesWritten = fwrite(buffer, sizeof(int), sizeof(buffer)/sizeof(int), fp2);
fclose(fp);
fclose(fp2);
return 0;
}
5.10 定位流
ftell
ftell
函数用于获取文件指针的当前位置。它的原型如下:
#include <stdio.h>
long ftell(FILE *stream);
参数
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
参数
-
stream
:文件指针。 -
offset
:相对于whence
的偏移量。 -
whence
:指定从哪里开始偏移。它可以是以下三个值之一: -
如果成功,返回0;如果失败,返回非零值。
rewind
rewind
函数用于将文件指针移动到文件的开头。它的原型如下:
#include <stdio.h>
void rewind(FILE *stream);
参数
stream
:文件指针。
#include <stdio.h>
int main() {
FILE *fp = fopen("test.txt", "r");
if (fp == NULL) {
perror("Failed to open file");
return 1;
}
// 移动文件指针到文件的末尾
if (fseek(fp, 0, SEEK_END) != 0) {
perror("Failed to seek to end of file");
fclose(fp);
return 1;
}
// 获取文件的大小
long fileSize = ftell(fp);
if (fileSize == -1L) {
perror("Failed to tell position in file");
fclose(fp);
return 1;
}
printf("File size: %ld bytes", fileSize);
// 将文件指针移动到文件的开头
rewind(fp);
// 读取文件的前10个字节
char buffer[11];
size_t bytesRead = fread(buffer, 1, 10, fp);
if (bytesRead < 10 && ferror(fp)) {
perror("Failed to read from file");
fclose(fp);
return 1;
}
buffer[bytesRead] = '\0'; // 添加字符串终止符
printf("First 10 bytes: %s\n", buffer);
fclose(fp);
return 0;
}
ftello
和 fseeko
是用于文件流定位的函数,它们是 ftell
和 fseek
的大文件版本,支持大于2GB的文件操作。这些函数使用 off_t
类型来表示文件偏移量,而不是 long
类型,从而支持更大的文件。
ftello
ftello
函数用于获取文件指针的当前位置。它的原型如下:
#include <stdio.h>
off_t ftello(FILE *stream);
参数
#include <stdio.h>
int fseeko(FILE *stream, off_t offset, int whence);
参数
-
stream
:文件指针。 -
offset
:相对于whence
的偏移量。 -
whence
:指定从哪里开始偏移。它可以是以下三个值之一: -
如果成功,返回 0;如果失败,返回非零值。
fgetpos
和 fsetpos
是用于文件流定位的标准库函数。它们提供了一种独立于平台的方式来保存和恢复文件指针的位置。与 ftell
和 fseek
不同,fgetpos
和 fsetpos
使用 fpos_t
类型来表示文件位置,这在某些平台上可能比 long
类型更精确。
fgetpos
fgetpos
函数用于获取文件指针的当前位置,并将其存储在一个 fpos_t
类型的变量中。它的原型如下:
#include <stdio.h>
int fgetpos(FILE *stream, fpos_t *pos);
参数
-
stream
:文件指针。 -
pos
:指向fpos_t
类型变量的指针,用于存储文件指针的位置。
返回值
-
fsetpos
fsetpos
函数用于将文件指针移动到由fgetpos
保存的位置。它的原型如下:#include <stdio.h> int fsetpos(FILE *stream, const fpos_t *pos);
参数
-
stream
:文件指针。 -
pos
:指向fpos_t
类型变量的指针,表示要移动到的位置。
返回值
-
如果成功,返回 0;如果失败,返回非零值。
5.11 格式化I/O
printf
printf
函数用于将格式化的输出写入标准输出(通常是屏幕)。它的原型如下:
#include <stdio.h>
int printf(const char *format, ...);
参数
fprintf
fprintf
函数用于将格式化的输出写入指定的文件流。它的原型如下:
#include <stdio.h>
int fprintf(FILE *stream, const char *format, ...);
参数
#include <stdio.h>
int
main()
{
FILE *fp;
int rt;
if ((fp = fopen("test.txt", "w")) == NULL)
printf("fopen test.txt error!\n");
if ((rt = fprintf(fp, "aaabbbb")) < 0)
printf("fprintf error!\n");
return 0;
}
dprintf
dprintf
函数用于将格式化的输出写入指定的文件描述符。它的原型如下:
#include <stdio.h>
int dprintf(int fd, const char *format, ...);
参数
dprintf.c: In function ‘main’:
dprintf.c:17:9: warning: implicit declaration of function ‘close’; did you mean ‘pclose’? [-Wimplicit-function-declaration]
17 | close(fd);
| ^~~~~
| pclose
//添加 unistd
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int
main()
{
int fd, num, rt;
if ((fd = open("test.txt", 2)) == -1)
printf("open test.txt error!\n");
num = 10;
if ((rt = dprintf(fd, "The number is %d", num)) < 0)
printf("dprintf error!");
close(fd);
return 0;
}
sprintf
sprintf
函数用于将格式化的输出写入字符串。它的原型如下:
#include <stdio.h>
int sprintf(char *str, const char *format, ...);
参数
#include <stdio.h>
int
main()
{
char buff[100] = "Hello world!";
char my[] = "My app";
sprintf(buff, "This is %s\n", my);
printf("%s", buff);
return 0;
}
snprintf
snprintf
函数用于将格式化的输出写入字符串,并指定最大字符数。它的原型如下:
#include <stdio.h>
int snprintf(char *str, size_t size, const char *format, ...);
参数
str
:目标字符串,存储格式化的输出。size
:目标字符串的最大长度。format
:格式字符串,包含普通字符和格式说明符。...
:可变参数列表,包含要格式化的值。
返回值
成功时返回输出的字符数(不包括终止符),如果输出被截断,则返回欲写入的字符数。
**printf**
:将格式化的输出写入标准输出。**fprintf**
:将格式化的输出写入指定的文件流。**dprintf**
:将格式化的输出写入指定的文件描述符。**sprintf**
:将格式化的输出写入字符串。**snprintf**
:将格式化的输出写入字符串,并指定最大字符数,防止缓冲区溢出。
格式化参数
例: printf("%d", i);
#include <stdio.h>
int
main()
{
FILE *fp;
int rt;
if ((fp = fopen("test.txt", "w")) == NULL)
printf("fopen test.txt error!\n");
if ((rt = fprintf(fp, "%d\n" , "a")) < 0)
printf("fprintf error!\n");
return 0;
}
#似乎是寻找了一个变量而非转换ascii码
fyh@VM-16-14-ubuntu:~/notec$ cat test.txt
-803508187
- [flags]
#include <stdio.h>
int
main()
{
int num=1000000;
printf("': %'d\n", num);
printf("-: %-d\n", num);
printf("+: %+d\n", num);
printf("\" \": % d\n", num);
printf("#: %#0x\n", num);
printf("0: %0d\n", num);
return 0;
}
fyh@VM-16-14-ubuntu:~/notec$ ./printf
': 1000000
-: 1000000
+: +1000000
" ": 1000000
#: 0xf4240
0: 1000000
- ' :将整数按千位分组字符
-
- :在字段内左对齐输出
-
- :总是显示带符号转换的正负号
- (空格) :如果第一个字符不是正负号,则在其前面加上一个空格
- #:指定另一种转换形式(例如 ,对于十六进制格式,加前缀0x)
- 0 :添加前导0进行填充
- [fldwidth]
#include <stdio.h>
int
main()
{
int num=10;
printf("d: %d\n", num);
printf("i: %i\n", num);
printf("o: %o\n", num);
printf("u: %u\n", num);
printf("x: %x\n", num);
return 0;
}
fyh@VM-16-14-ubuntu:~/notec$ ./printf
d: 10
i: 10
o: 12
u: 10
x: a
- d、i:有符号十进制
- o:无符号八进制
- u:无符号十进制
- x、X:无符号十六进制
- f、F:双精度浮点数
- e、E:指数格式双精度浮点数
- g、G:根据转换后的值解释为f、F、e、E
- a、A:十六进制指数格式双精度浮点数
- c:字符(若带有长度修饰符1,为宽字符)
- s:字符串(若带有长度修饰符1,为宽字符)
- p:指向void的指针
- [precision]
- [lenmodifier]
#include <stdio.h>
int
main()
{
short int sc = 10;
printf("hhd: %hhd\n", sc);
return 0;
}
fyh@VM-16-14-ubuntu:~/notec$ ./printf
hhd: 10
- hh:将相对应的参数按signed或unsigned char 类型输出
- h:将相应的参数按signed或unsigned short类型输出
- l:将相应的参数按signed或unsigned long或宽字符类型输出
- ll:将相应的参数按signed或unsigned long long类型输出
- j:intmax_t 或 uintmax_t
- z:size_t
- t:prtdiff_t
- L:long double
变形体
vprintf
, vfprintf
, vdprintf
, vsprintf
, vsnprintf
是C语言中的一组函数,它们用于格式化输出,与 printf
, fprintf
, dprintf
, sprintf
, snprintf
类似,但它们接受一个 va_list
类型的参数,而不是可变参数。这使得它们可以在其他接受可变参数的函数中使用。
#include <stdarg.h>
#include <stdio.h>
int vprintf(const char *format, va_list ap);
int vfprintf(FILE *stream, const char *format, va_list ap);
int vdprintf(int fd, const char *format, va_list ap);
int vsprintf(char *str, const char *format, va_list ap);
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
#include <stdio.h>
#include <stdarg.h>
void
myprintf(int count, ...)
{
va_list mys;
va_start(mys, count);
for (int i = 0; i < count; i++)
{
vprintf("%d\n", mys);
}
va_end(mys);
}
int
main()
{
myprintf(4, 1, 2, 3, 4);
return 0;
}
fyh@VM-16-14-ubuntu:~/notec$ ./vprintf
1
2
3
4
va_list
是 C 语言标准库中的一个类型,用于处理可变参数函数。可变参数函数是指参数数量不固定的函数,例如 printf
。为了处理这些可变参数,C 语言提供了一组宏和类型,包括 va_list
、va_start
、va_arg
和 va_end
。
#include <stdio.h>
#include <stdarg.h>
// 可变参数函数,计算所有参数的和
int sum(int count, ...) {
va_list args;
int total = 0;
// 初始化 va_list 变量
va_start(args, count);
// 访问每个参数
for (int i = 0; i < count; i++) {
total += va_arg(args, int);
}
// 清理 va_list 变量
va_end(args);
return total;
}
int main() {
//4 对应count
int result = sum(4, 1, 2, 3, 4); // 计算 1 + 2 + 3 + 4
printf("The sum is %d\n", result); // 输出结果
return 0;
}
fyh@VM-16-14-ubuntu:~/notec$ ./va_list
The sum is 10
scanf
scanf
从标准输入(通常是键盘)读取格式化数据。
#include
int scanf(const char *format, ...);
返回值
赋值的输入项数,若输入出错或在任一转换前以达到文件尾端,返回EOF
#include <stdio.h>
int
main()
{
int num;
char cr[30];
//%[^\n] 读到换行符就停下
scanf("%d %[^\n]", &num, cr);
printf("输入内容:%d %s\n", num, cr);
return 0;
}
fscanf
fscanf
从文件流中读取格式化数据。
#include <stdio.h>
int fscanf(FILE *stream, const char *format, ...);
返回值
赋值的输入项数,若输入出错或在任一转换前以达到文件尾端,返回EOF
#include <stdio.h>
int
main()
{
FILE *file;
char cr[50];
file = fopen("test.txt", "r");
fscanf(file, "%[^\n]", cr);
printf("%s", cr);
return 0;
}
sscanf
sscanf
从字符串中读取格式化数据。
#include <stdio.h>
int sscanf(const char *str, const char *format, ...);
#include <stdio.h>
int
main()
{
const char * input = "25 5.9 JohnDoe";
int age;
float height;
char name[50];
sscanf(input, "%d %f %[^/n]", &age, &height, name);
printf("Age: %d\nHeight: %.2f\nName: %s\n", age, height, name);
return 0;
}
fyh@VM-16-14-ubuntu:~/notec$ ./sscanf
Age: 25
Height: 5.90
Name: Joh
5.12 实现细节
fileno
fileno
是一个 C 标准库函数,用于获取与文件流(FILE *
)关联的文件描述符。文件描述符是一个整数,表示打开的文件、管道或网络套接字等资源。文件描述符在底层操作系统级别使用,而文件流在 C 标准库级别使用。
#include <stdio.h>
int fileno(FILE *stream);
参数
#include <stdio.h>
#include <unistd.h>
int
main()
{
FILE *file = fopen("test.txt", "w");
int fd = fileno(file);
char *text = "Hello World!\n";
write(fd, text, 14);
fclose(file);
return 0;
}
5.13 临时文件
tmpnam
tmpnam
函数生成一个唯一的临时文件名。
#include <stdio.h>
char *tmpnam(char *s);
参数
#include <stdio.h>
int main()
{
char buffer[L_tmpnam];
char *ptr;
tmpnam(buffer);
printf("临时名称 1: %s\n", buffer);
ptr = tmpnam(NULL);
printf("临时名称 2: %s\n", ptr);
return(0);
}
#include <stdio.h>
int main() {
char buffer[100] = {0};
FILE *stream = fmemopen(buffer, sizeof(buffer), "w+");
if (stream == NULL) {
perror("Failed to open memory stream");
return 1;
}
// 写入数据
const char *text = "Hello, World!";
if (fwrite(text, 1, 13, stream) != 13) {
perror("Failed to write to memory stream");
fclose(stream);
return 1;
}
// 重置文件位置指示器
rewind(stream);
// 读取数据
char read_buffer[100] = {0};
if (fread(read_buffer, 1, 13, stream) != 13) {
perror("Failed to read from memory stream");
fclose(stream);
return 1;
}
printf("Read from memory stream: %s
", read_buffer);
fclose(stream);
return 0;
}