38 C语言文件的读取与写入

38 C语言文件的读取与写入

1. 简介

在C语言中,文件操作是处理数据持久化的重要部分。通过文件读取和写入,程序可以保存数据并在需要时重新加载它们。

2. 文件操作的基本概念

  • 文件:存储数据的地方,可以是文本文件或二进制文件。
  • 文件指针:用于在文件中定位的指针。

3. 文件操作的标准库函数

C语言通过标准库提供了一系列函数来进行文件的读取和写入。

3.1 文件打开与关闭

  • fopen(): 打开文件并返回文件指针。
  • fclose(): 关闭已打开的文件。

示例代码:

1
2
3
4
5
6
FILE *file;
file = fopen("example.txt", "w"); // 以写入模式打开文件
if (file == NULL) {
// 错误处理
}
fclose(file); // 关闭文件

3.2 文件模式

  • "r": 只读模式,文件必须存在。
  • "w": 只写模式,若文件存在则会被清空,不存在则创建。
  • "a": 追加模式,数据会被写入文件末尾。
  • "r+": 读写模式,文件必须存在。
  • "w+": 读写模式,若文件存在则会被清空,不存在则创建。
  • "a+": 读追加模式,数据会被写入文件末尾,允许读操作。

3.3 写入文件

  • fprintf(): 按格式写入数据。
  • fputs(): 写入字符串,不带格式。
  • fwrite(): 写入二进制数据。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

int main() {
FILE *file = fopen("example.txt", "w");
if (file == NULL) {
perror("Error opening file");
return 1;
}

fprintf(file, "Hello, World!\n"); // 格式化写入
fputs("This is a test.\n", file); // 写入字符串

fclose(file); // 关闭文件
return 0;
}

3.4 读取文件

  • fscanf(): 从文件中按格式读取数据。
  • fgets(): 读取一行字符串。
  • fread(): 读取二进制数据。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>

int main() {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
perror("Error opening file");
return 1;
}

char buffer[100];
while (fgets(buffer, sizeof(buffer), file) != NULL) {
printf("%s", buffer); // 打印读取的行
}

fclose(file); // 关闭文件
return 0;
}

3.5 错误处理

文件操作可能会出错,应使用 perror()ferror() 检查错误。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
perror("Error opening file");
// 处理错误
return 1;
}

// 进行文件操作
if (ferror(file)) {
perror("Error reading from file");
}

fclose(file);

4. 操作总结

  • 使用 fopen() 打开文件,进行读写操作后使用 fclose() 关闭文件。
  • 根据需求选择合适的文件模式。
  • 使用相应的读取和写入函数:fprintf()fscanf()fgets()fread() 等。
  • 处理错误以确保程序的健壮性。

5. 练习

  1. 创建一个程序,将用户输入的若干行文本写入一个文件中。
  2. 创建一个程序,读取一个文件并统计其中的行数和单词数。

通过这些基本的文件操作,C语言小白可以开始简单的文件处理工作,并为更复杂的应用程序打下基础。

39 C语言进阶到上手大纲

39 C语言进阶到上手大纲

小节:实时操作系统基础

1. 实时操作系统概述

  • 定义实时操作系统(RTOS)是一种专门设计用于处理实时应用程序的操作系统。
  • 特性
    • 确定性:能够在预定时间内完成任务。
    • 多任务:支持多个任务并能够合理调度它们。
    • 优先级调度:任务有优先级,系统根据优先级调度任务。

2. 实时系统的分类

  • 硬实时系统:必须在严格的时间限制内完成任务。
  • 软实时系统:尽量在时间限制内完成任务,但不必严格遵守。

3. 实时任务的调度

  • 调度算法
    • 固定优先级调度(如 Rate Monotonic Scheduling):优先级根据任务周期决策。
    • 动态优先级调度(如 Earliest Deadline First):根据任务的紧迫性动态调整优先级。

4. 常见的RTOS

  • FreeRTOS:开源RTOS,常用于嵌入式系统。
  • ChibiOS:高效、轻量的RTOS,具有多种功能。
  • RTEMS:适合于高可靠性和高性能的场合。

5. FreeRTOS实例

5.1 安装FreeRTOS

  • 下载FreeRTOS源代码并添加到项目中。

5.2 创建一个简单的RTOS任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <FreeRTOS.h>
#include <task.h>

// 定义任务句柄
TaskHandle_t xTaskHandle = NULL;

// 任务函数
void vTaskFunction(void *pvParameters) {
// 任务循环
for(;;) {
// 做一些工作
printf("Task is running\n");
// 挂起一段时间
vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟1000毫秒
}
}

int main(void) {
// 创建任务
xTaskCreate(vTaskFunction, "Task1", 1000, NULL, 1, &xTaskHandle);

// 启动调度器
vTaskStartScheduler();

// 程序不应执行到这里
for(;;);
return 0;
}

6. 任务间通信

  • 消息队列:任务之间通过消息队列进行通信。
  • 信号量:用于同步和互斥。
  • 事件组:多任务共享的一组事件。

6.1 使用消息队列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <FreeRTOS.h>
#include <queue.h>

// 定义消息队列
QueueHandle_t xQueue;

void senderTask(void *pvParameters) {
int valueToSend = 0;
for(;;) {
xQueueSend(xQueue, &valueToSend, portMAX_DELAY);
valueToSend++;
vTaskDelay(pdMS_TO_TICKS(500));
}
}

