Chapter12

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;  
}
相关推荐
网易独家音乐人Mike Zhou3 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
搬砖的小码农_Sky6 小时前
C语言:数组
c语言·数据结构
ahadee10 小时前
蓝桥杯每日真题 - 第19天
c语言·vscode·算法·蓝桥杯
Theliars10 小时前
C语言之字符串
c语言·开发语言
Reese_Cool10 小时前
【数据结构与算法】排序
java·c语言·开发语言·数据结构·c++·算法·排序算法
搬砖的小码农_Sky11 小时前
C语言:结构体
c语言·数据结构
平头哥在等你13 小时前
求一个3*3矩阵对角线元素之和
c语言·算法·矩阵
尹蓝锐13 小时前
C语言-11-18笔记
c语言
ahadee14 小时前
蓝桥杯每日真题 - 第18天
c语言·vscode·算法·蓝桥杯
就爱六点起14 小时前
C/C++ 中的类型转换方式
c语言·开发语言·c++