scanf_s的返回值
int main(void)
{
int number;
int result;
puts("Enter an integer:");
result = scanf_s("%d", &number);
if (result == 1){
printf("You entered thr integer: %d", number);
}
else if (result == EOF){
// End of file -1
//专门用来指示文件读取或输入操作已经到达了数据源的末尾
printf("An error occurred or end of file was reached.\n");
return 1; //直接退出函数
}
else{
printf("Invalid input for integer.\n");
return 1;
}
return 0;
}
result == 1说明读取得到的是数字,如果输入的是字符,会跳到最后一个else
流(Stream)
FILE* stream这种定义方式,包含了各种各样的流·
1.文件流
磁盘
用于读取与写入在磁盘上的文件
2.标准I/O流
stdin: 默认连接到键盘,用于程序输入 -> scanf_s
stdout: 默认连接到控制台或者是屏幕,用于程序输出 -> printf
stderr: 默认也连接到控制台或者屏幕, 专门输出错误信息和警告, 使得其能够被区分开来或者是重定向到不同的目的地
3.管道流
用于进程之间的通信(IPC), 允许一个进程的输出成为另一个进程的输入。plpen();
4.内存流
允许你将流与内存缓冲区相关联,使得你可以向内存中读写数据,就像操作文件一样。POSIX -> fmemopen
5.网络流
套接字(Sockets)
6.设备流
特殊文件或者是设备打印机
小实例
#include
#include
#include
#include
int main(void)
{
FILE* fileStream = NULL;
char buffer[1023] = { 0 };
//fopen()
//fopen_s()
//打开文件,设定文件路径要读取的文件,设定文件的操作模式
errno_t err = fopen_s(&fileStream, "C:\\Users\\yangy\\Desktop\\Hello!.txt", "r");
//这里对返回值进行处理,!= 0说明读取失败或者是读取的流是一个NULL
if (err != 0 || fileStream == NULL) {
//这是专门用来错误处理的函数,正确地反馈错误
perror("Error opening file");
return EXIT_FAILURE;
}
//需要对fopen进行处理,可能会出现文件路径不对,文件不存在,文件出现了异常,文件没有权限访问
//令fgets != NULL即可一直读取下去
while (fgets(buffer, sizeof(buffer), fileStream) != NULL) {
printf("%s", buffer);
}
//之前用的字符串buffer此时里面是有东西的,之后我们不再使用了,就得确保他是空的,不然是一件非常不文明的事情
memset(buffer, 0, sizeof(buffer));
//如果需要读取两次的话,第一次读的文件末尾是没有换行符的,需要手动加
printf("\n");
//这个函数不管多长都能直接定位到文件开头
rewind(fileStream);
//也可以一个字符的读,一个字一个字往出蹦,不需要缓冲区但是比较慢
int ch = 0;
while ((ch = fgetc(fileStream)) != EOF) {
putchar(ch);
}
//最后一定要关闭文件流,关闭也可能出现问题,需要对fclose进行处理
if (fclose(fileStream) != 0) {
perror("Error closing file");
return EXIT_FAILURE;
}
return 0;
}
rewind和fseek的区别与联系
特性 | rewind() | fseek() |
---|---|---|
返回值 | 无 | 返回成功/失败状态 |
错误标志处理 | 会清除流的错误标志 | 不会修改错误标志 |
参数复杂度 | 无参数,直接回到开头 | 需要指定偏移量和起始点 |
如果只需要简单回到文件开头,推荐使用 rewind()
如果需要更精确的控制或错误检查,使用 fseek(fp, 0L, SEEK_SET)
使用后建议检查文件状态:
fseek的更多解释
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) {
perror("文件打开失败");
exit(EXIT_FAILURE);
}
// 将指针移动到文件开头(等价于 rewind(fp))
fseek(fp, 0L, SEEK_SET);
// 跳过前 100 字节(从开头向后移动)
fseek(fp, 100L, SEEK_SET);
// 读取后续内容
char buffer[1024];
fread(buffer, sizeof(char), 1024, fp);
// 假设当前指针在位置 200
// 向后移动 50 字节(正偏移)
fseek(fp, 50L, SEEK_CUR); // 新位置 = 250
// 向前移动 30 字节(负偏移)
fseek(fp, -30L, SEEK_CUR); // 新位置 = 220
// 移动到文件末尾
fseek(fp, 0L, SEEK_END); // 用于追加数据或计算文件大小
// 在末尾追加数据
fputs("追加的内容", fp);
// 读取文件的最后 10 字节
fseek(fp, -10L, SEEK_END); // 从末尾向前移动 10 字节
char last10[11];
fread(last10, sizeof(char), 10, fp);
last10[10] = '\0'; // 添加字符串结束符
printf("最后10字节: %s\n", last10);
// 修改文件中第 50 字节处的内容(二进制文件)
FILE *fp = fopen("data.bin", "r+"); // 读写模式
if (fp == NULL) exit(EXIT_FAILURE);
fseek(fp, 49L, SEEK_SET); // 移动到第 50 字节(索引从 0 开始)
fputc('X', fp); // 修改该字节
fclose(fp);
FILE *fp = fopen("data.bin", "rb");
if (fp == NULL) exit(EXIT_FAILURE);
fseek(fp, 0L, SEEK_END); // 移动到文件末尾
long file_size = ftell(fp); // 获取文件大小(字节数)
rewind(fp); // 回到开头
printf("文件大小: %ld 字节\n", file_size);
// 假设文件指针初始位置为 100
fseek(fp, 100L, SEEK_SET);
// 从当前位置向前移动 50 字节
fseek(fp, 50L, SEEK_CUR); // 新位置 = 150
// 从文件末尾向前移动 200 字节
fseek(fp, -200L, SEEK_END); // 适用于大文件末尾操作
// 假设文件指针初始位置为 100
fseek(fp, 100L, SEEK_SET);
// 从当前位置向前移动 50 字节
fseek(fp, 50L, SEEK_CUR); // 新位置 = 150
// 从文件末尾向前移动 200 字节
fseek(fp, -200L, SEEK_END); // 适用于大文件末尾操作
二进制文件 vs 文本文件
在文本文件中,某些系统(如 Windows)的换行符 \r\n
可能被转换为 \n
,导致 fseek
偏移量与实际字节数不一致。建议对文本文件谨慎使用偏移量。
有效性检查
使用 ftell()
可获取当前位置:
long pos = ftell(fp);
if (pos == -1L) {
perror("ftell 失败");
}
重置文件状态
fseek
可以清除文件结束标志(feof()
返回 false
),但不会自动清除错误标志(需用 clearerr(fp)
)。
fopen_s的不同区别
模式 | 描述 | 文件存在 | 文件不存在 | 文件指针位置 | 操作权限 |
---|---|---|---|---|---|
r |
只读 | 打开文件 | 报错 | 开头 | 只能读 |
w |
只写 | 清空 | 创建文件 | 开头 | 只能写 |
a |
追加 | 打开文件 | 创建文件 | 末尾 | 只能写 |
模式 | 描述 | 文件存在 | 文件不存在 | 文件指针位置 | 操作权限 |
---|---|---|---|---|---|
r+ |
读写(更新模式) | 打开文件 | 报错 | 开头 | 可读可写 |
w+ |
读写(清空并创建) | 清空 | 创建文件 | 开头 | 可读可写 |
a+ |
读写(追加模式) | 打开文件 | 创建文件 | 末尾 | 可读可写 |
注:
a+
模式下,写入总是追加到末尾,但读取可以定位到任意位置(需先调用fseek
调整指针)
r+
和w+
的主要区别:r+
不删除原内容,w+
会清空原内容
在模式后添加 b
(如 rb
, wb+
),用于处理二进制文件:
FILE *fp = fopen("data.bin", "rb"); // 二进制只读
文本模式 vs 二进制模式:
文本模式:自动处理换行符(如 Windows 将 \r\n
转为 \n
)
二进制模式:直接操作原始字节(无转换)
写入函数
fputc('O', fileStream);
fputs("dashdasdjha", fileStream);
fprintf_s(fileStream, "asdhasdi%d %d %d sdhaskdh%d", 19, 29, 39, 1);
这里因为是写入,一定要与之前的fopen_s函数中的模式相匹配
long ftell(FILE *stream);
作用:返回当前文件指针的位置(相对于文件开头的偏移量,单位:字节)
返回值:
成功:返回 long
类型的当前位置
失败:返回 -1L
(需检查错误)
FILE *fp = fopen("data.bin", "rb");
if (fp == NULL) exit(EXIT_FAILURE);
fseek(fp, 0L, SEEK_END); // 移动到文件末尾
long file_size = ftell(fp); // 获取总字节数
printf("文件大小: %ld 字节\n", file_size);
rewind(fp); // 重置指针到文件开头
fclose(fp);
long original_pos = ftell(fp); // 保存当前位置
// 执行某些操作后...
fseek(fp, original_pos, SEEK_SET); // 返回原位置
if (fseek(fp, 100L, SEEK_SET) == 0) {
printf("当前指针位置: %ld\n", ftell(fp)); // 应输出 100
} else {
perror("指针移动失败");
}
二进制文件 vs 文本文件
二进制模式:ftell()
返回的偏移量精确对应物理字节位置
文本模式:
Windows 系统中换行符 \r\n
会被转换为 \n
,导致逻辑位置与物理位置不一致,这里\r算一个\n也算一个(算一个字节)
建议文本文件操作时谨慎使用 ftell()
的返回值
文件有效性检查
long pos = ftell(fp);
if (pos == -1L) {
perror("ftell 失败");
// 常见错误原因:
// - 文件未成功打开
// - stream 参数无效
// - 文件是终端设备(如 stdin/stdout)
}
fscanf_s
与scanf的返回值一样,需要判断是否为1
char bufferplus[256] = { 0 };
int number = 0;
float FloatNumber = 0.0;
char character = 0;
//scanf_s的问题
if (fscanf_s(fileStream, "%d", &number) != 1) {
printf("读取失败");
}
if (fscanf_s(fileStream, "%s", &bufferplus, (unsigned)sizeof(bufferplus)) != 1) {
printf("读取失败");
}
if (fscanf_s(fileStream, "%f", &FloatNumber) != 1) {
printf("读取失败");
}
if (fscanf_s(fileStream, " %c", &character, 1)
!= 1) {
printf("读取失败");
}
printf("%d\n", number);
printf("%f\n", FloatNumber);
printf("%c\n", character);
printf("%s\n", bufferplus);
scanf
在不同的格式化控制符下对空格的处理方式不同
想读取的东西得按顺序来
%s
读取字符串时当使用 %s
格式化控制符时,scanf
不会读取空格、制表符(\t
)和换行符(\n
),它会将这些字符视为字符串的分隔符。一旦遇到这些空白字符,scanf
就会停止读取,并在字符串末尾自动添加字符串结束符 '\0'
。
示例代码:
#include
int main() {
char str[100];
printf("请输入一个包含空格的字符串:");
scanf("%s", str);
printf("你输入的字符串是:%s\n", str);
return 0;
}
输入与输出示例:
请输入一个包含空格的字符串:hello world
你输入的字符串是:hello
在这个例子中,当输入 hello world
时,scanf
遇到空格就停止读取,只将 hello
存储到 str
数组中。
%c
读取字符时当使用 %c
格式化控制符时,scanf
会读取包括空格、制表符和换行符在内的任意字符。也就是说,空格对于 %c
来说就是一个普通的字符。
示例代码:
#include
int main() {
char ch;
printf("请输入一个字符(可以是空格):");
scanf("%c", &ch);
printf("你输入的字符是:%c\n", ch);
return 0;
}
输入与输出示例:
请输入一个字符(可以是空格):
你输入的字符是:
这里输入一个空格,scanf
会将这个空格字符读取并存储到 ch
变量中。
%d
、%f
等)读取数值时对于读取整数(%d
)、浮点数(%f
)等数值类型的格式控制符,scanf
会自动跳过前导的空白字符(空格、制表符、换行符),直到遇到有效的数字字符才开始读取。
示例代码:
#include
int main() {
int num;
printf("请输入一个整数(可以在前面加空格):");
scanf("%d", &num);
printf("你输入的整数是:%d\n", num);
return 0;
}
输入与输出示例:
请输入一个整数(可以在前面加空格): 123
你输入的整数是:123
fprintf
格式化往文件里打印
fprintf(file, "整数: %d\n", num);
fprintf(file, "浮点数: %.2f\n", f);
fprintf(file, "字符串: %s\n", str);
ferror feof clearerr
while (fgets(buffer, sizeof(buffer), file_ptr)!= NULL) {
printf("%s", buffer);
}
if (ferror(file_ptr)) {
perror("读取文件时候发生了错误!");
clearerr(file_ptr);
}
if (feof(file_ptr)) {
printf("已经到达文件的末尾...\n");
} else {
printf("文件未到达末尾,可能因为发生了错误!\n");
}
ferror读取文件过程中检查是否发生错误
feof检查文件流是否达到的末尾
claererr清除错误
更专业一点的错误处理
抽离文件读取函数
void read_config_safe(const char* filename);
int main(void)
{
const char* filename = "C:\\Users\\yangy\\Desktop\\Hello!.txt";
read_config_safe(filename);
return 0;
}
void read_config_safe(const char* filename) {
FILE* fileStream = NULL;
errno_t err = fopen_s(&fileStream, filename, "r+");
//比较标准的错误处理
if (err != 0 || fileStream == NULL) {
char errorMsg[256] = { 0 };
//这里把错误信息装到了这个数组里
strerror_s(errorMsg, sizeof(errorMsg), errno);
//这里的fprintf不再是将错误信息打印到文本里了,这里用stderr是将错误信息放到了cmd或者是用户的显示屏上,也有可能是一个设备专门去报错,这样写比较灵活
fprintf(stderr, "Failed to open config file for reading : %s\n", errorMsg);
exit(EXIT_FAILURE);
}
}
写入文件用fprintf
确保关闭所有的流,这一步是为了保险
//All other files are closed
unsigned int numclosed = _fcloseall();
printf("Number if files closed by _flcloseall: %u", numclosed);
使用r+来修改日志,待修缮
#include
#include
#include
#include
#define BUFFER_SIZE 1024
errno_t update_log_replace_s(const char* logFile, const char* rearchStr, const char* replaceStr);
int main(void)
{
const char* logFile = "C:\\Users\\yangy\\Desktop\\log.txt";
const char* rearchStr = "Memory usage exceeds 80% of available memory.";
const char* replaceStr = "[2023-02-13T12:36:00Z] [INFO] Memory usage is back to normal levels.";
//更新需要返回值来告诉是否更新成功
errno_t result = update_log_replace_s(logFile, rearchStr, replaceStr);
if (result != 0) {
char config_msg[256] = { 0 };
strerror_s(config_msg, sizeof(config_msg), errno);
fprintf(stderr, "An error occured: %s", config_msg);
exit(EXIT_FAILURE);
}
else {
printf("Record updated successfully");
}
_fcloseall();
return 0;
}
//修改log日志中的一条警告
errno_t update_log_replace_s(const char* logFile, const char* rearchStr, const char* replaceStr) {
//因为涉及到更新,要确保传进来的东西都不是空
if (logFile == NULL || rearchStr == NULL || replaceStr == NULL) {
return EINVAL; //返回无效参数
}
FILE* fileStream = NULL;
errno_t err = fopen_s(&fileStream, logFile, "r+");
if (err != 0 || fileStream == NULL) {
char config_msg[256] = { 0 };
strerror_s(config_msg, sizeof(config_msg), errno);
fprintf(stderr, "Error to open config file to r+: %s", config_msg);
exit(EXIT_FAILURE);
}
char buffer[BUFFER_SIZE] = { 0 };
long position = 0;
int found = 0;
while (fgets(buffer, sizeof(buffer), fileStream)) {
//strstr去寻找是否有想要的字符串
if (strstr(buffer, rearchStr) != NULL) {
found = 1; //标志着已经找到
//这里得知要找的字符的具体位置
//这个时候fileStream在我们要找的句子的末尾
//这里加减1取决于是否是二进制
position = ftell(fileStream) - (long)strlen(buffer);
break; //找到第一个匹配项之后立刻退出
}
}
if (found) {
//将文件流从目标句段的末尾定位到开头
fseek(fileStream, position, SEEK_SET);
//为了确保安全计算替换文本和目标文本的长度差异
size_t replace_len = strlen(replaceStr);
size_t research_len = strlen(rearchStr);
if (replace_len > BUFFER_SIZE || research_len > BUFFER_SIZE) {
fclose(fileStream);
return ERANGE; //返回错误码,表示字符串长度超出范围
}
//写入新纪录之前,删除原有行的数据,用空格去填充,防止删完了下一行加上来了
memset(buffer, ' ', strlen(buffer) - 1); //用空格填充保持文件大小不变,-1是防止换掉\n换行符
buffer[strlen(buffer) - 1] = '\n'; //保留换行符
fseek(fileStream, position, SEEK_SET);
int result = fputs(replaceStr, fileStream); //彻底清除原行的内容
//确保清除成功
if (result == EOF) {
fclose(fileStream);
return errno;
}
fseek(fileStream, position, SEEK_SET); //再次回到文件的开头
}
else {
fclose(fileStream);
return ENOENT; //返回未找到的匹配项
}
fclose(fileStream);
return 0;
}
fgets
函数简介fgets
函数的原型如下:
char *fgets(char *str, int num, FILE *stream);
该函数从指定的文件流 stream
中读取最多 num - 1
个字符,并将其存储到字符数组 str
中,直到遇到换行符 \n
或者文件结束符 EOF
为止。读取完成后,会在字符串末尾自动添加字符串结束符 '\0'
。
"Hello, World!\n"
,当使用 fgets
读取这一行时,如果 num
足够大,fgets
会读取 "Hello, World!\n"
并存储到 str
中,然后文件流指针会移动到下一行的起始位置(如果存在下一行)。例如:#include
int main() {
FILE *file = fopen("test.txt", "r");
if (file == NULL) {
perror("文件打开失败");
return 1;
}
char buffer[100];
fgets(buffer, sizeof(buffer), file); // 读取一行内容
// 此时文件流指针位于下一行的起始位置
fclose(file);
return 0;
}
"Hello\nWorld"
,当使用 fgets
读取时,它会读取 "Hello\n"
并存储到 str
中,文件流指针会移动到 'W'
这个字符的位置,即下一行的起始字符处。num
较小,不足以读取完整的一行内容,fgets
会读取 num - 1
个字符并存储到 str
中,文件流指针会停留在本次读取的最后一个字符的下一个位置。例如,文件内容为 "Hello, World!\n"
,而 num
为 5,那么 fgets
会读取 "Hell"
并存储到 str
中,文件流指针会停留在 'o'
这个字符的位置。保存游戏设置简单代码(部分变量命名有误)
#include
#include
#include
typedef enum{
ESAY,
MIDDLE,
HARD
}Difficulty;
typedef struct {
float volumn;
int resolution_x;
int resolution_y;
Difficulty Difficulty;
}Settings;
//读取设置
void load_game_settings(const Settings* settings, const char* filename);
//保存设置
void save_game_settings(const Settings* settings, const char* filename);
int main(void)
{
//fread
//fwrite
//二进制下的读与写
Settings settings = { 0.75, 1920, 1080, MIDDLE };
save_game_settings(&settings, "C:\\Users\\yangy\\Desktop\\log.txt");
Settings load_setting = { 0 };
load_game_settings(&load_setting, "C:\\Users\\yangy\\Desktop\\log.txt");
printf("volunm : %f\nresolution_x : %d\nresolution_y : %d\ndifficulty : %d", load_setting.volumn, load_setting.resolution_x, load_setting.resolution_y, load_setting.Difficulty);
return 0;
}
void save_game_settings(const Settings* settings, const char* filename) {
FILE* file_stream = NULL;
errno_t err = fopen_s(&file_stream, filename, "wb");
if (err != 0 || file_stream == NULL) {
char config_msg[256] = { 0 };
strerror_s(config_msg, sizeof(config_msg), errno);
fprintf(stderr, "Error to open the file: %s", config_msg);
exit(EXIT_FAILURE);
}
//总共有四个参数,分别是指向缓冲区的指针,所读取数据的大小,每次读取的数目
fwrite(settings, sizeof(Settings), 1, file_stream);
fclose(file_stream);
}
void load_game_settings(const Settings* settings, const char* filename) {
FILE* file_stream = NULL;
errno_t err = fopen_s(&file_stream, filename, "rb");
if (err != 0 || file_stream == NULL) {
char config_msg[256] = { 0 };
strerror_s(config_msg, sizeof(config_msg), errno);
fprintf(stderr, "Error to open the file: %s", config_msg);
exit(EXIT_FAILURE);
}
//总共有四个参数,分别是指向缓冲区的指针,所读取数据的大小,每次读取的数目
fread(settings, sizeof(Settings), 1, file_stream);
fclose(file_stream);
}
复制文件
#include
#include
#include
int main(void)
{
FILE* source_file = NULL;
FILE* target_file = NULL;
char source_path[] = "C:\\Users\\yangy\\Desktop\\abc.log";
char target_path[] = "C:\\Users\\yangy\\Desktop\\log.txt";
errno_t sourerr = fopen_s(&source_file, source_path, "rb");
if (sourerr != 0 || source_file == NULL) {
perror("Error to open source file");
return EXIT_FAILURE;
}
errno_t tarerror = fopen_s(&target_file, target_path, "wb");
if (tarerror != 0 || target_file == NULL) {
perror("Error to open target file");
return EXIT_FAILURE;
}
size_t byte_read = 0;
char buffer[256] = { 0 };
while ((byte_read = fread(buffer, 1, sizeof(buffer), source_file)) > 0) {
fwrite(buffer, 1, byte_read, target_file);
}
_fcloseall();
printf("succussfully");
return 0;
}
#include
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
ptr
:指向用于存储读取数据的内存块的指针。该内存块的大小至少应该为 size * nmemb
字节,以确保能够容纳读取的数据。size
:每个数据项的大小(以字节为单位)。例如,如果要读取整数,size
可以设置为 sizeof(int)
。nmemb
:要读取的数据项的数量。函数将尝试读取 nmemb
个大小为 size
字节的数据项。stream
:指向 FILE
对象的指针,表示要从中读取数据的文件流。这个文件流通常是通过 fopen
函数打开的。fread
函数返回实际成功读取的数据项的数量(而不是字节数)。如果发生错误或到达文件末尾,返回值可能小于 nmemb
。具体情况如下:
nmemb
,也可能小于 nmemb
(例如,当接近文件末尾时)。nmemb
,表示已经读取到文件末尾,没有足够的数据项可供读取。nmemb
。可以使用 ferror
函数检查是否发生了错误。#include
#define ARRAY_SIZE 5
int main() {
FILE *file = fopen("data.bin", "rb");
if (file == NULL) {
perror("无法打开文件");
return 1;
}
int numbers[ARRAY_SIZE];
size_t items_read = fread(numbers, sizeof(int), ARRAY_SIZE, file);
if (items_read < ARRAY_SIZE) {
if (feof(file)) {
printf("已到达文件末尾,读取了 %zu 个整数。\n", items_read);
} else if (ferror(file)) {
perror("读取文件时发生错误");
}
} else {
printf("成功读取 %zu 个整数。\n", items_read);
}
for (size_t i = 0; i < items_read; i++) {
printf("numbers[%zu] = %d\n", i, numbers[i]);
}
fclose(file);
return 0;
}
#include
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
ptr
:指向要写入的数据的指针。该指针指向的数据块将被写入到文件流中。size
:每个数据项的大小(以字节为单位)。例如,如果要写入整数,size
通常设置为 sizeof(int)
;若写入字符,size
则为 sizeof(char)
。nmemb
:要写入的数据项的数量。函数会尝试将 nmemb
个大小为 size
字节的数据项写入文件流。stream
:指向 FILE
对象的指针,表示数据要写入的目标文件流。这个文件流一般是通过 fopen
函数打开的。fwrite
函数返回实际成功写入的数据项的数量(并非字节数)。具体情况如下:
nmemb
,表明所有指定的数据项都已成功写入文件流。nmemb
,这意味着在写入过程中可能发生了错误,或者由于磁盘空间不足等原因,未能写入所有数据项。可以使用 ferror
函数来检查是否发生了错误。#include
#define ARRAY_SIZE 5
int main() {
FILE *file = fopen("data.bin", "wb");
if (file == NULL) {
perror("无法打开文件");
return 1;
}
int numbers[ARRAY_SIZE] = {1, 2, 3, 4, 5};
size_t items_written = fwrite(numbers, sizeof(int), ARRAY_SIZE, file);
if (items_written < ARRAY_SIZE) {
if (ferror(file)) {
perror("写入文件时发生错误");
}
} else {
printf("成功写入 %zu 个整数到文件。\n", items_written);
}
fclose(file);
return 0;
}
#include
int main() {
FILE *file = fopen("text.txt", "w");
if (file == NULL) {
perror("无法打开文件");
return 1;
}
char str[] = "Hello, World!";
size_t items_written = fwrite(str, sizeof(char), sizeof(str), file);
if (items_written < sizeof(str)) {
if (ferror(file)) {
perror("写入文件时发生错误");
}
} else {
printf("成功写入字符串到文件。\n");
}
fclose(file);
return 0;
}
来源于micro_frank