12.3
c
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#define BUFFER_SIZE 1024
void convert_to_uppercase(char *str) {
for (; *str; ++str) {
*str = toupper((unsigned char)*str);
}
}
int main() {
char buffer[BUFFER_SIZE];
FILE *file = fopen("output.txt", "w");
if (file == NULL) {
perror("文件打开失败");
return EXIT_FAILURE;
}
printf("输入ctrl + c 或者ctrl + z 结束输入\n");
while (fgets(buffer, BUFFER_SIZE, stdin) != NULL) {
convert_to_uppercase(buffer);
fputs(buffer, file);
}
//清除错误标志和文件结束(EOF)标志
clearerr(stdin);
fclose(file);
printf("文件写入成功\n");
return EXIT_SUCCESS;
}
12.4
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 1024
void reverse_string(char *str);
int main() {
FILE *input_file, *output_file;
char buffer[BUFFER_SIZE];
// 打开输入文件
input_file = fopen("input.txt", "r");
if (input_file == NULL) {
perror("文件打开失败");
return EXIT_FAILURE;
}
// 打开输出文件
output_file = fopen("output.txt", "w");
if (output_file == NULL) {
perror("文件打开失败");
fclose(input_file);
return EXIT_FAILURE;
}
// 逐行读取输入文件并逆置写入输出文件
while (fgets(buffer, BUFFER_SIZE, input_file) != NULL) {
buffer[strcspn(buffer, "\n")] = 0;
// 翻转字符串
reverse_string(buffer);
// 写入输出文件
fputs(buffer, output_file);
fputs("\n", output_file); // 添加换行符以保持格式
}
// 关闭文件
fclose(input_file);
fclose(output_file);
printf("文件写入失败\n");
return EXIT_SUCCESS;
}
// 翻转字符串
void reverse_string(char *str) {
int length = strlen(str);
for (int i = 0; i < length / 2; i++) {
char temp = str[i];
str[i] = str[length - i - 1];
str[length - i - 1] = temp;
}
}
12.5
c
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
bool is_word_char(char ch) {
// 判断字符是否是单词的一部分(字母、数字或下划线)
return isalnum((unsigned char)ch) || ch == '_';
}
int count_words(const char *filename) {
FILE *file = fopen(filename, "r");
if (file == NULL) {
perror("文件打开失败");
return EXIT_FAILURE; // 打开文件失败
}
int word_count = 0;
bool in_word = false;
char ch;
while ((ch = fgetc(file)) != EOF) {
if (is_word_char(ch)) {
if (!in_word) {
in_word = true; // 进入单词
word_count++; // 单词计数加一
}
} else {
in_word = false; // 退出单词
}
}
// 处理文件末尾可能的情况,如果最后一个字符是单词字符,则上面的循环已经正确计数
// 不需要额外的检查,因为当读取到EOF时,循环已经结束
fclose(file);
return word_count;
}
int main() {
const char *filename = "textfile.txt"; // 替换为你的文本文件名
int word_count = count_words(filename);
if (word_count != -1) {
printf("文件中的单词数量为: %d\n", word_count);
}
return 0;
}
12.7
c
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SIZE 1024
void replace_tabs_with_spaces(const char *filename) {
FILE *source_file = fopen(filename, "r");
if (source_file == NULL) {
perror("文件打开失败");
return EXIT_FAILURE;
}
// 创建一个临时文件来存储替换后的内容
// 为了简化,这里我们使用相同的文件名但加上".tmp"后缀
// 在实际应用中,应该使用更安全的临时文件创建方法
char temp_filename[strlen(filename) + 5]; // 留出空间给".tmp"和空字符
strcpy(temp_filename, filename);
strcat(temp_filename, ".tmp");
FILE *temp_file = fopen(temp_filename, "w");
if (temp_file == NULL) {
perror("打开临时文件失败");
fclose(source_file);
return EXIT_FAILURE;
}
char buffer[BUFFER_SIZE];
size_t bytes_read;
while ((bytes_read = fread(buffer, 1, BUFFER_SIZE, source_file)) > 0) {
for (size_t i = 0; i < bytes_read; ++i) {
if (buffer[i] == '\t') {
fputc(' ', temp_file);
fputc(' ', temp_file);
fputc(' ', temp_file);
fputc(' ', temp_file);
} else {
fputc(buffer[i], temp_file);
}
}
}
fclose(source_file);
fclose(temp_file);
// 删除源文件(可选,但存在风险)
// if (remove(filename) != 0) {
// perror("Failed to delete source file");
// exit(EXIT_FAILURE);
// }
// 重命名临时文件为源文件的名字(可选,但在这里直接覆盖)
if (rename(temp_filename, filename) != 0) {
perror("重命名临时文件出错");
return EXIT_FAILURE;
}
printf("%s中制表符替换空格成功\n", filename);
}
int main() {
const char *filename = "sourcecode.c"; // 替换为源代码文件名
replace_tabs_with_spaces(filename);
return 0;
}
12.7
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_STUDENTS 20
#define NAME_LENGTH 50
// 定义学生信息结构体
typedef struct {
char name[NAME_LENGTH]; // 姓名
int id; // 学号
float math; // 数学成绩
float english; // 英语成绩
float c_language; // C语言成绩
} Student;
// 将学生信息写入二进制文件
void write_students_to_binary_file(const char *filename, Student students[], int num_students) {
FILE *file = fopen(filename, "wb"); // 以二进制写入模式打开文件
if (file == NULL) {
perror("文件打开失败");
return EXIT_FAILURE;
}
size_t written = fwrite(students, sizeof(Student), num_students, file); // 写入学生信息到文件
if (written != num_students) {
perror("写入文件失败,未写入所有学生信息");
fclose(file);
return EXIT_FAILURE;
}
fclose(file); // 关闭文件
printf("成功将%d名学生信息写入到%s\n", num_students, filename);
}
int main() {
Student students[NUM_STUDENTS]; // 创建学生信息数组
// 示例数据填充(实际应用中应从用户输入或其他来源获取)
for (int i = 0; i < NUM_STUDENTS; ++i) {
snprintf(students[i].name, NAME_LENGTH, "学生%02d", i + 1); // 生成学生姓名
students[i].id = 1000 + i; // 生成学号(从1000开始递增)
students[i].math = (float)(rand() % 101); // 生成随机数学成绩(0-100之间)
students[i].english = (float)(rand() % 101); // 生成随机英语成绩
students[i].c_language = (float)(rand() % 101); // 生成随机C语言成绩
}
const char *filename = "students.bin"; // 定义文件名
write_students_to_binary_file(filename, students, NUM_STUDENTS); //将学生信息写入文件
return 0;
}
17.8
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_STUDENTS 20
#define NAME_LENGTH 50
// 定义学生信息结构体
typedef struct {
char name[NAME_LENGTH];
int id;
float math;
float english;
float c_language;
float total; // 新增总分字段
} Student;
// 比较函数,用于qsort排序
int compare_students(const void *a, const void *b) {
Student *studentA = (Student *)a;
Student *studentB = (Student *)b;
// 按总分降序排序
return (studentB->total - studentA->total > 0) - (studentA->total - studentB->total > 0);
}
// 从二进制文件读取学生信息
void read_students_from_binary_file(const char *filename, Student students[], int num_students) {
FILE *file = fopen(filename, "rb");
if (file == NULL) {
perror("文件打开失败");
return EXIT_FAILURE;
}
size_t read = fread(students, sizeof(Student), num_students, file);
if (read != num_students) {
perror("文件读取失败");
fclose(file);
return EXIT_FAILURE;
}
// 计算每个学生的总分
for (int i = 0; i < num_students; ++i) {
students[i].total = students[i].math + students[i].english + students[i].c_language;
}
fclose(file);
}
// 将排序后的学生信息写入文本文件
void write_students_to_text_file(const char *filename, Student students[], int num_students) {
FILE *file = fopen(filename, "w");
if (file == NULL) {
perror("文件打开失败");
return EXIT_FAILURE;
}
// 写入表头
fprintf(file, "排名\t姓名\t学号\t数学\t英语\tC语言\t总分\n");
// 写入学生信息
for (int i = 0; i < num_students; ++i) {
fprintf(file, "%d\t%s\t%d\t%.2f\t%.2f\t%.2f\t%.2f\n",
i + 1, students[i].name, students[i].id,
students[i].math, students[i].english, students[i].c_language, students[i].total);
}
fclose(file);
printf("成功将排序后的学生信息写入到%s\n", filename);
}
int main() {
Student students[NUM_STUDENTS];
const char *binary_filename = "students.bin";
read_students_from_binary_file(binary_filename, students, NUM_STUDENTS);
// 对学生信息进行排序
qsort(students, NUM_STUDENTS, sizeof(Student), compare_students);
const char *text_filename = "students_rank.txt";
write_students_to_text_file(text_filename, students, NUM_STUDENTS);
return 0;
}
12.9
定义一个学生信息结构体来存储学生的记录。
编写函数来读取和写入文件。
打开源文件,读取所有学生记录到一个数组中。
遍历数组,将偶数序的记录写入新的文件,并从数组中移除这些记录。
将剩余的记录写回到原文件(覆盖原有内容)。
关闭所有文件。
需要注意的是,由于C语言中的文件操作不支持直接"删除"文件中的某部分数据,我们需要通过读取、处理后再写回的方式来实现这一需求。
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_STUDENTS 20
#define NAME_LENGTH 50
typedef struct {
char name[NAME_LENGTH];
int id;
float score;
} Student;
void read_students(const char *filename, Student students[], int *num_students) {
FILE *file = fopen(filename, "r");
if (!file) {
perror("打开源文件失败");
exit(EXIT_FAILURE);
}
*num_students = fread(students, sizeof(Student), NUM_STUDENTS, file);
fclose(file);
}
void write_students(const char *filename, Student students[], int num_students) {
FILE *file = fopen(filename, "w");
if (!file) {
perror("打开目标文件失败");
exit(EXIT_FAILURE);
}
fwrite(students, sizeof(Student), num_students, file);
fclose(file);
}
int main() {
Student students[NUM_STUDENTS];
int num_students;
Student even_students[NUM_STUDENTS]; // 用于存储偶数序的学生记录
int even_count = 0; // 偶数序学生记录的计数器
// 读取源文件中的所有学生记录
read_students("students.dat", students, &num_students);
// 遍历学生记录,将偶数序的记录保存到even_students数组中
for (int i = 0; i < num_students; ++i) {
if ((i + 1) % 2 == 0) { // 注意这里i是从0开始的,所以(i + 1)才是实际的记录序号
even_students[even_count++] = students[i];
}
}
// 将偶数序的记录写入新的文件
write_students("even_students.dat", even_students, even_count);
// 将剩余(奇数序)的记录写回原文件(覆盖原有内容)
write_students("students.dat", students, num_students - even_count);
// 注意:这里需要调整fwrite的第三个参数,因为我们已经移除了偶数序的记录
// 由于我们是从头开始覆盖写入的,所以不需要移动数组中的元素来填补被删除记录的空间
// 但是,如果源文件不是以二进制模式打开,而是包含了定长记录之间的分隔符或换行符,
// 那么在写回时可能需要处理这些分隔符或换行符。
// 在本例中,我们假设文件是以二进制模式打开,且记录之间没有额外的分隔符。
printf("偶数序的学生记录已写入even_students.dat,并已从students.dat中删除。\n");
return 0;
}
12.10
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_WORDS 1000
#define MAX_WORD_LENGTH 100
// 比较函数,用于qsort排序
int compare(const void *a, const void *b) {
char *wordA = *(char **)a;
char *wordB = *(char **)b;
return strcmp(wordA, wordB);
}
int main() {
char words1[MAX_WORDS][MAX_WORD_LENGTH];
char words2[MAX_WORDS][MAX_WORD_LENGTH];
char *allWords[2 * MAX_WORDS]; // 用于存储所有单词的指针数组
int count1 = 0, count2 = 0, totalCount = 0;
FILE *file1, *file2, *fileOut;
char word[MAX_WORD_LENGTH];
// 读取第一个文件
file1 = fopen("file1.txt", "r");
if (!file1) {
perror("无法打开第一个文件");
return EXIT_FAILURE;
}
while (fscanf(file1, "%s", word) == 1 && count1 < MAX_WORDS) {
strcpy(words1[count1], word);
count1++;
}
fclose(file1);
// 读取第二个文件
file2 = fopen("file2.txt", "r");
if (!file2) {
perror("无法打开第二个文件");
return EXIT_FAILURE;
}
while (fscanf(file2, "%s", word) == 1 && count2 < MAX_WORDS) {
strcpy(words2[count2], word);
count2++;
}
fclose(file2);
// 合并单词到allWords数组
for (int i = 0; i < count1; i++) {
allWords[totalCount++] = words1[i];
}
for (int i = 0; i < count2; i++) {
allWords[totalCount++] = words2[i];
}
// 对allWords数组进行排序
qsort(allWords, totalCount, sizeof(char *), compare);
// 将排序后的单词写入新的文件
fileOut = fopen("sorted_words.txt", "w");
if (!fileOut) {
perror("无法打开输出文件");
return EXIT_FAILURE;
}
for (int i = 0; i < totalCount; i++) {
fprintf(fileOut, "%s\n", allWords[i]);
}
fclose(fileOut);
printf("单词已合并并按字典序写入sorted_words.txt文件。\n");
return 0;
}