学期:2024-2025-1 学号:20241303 《计算机基础与程序设计》第十四周学习总结
作业信息
这个作业属于哪个课程 | <班级的链接>(如2024-2025-1-计算机基础与程序设计) |
---|---|
这个作业要求在哪里 | <作业要求的链接>(如2024-2025-1计算机基础与程序设计第十四周作业) |
这个作业的目标 | <写上具体方面>《C语言程序设计》第13-14章并完成云班课测试 |
作业正文 | ... 本博客链接 |
教材学习内容总结
一、文件的基本概念
- 在C语言中,文件是存储在外部介质(如磁盘)上的数据集合。从文件编码的方式来看,文件可分为ASCII文件和二进制文件。
- ASCII文件:也叫文本文件,这种文件的每个字节存放一个ASCII码,代表一个字符。例如,一个整数1234在文本文件中是按照字符'1'、'2'、'3'、'4'的ASCII码值存储的,占4个字节。
- 二进制文件:是把内存中的数据按照其在内存中的存储形式原样输出到磁盘上存放。同样是整数1234,在二进制文件中以二进制形式存储,可能只占2个字节(假设为短整型)。
二、文件指针
- 文件指针是一个指向结构体类型的指针,这个结构体类型是由系统定义的,其中包含了文件名、文件状态和文件当前位置等信息。在C语言中,使用
FILE
类型来声明文件指针。例如:FILE *fp;
,这里fp
就是一个文件指针,通过它可以对文件进行各种操作。
三、文件的打开与关闭
- 文件打开函数
fopen()
- 语法:
FILE *fopen(const char *filename, const char *mode);
- 参数说明:
filename
:是要打开的文件名,可以包含文件路径。例如"test.txt"
表示当前目录下的test.txt
文件,"C:\\data\\file.dat"
表示C
盘data
文件夹下的file.dat
文件。mode
:是打开文件的方式,主要有以下几种:"r"
:以只读方式打开一个文本文件。文件必须存在,否则打开失败。"w"
:以只写方式打开一个文本文件。如果文件不存在,则创建一个新文件;如果文件已存在,则先删除原有内容再写入新内容。"a"
:以追加方式打开一个文本文件。如果文件不存在,则创建一个新文件;如果文件已存在,则在文件末尾追加内容。"rb"
、"wb"
、"ab"
:与上述模式类似,但用于二进制文件。"r+"
、"w+"
、"a+"
:可读可写的文本文件打开方式。"r+"
要求文件必须存在;"w+"
如果文件存在则先清空内容,若不存在则创建;"a+"
在文件末尾进行读写操作,若文件不存在则创建。"rb+"
、"wb+"
、"ab+"
:用于二进制文件的可读可写模式。
- 返回值:如果文件打开成功,则返回一个指向该文件的文件指针;如果打开失败,则返回
NULL
。例如:
- 语法:
FILE *fp;
fp = fopen("test.txt", "r");
if (fp == NULL) {
printf("文件打开失败!\n");
// 可以在这里添加错误处理代码,如退出程序等
return 1;
}
- 文件关闭函数
fclose()
- 语法:
int fclose(FILE *stream);
,其中stream
是要关闭的文件指针,即通过fopen()
函数打开文件后返回的指针。 - 作用:关闭文件,释放文件相关的缓冲区等资源。当一个文件使用完毕后,应该及时关闭,以防止数据丢失或其他错误。
- 返回值:如果文件关闭成功,返回
0
;如果关闭失败,返回EOF
(EOF
是一个在<stdio.h>
中定义的常量,通常值为 -1)。例如:fclose(fp);
,其中fp
是之前打开文件得到的文件指针。
- 语法:
四、文件的读写操作
- 字符读写函数
fgetc()
函数- 语法:
int fgetc(FILE *stream);
,用于从指定的文件流中读取一个字符。 - 返回值:成功读取一个字符时,返回该字符的ASCII码值;如果读到文件末尾或者发生错误,则返回
EOF
。例如,从文件中逐个字符读取并输出,直到文件末尾:
- 语法:
FILE *fp;
fp = fopen("test.txt", "r");
int ch;
while ((ch = fgetc(fp))!= EOF) {
putchar(ch);
}
fclose(fp);
- **`fputc()`函数**
- 语法:`int fputc(int c, FILE *stream);`,用于将一个字符写入指定的文件流中。
- **参数说明**:`c`是要写入的字符(可以是字符常量或者字符变量),`stream`是目标文件指针。
- **返回值**:成功写入一个字符时,返回写入的字符;如果发生错误,则返回`EOF`。例如,将字符串写入文件:
FILE *fp;
fp = fopen("output.txt", "w");
char str[] = "Hello, World!";
for (int i = 0; str[i]!= '\0'; i++) {
fputc(str[i], fp);
}
fclose(fp);
- 字符串读写函数
fgets()
函数- 语法:
char *fgets(char *s, int n, FILE *stream);
,用于从指定文件中读取一个字符串。 - 参数说明:
s
是存储读取字符串的字符数组,n
是读取的字符数(最多读取n - 1
个字符,因为最后要留一个位置给'\0'),stream
是文件指针。 - 返回值:成功读取字符串时,返回指向
s
的指针;如果读到文件末尾或者发生错误,则返回NULL
。例如:
- 语法:
FILE *fp;
fp = fopen("test.txt", "r");
char buffer[100];
if (fgets(buffer, 100, fp)!= NULL) {
printf("%s", buffer);
}
fclose(fp);
- **`fputs()`函数**
- 语法:`int fputs(const char *s, FILE *stream);`,用于将一个字符串写入指定的文件。
- **参数说明**:`s`是要写入的字符串,`stream`是文件指针。
- **返回值**:成功写入字符串时,返回一个非负整数;如果发生错误,则返回`EOF`。例如:
FILE *fp;
fp = fopen("output.txt", "w");
char str[] = "This is a test string.";
fputs(str, fp);
fclose(fp);
- 格式化读写函数(类似于
scanf
和printf
)fscanf()
函数- 语法:
int fscanf(FILE *stream, const char *format,...);
,用于从文件中按照指定的格式读取数据。 - 参数说明:
stream
是文件指针,format
是格式控制字符串,后面是变量地址列表(与scanf
类似)。例如,从文件中读取两个整数:
- 语法:
FILE *fp;
fp = fopen("data.txt", "r");
int num1, num2;
fscanf(fp, "%d %d", &num1, &num2);
printf("读取的两个整数为:%d和%d\n", num1, num2);
fclose(fp);
- **`fprintf()`函数**
- 语法:`int fprintf(FILE *stream, const char *format,...);`,用于将数据按照指定的格式写入文件。
- **参数说明**:`stream`是文件指针,`format`是格式控制字符串,后面是要写入的数据列表(与`printf`类似)。例如,将一个整数和一个字符串写入文件:
FILE *fp;
fp = fopen("output.txt", "w");
int num = 10;
char str[] = "Test data";
fprintf(fp, "整数:%d,字符串:%s", num, str);
fclose(fp);
- 二进制文件读写函数
fread()
函数- 语法:
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
,用于从二进制文件中读取数据。 - 参数说明:
ptr
是存储读取数据的内存地址,size
是每个数据单元的大小(以字节为单位),count
是要读取的数据单元个数,stream
是文件指针。 - 返回值:成功读取的数据单元个数;如果遇到文件末尾或者发生错误,返回值可能小于
count
。例如,从二进制文件中读取一个结构体数组:
- 语法:
typedef struct {
int id;
char name[20];
} Student;
FILE *fp;
fp = fopen("students.dat", "rb");
Student students[10];
size_t n = fread(students, sizeof(Student), 10, fp);
fclose(fp);
- **`fwrite()`函数**
- 语法:`size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);`,用于将数据写入二进制文件。
- **参数说明**:`ptr`是要写入数据的内存地址,`size`是每个数据单元的大小,`count`是要写入的数据单元个数,`stream`是文件指针。
- **返回值**:成功写入的数据单元个数;如果发生错误,返回值可能小于`count`。例如,将一个结构体数组写入二进制文件:
typedef struct {
int id;
char name[20];
} Student;
Student students[10] = { {1, "Alice"}, {2, "Bob"} };
FILE *fp;
fp = fopen("students.dat", "wb");
size_t n = fwrite(students, sizeof(Student), 10, fp);
fclose(fp);
五、文件的定位
ftell()
函数:用于获取文件指针当前位置相对于文件开头的偏移量(以字节为单位)。语法是long ftell(FILE *stream);
,其中stream
是文件指针。返回值是文件指针当前位置相对于文件开头的偏移量,如果发生错误,返回 -1L。例如:
FILE *fp;
fp = fopen("test.txt", "r");
long offset = ftell(fp);
// 进行一些文件读取操作
fclose(fp);
fseek()
函数:用于设置文件指针的位置。语法是int fseek(FILE *stream, long offset, int whence);
。- 参数说明:
stream
:文件指针。offset
:偏移量(以字节为单位),可以是正数(向后偏移)、负数(向前偏移)或0。whence
:指定偏移量的起始位置,有以下三种取值:SEEK_SET
:文件开头,此时offset
是从文件开头开始计算的偏移量。SEEK_CUR
:文件当前位置,offset
是相对于当前位置的偏移量。SEEK_END
:文件末尾,offset
是相对于文件末尾的偏移量,通常为负数。
- 返回值:如果操作成功,返回0;如果发生错误,返回非零值。例如,将文件指针移动到文件开头后10个字节的位置:
- 参数说明:
FILE *fp;
fp = fopen("test.txt", "r");
fseek(fp, 10, SEEK_SET);
// 从新位置开始读取文件
fclose(fp);
rewind()
函数:将文件指针重新定位到文件的开头。语法是void rewind(FILE *stream);
,其中stream
是文件指针。它等价于fseek(fp, 0, SEEK_SET);
。例如:
FILE *fp;
fp = fopen("test.txt", "r");
// 进行一些文件读取操作,使文件指针位置改变
rewind(fp);
// 现在文件指针回到了文件开头,可以重新读取文件
fclose(fp);
基于AI的学习
#include <stdio.h>
int main() {
FILE *fp;
char str[20];
int num;
float fnum;
fp = fopen("test.txt", "r");
if (fp == NULL) {
perror("Error opening file");
return 1;
}
// 读取一个字符串
fscanf(fp, "%s", str);
printf("Read string: %s\n", str);
// 读取一个固定长度的字符串
fscanf(fp, "%5s", str);
printf("Read fixed length string: %s\n", str);
// 读取一个整数
fscanf(fp, "%d", &num);
printf("Read integer: %d\n", num);
// 读取一个浮点数
fscanf(fp, "%f", &fnum);
printf("Read float: %f\n", fnum);
fclose(fp);
return 0;
}
// 假设 test.txt 中的内容如下:
// Hello World
// 123 45.67
#include <stdio.h>
int main() {
FILE *fp;
int num;
int result;
fp = fopen("test.txt", "r");
if (fp == NULL) {
perror("Error opening file");
return 1;
}
result = fscanf(fp, "%d", &num);
if (result == 1) {
printf("Read integer successfully: %d\n", num);
} else {
printf("Error reading integer\n");
}
fclose(fp);
return 0;
}
// 假设 test.txt 中的内容如下:
// Hello
#include <stdio.h>
int main() {
FILE *fp;
int num;
int result;
fp = fopen("test.txt", "r");
if (fp == NULL) {
perror("Error opening file");
return 1;
}
// 尝试读取整数,但文件中是 "abc"
result = fscanf(fp, "%d", &num);
if (result == 0) {
printf("Failed to read integer.\n");
}
// 打印文件指针位置
long int pos = ftell(fp);
printf("File pointer position after first read: %ld\n", pos);
// 清除不匹配的字符
fscanf(fp, "%*s");
// 再次尝试读取整数
result = fscanf(fp, "%d", &num);
if (result == 1) {
printf("Read integer successfully: %d\n", num);
} else {
printf("Failed to read integer again.\n");
}
fclose(fp);
return 0;
}
// 假设 test.txt 中的内容如下:
// abc 123
代码调试中的问题和解决过程
问题一:
孤独字符
Description;输入一个字符串,按照从小到大顺序输出只出现一次的那些字符。
Input:输入一个字符串,输入格式"%s"
Output:按照从小到大顺序输出只出现一次的那些字符,输出格式"%c\n"
疑惑:去判断如何一个字符只出现了一次?
方法:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char str[1000];
scanf("%s", str);
int len = strlen(str);
int count[256] = {0};
for (int i = 0; i < len; i++) {
count[str[i]]++;
}
for (int i = 0; i < 256; i++) {
if (count[i] == 1) {
printf("%c\n", (char)i);
}
}
return 0;
}
其他(感悟、思考等,可选)
要学的还有很多!
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 20/20 | |
第二周 | 300/500 | 2/4 | 18/38 | |
第三周 | 500/1000 | 3/7 | 22/60 | |
第四周 | 300/1300 | 2/9 | 30/90 |