void receiverTask(void *pvParameters) {
int receivedValue;
for(;;) {
xQueueReceive(xQueue, &receivedValue, portMAX_DELAY);
printf("Received value: %d\n", receivedValue);
}
}

int main(void) {
xQueue = xQueueCreate(10, sizeof(int)); // 创建消息队列
// 创建任务
xTaskCreate(senderTask, "Sender", 1000, NULL, 1, NULL);
xTaskCreate(receiverTask, "Receiver", 1000, NULL, 1, NULL);

vTaskStartScheduler();
for(;;);
return 0;
}

7. 实时系统中的资源管理

  • 内存管理:RTOS通常提供特定的内存分配方式,以避免碎片化。
  • 时间管理:提供精确的定时器和时间切片功能。

8. 调试和性能分析

  • RTOS调试:使用调试工具和日志功能检查任务状态或堆栈信息。
  • 性能评估:测量任务的响应时间和处理能力,优化系统设计以满足实时要求。

9. 实战项目示例

  • 项目描述:开发一个简单的实时控制应用,例如LED闪烁和温度监测。
  • 项目实现
    • 创建任务控制LED状态和读取温度传感器数据。
    • 通过消息队列实现任务间的通信。

10. 重要概念总结

  • 理解实时性并发性的区别。
  • 掌握基本的RTOS功能,能创建任务并进行同步与通信。
  • 实际操作与编码中积累经验,不断优化RTOS应用。

以上内容提供了实时操作系统的基础知识和操作实例,为你深入学习C语言及RTOS奠定基础。

39 C语言初学者学习大纲 - 文件操作章节

39 C语言初学者学习大纲 - 文件操作章节

文件操作

文件操作是 C 语言中的重要部分,它允许程序读取和写入文件中的数据。以下是文件操作的基本概念和常用函数。

1. 文件指针

在 C 语言中,文件通过 FILE 结构来处理。我们需要使用文件指针来操作文件。

1
FILE *fp;

2. 打开文件

使用 fopen() 函数打开文件。该函数的原型如下:

1
FILE *fopen(const char *filename, const char *mode);
  • filename: 要打开的文件名。
  • mode: 文件打开模式,可以是以下之一:
    • "r": 以只读方式打开。
    • "w": 以写入方式打开(如果文件存在则清空文件,如果不存在则创建新文件)。
    • "a": 以追加方式打开(写入时数据将添加到文件末尾)。
    • "rb", "wb", "ab": 二进制模式。

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main() {
FILE *fp = fopen("example.txt", "w");
if (fp == NULL) {
printf("文件打开失败!\n");
return 1;
}
fprintf(fp, "Hello, World!\n");
fclose(fp);
return 0;
}

3. 关闭文件

使用 fclose() 函数关闭已打开的文件,以释放系统资源。

1
int fclose(FILE *stream);

示例代码

1
fclose(fp);

4. 读取文件

使用 fgetc()fgets()fread() 函数读取文件中的数据。

  • fgetc(): 读取单个字符。
1
int fgetc(FILE *stream);
  • fgets(): 读取一行数据。
1
char *fgets(char *str, int n, FILE *stream);
  • fread(): 读取块数据。
1
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);

示例代码

1
2
3
4
5
6
7
8
9
10
11
char buffer[100];
FILE *fp = fopen("example.txt", "r");
if (fp == NULL) {
perror("文件打开失败");
}

if (fgets(buffer, 100, fp) != NULL) {
printf("读取的内容: %s\n", buffer);
}

fclose(fp);

5. 写入文件

使用 fputc()fputs()fwrite() 函数向文件写入数据。

  • fputc(): 写入单个字符。
1
int fputc(int char, FILE *stream);
  • fputs(): 写入字符串。
1
int fputs(const char *str, FILE *stream);
  • fwrite(): 写入块数据。
1
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);

示例代码

1
2
3
4
5
6
7
8
9
FILE *fp = fopen("output.txt", "w");
if (fp == NULL) {
perror("文件打开失败");
}

fputs("Hello, World!", fp);
fputc('\n', fp); // 写入换行

fclose(fp);

6. 文件定位

使用 fseek()ftell()rewind() 函数定位文件指针。

  • fseek(): 移动文件指针。
1
int fseek(FILE *stream, long offset, int whence);
  • ftell(): 获取当前位置。
1
long ftell(FILE *stream);
  • rewind(): 返回文件指针到开头。
1
void rewind(FILE *stream);

示例代码

1
2
3
4
5
FILE *fp = fopen("example.txt", "r");
fseek(fp, 0, SEEK_END); // 移动到文件末尾
long size = ftell(fp); // 获取文件大小
rewind(fp); // 返回文件开头
fclose(fp);

7. 错误处理

在文件操作中,随时检查错误是很重要的。你可以使用 perror()fprintf(stderr, ...) 来输出错误信息。

例子

1
2
3
4
FILE *fp = fopen("nonexistent.txt", "r");
if (fp == NULL) {
perror("文件打开错误");
}

8. 文件的其他操作

  • remove(): 删除文件。
1
int remove(const char *filename);
  • rename(): 重命名文件。
1
int rename(const char *oldname, const char *newname);

总结

文件操作在 C 语言中是非常重要的一部分,掌握以上基本函数可以帮助你有效地读写文件。练习使用这些函数,尝试创建、读取和写入不同类型的文件,以加深对文件操作的理解。