编辑代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <stdbool.h>

#define MAX_RECORDS 1000
#define MAX_NAME_LEN 50
#define MAX_LOC_LEN 100
#define MAX_WEATHER_LEN 50
#define FILENAME_LEN 150
#define DATE_LEN 20

typedef struct {
    char location[MAX_LOC_LEN];
    char fishSpecies[MAX_NAME_LEN];
    float weight;
    char weather[MAX_WEATHER_LEN];
    time_t date;
    bool isRare;
} FishingRecord;

FishingRecord records[MAX_RECORDS];
int recordCount = 0;

// 函数声明
void addRecord();
void displayRecords();
bool saveRecords();
bool loadRecords();
void generateStatistics();
void searchRecords();
bool editRecord();
bool deleteRecord();
void markRareFish();
void displayMenu();
void clearInputBuffer();
void toLowerCase(char *str);
int compareStringsIgnoreCase(const char *str1, const char *str2);
bool isValidWeight(float weight);
bool isValidDate(const char *dateStr);
bool parseDate(const char *dateStr, struct tm *tm);
void printRecord(FishingRecord record, int index);
void printHeader();

int main() {
    if (!loadRecords()) {
        printf("警告:加载记录失败,将从空记录开始\n");
    }

    int choice;
    do {
        displayMenu();
        printf("请输入您的选择(1-8): ");
        if (scanf("%d", &choice) != 1) {
            clearInputBuffer();
            printf("输入无效,请输入数字\n");
            continue;
        }
        clearInputBuffer();

        switch(choice) {
            case 1: addRecord(); break;
            case 2: displayRecords(); break;
            case 3: searchRecords(); break;
            case 4: editRecord(); break;
            case 5: deleteRecord(); break;
            case 6: generateStatistics(); break;
            case 7: markRareFish(); break;
            case 8: 
                if (saveRecords()) {
                    printf("记录已保存,程序退出。\n");
                } else {
                    printf("保存失败,是否仍要退出?(y/n): ");
                    char confirm = getchar();
                    if (tolower(confirm) != 'y') {
                        choice = 0; // 继续循环
                    }
                }
                break;
            default:
                printf("无效的选择,请输入1-8之间的数字\n");
        }
    } while(choice != 8);

    return 0;
}

void displayMenu() {
    printf("\n===== 钓鱼记录管理系统 =====\n");
    printf("1. 添加钓鱼记录\n");
    printf("2. 显示所有记录\n");
    printf("3. 搜索记录\n");
    printf("4. 编辑记录\n");
    printf("5. 删除记录\n");
    printf("6. 生成统计报表\n");
    printf("7. 标记稀有鱼种\n");
    printf("8. 保存并退出\n");
    printf("============================\n");
}

void addRecord() {
    if(recordCount >= MAX_RECORDS) {
        printf("错误:记录已满,无法添加更多记录\n");
        return;
    }
    
    FishingRecord newRecord;
    char dateInput[DATE_LEN];
    
    printf("\n--- 添加新钓鱼记录 ---\n");
    
    // 输入钓鱼地点
    while(true) {
        printf("请输入钓鱼地点(1-%d字符): ", MAX_LOC_LEN-1);
        if (fgets(newRecord.location, MAX_LOC_LEN, stdin) == NULL) {
            printf("输入错误\n");
            continue;
        }
        newRecord.location[strcspn(newRecord.location, "\n")] = '\0';
        if (strlen(newRecord.location) > 0) break;
        printf("地点不能为空\n");
    }
    
    // 输入鱼种
    while(true) {
        printf("请输入鱼种(1-%d字符): ", MAX_NAME_LEN-1);
        if (fgets(newRecord.fishSpecies, MAX_NAME_LEN, stdin) == NULL) {
            printf("输入错误\n");
            continue;
        }
        newRecord.fishSpecies[strcspn(newRecord.fishSpecies, "\n")] = '\0';
        if (strlen(newRecord.fishSpecies) > 0) break;
        printf("鱼种不能为空\n");
    }
    
    // 输入重量
    while(true) {
        printf("请输入重量(kg): ");
        if (scanf("%f", &newRecord.weight) != 1) {
            printf("请输入有效的数字\n");
            clearInputBuffer();
            continue;
        }
        clearInputBuffer();
        if (isValidWeight(newRecord.weight)) break;
        printf("重量必须在0.01-500kg之间\n");
    }
    
    // 输入天气情况
    while(true) {
        printf("请输入天气情况(1-%d字符): ", MAX_WEATHER_LEN-1);
        if (fgets(newRecord.weather, MAX_WEATHER_LEN, stdin) == NULL) {
            printf("输入错误\n");
            continue;
        }
        newRecord.weather[strcspn(newRecord.weather, "\n")] = '\0';
        if (strlen(newRecord.weather) > 0) break;
        printf("天气不能为空\n");
    }
    
    // 输入日期
    while(true) {
        printf("请输入日期(YYYY-MM-DD,留空使用今天): ");
        if (fgets(dateInput, DATE_LEN, stdin) == NULL) {
            printf("输入错误\n");
            continue;
        }
        dateInput[strcspn(dateInput, "\n")] = '\0';
        
        if (strlen(dateInput) == 0) {
            time(&newRecord.date);
            break;
        } else if (isValidDate(dateInput)) {
            struct tm tm = {0};
            if (parseDate(dateInput, &tm)) {
                newRecord.date = mktime(&tm);
                break;
            }
        }
        printf("日期格式无效,请使用YYYY-MM-DD格式\n");
    }
    
    newRecord.isRare = false;
    records[recordCount++] = newRecord;
    printf("\n记录添加成功!\n");
}

bool saveRecords() {
    if(recordCount == 0) {
        printf("没有记录需要保存\n");
        return true;
    }
    
    FILE *fileList = fopen("fishing_files.txt", "w");
    if(fileList == NULL) {
        perror("无法创建文件列表");
        return false;
    }
    
    bool success = true;
    for(int i = 0; i < recordCount; i++) {
        char filename[FILENAME_LEN];
        snprintf(filename, FILENAME_LEN, "fishing_%s.txt", records[i].location);
        
        // 检查是否已经处理过这个地点的文件
        bool alreadyProcessed = false;
        for(int j = 0; j < i; j++) {
            if(strcmp(records[i].location, records[j].location) == 0) {
                alreadyProcessed = true;
                break;
            }
        }
        if(alreadyProcessed) continue;
        
        // 写入文件列表
        fprintf(fileList, "%s\n", filename);
        
        FILE *file = fopen(filename, "w");
        if(file == NULL) {
            perror("无法创建记录文件");
            success = false;
            continue;
        }
        
        fprintf(file, "地点,鱼种,重量(kg),天气,日期,是否稀有\n");
        for(int j = 0; j < recordCount; j++) {
            if(strcmp(records[i].location, records[j].location) == 0) {
                char dateStr[DATE_LEN];
                struct tm *timeinfo = localtime(&records[j].date);
                strftime(dateStr, sizeof(dateStr), "%Y-%m-%d", timeinfo);
                
                fprintf(file, "%s,%s,%.2f,%s,%s,%d\n", 
                       records[j].location,
                       records[j].fishSpecies,
                       records[j].weight,
                       records[j].weather,
                       dateStr,
                       records[j].isRare ? 1 : 0);
            }
        }
        
        if(fclose(file) != 0) {
            perror("关闭文件失败");
            success = false;
        }
    }
    
    if(fclose(fileList) != 0) {
        perror("关闭文件列表失败");
        success = false;
    }
    
    return success;
}

bool loadRecords() {
    FILE *fileList = fopen("fishing_files.txt", "r");
    if(fileList == NULL) {
        return false;
    }
    
    char filename[FILENAME_LEN];
    while(fgets(filename, FILENAME_LEN, fileList) && recordCount < MAX_RECORDS) {
        filename[strcspn(filename, "\n")] = '\0';
        
        FILE *file = fopen(filename, "r");
        if(file == NULL) {
            printf("无法打开文件: %s\n", filename);
            continue;
        }
        
        char line[256];
        fgets(line, sizeof(line), file); // 跳过标题行
        
        while(fgets(line, sizeof(line), file) && recordCount < MAX_RECORDS) {
            FishingRecord record;
            char dateStr[DATE_LEN];
            
            if(sscanf(line, "%[^,],%[^,],%f,%[^,],%[^,],%d",
                      record.location,
                      record.fishSpecies,
                      &record.weight,
                      record.weather,
                      dateStr,
                      &record.isRare) == 6) {
                
                struct tm tm = {0};
                if(parseDate(dateStr, &tm)) {
                    record.date = mktime(&tm);
                    records[recordCount++] = record;
                }
            }
        }
        fclose(file);
    }
    fclose(fileList);
    return true;
}

// 其他函数实现...

bool isValidWeight(float weight) {
    return weight > 0.01 && weight <= 500.0;
}

bool isValidDate(const char *dateStr) {
    if(strlen(dateStr) != 10) return false;
    if(dateStr[4] != '-' || dateStr[7] != '-') return false;
    
    for(int i = 0; i < 10; i++) {
        if(i == 4 || i == 7) continue;
        if(!isdigit(dateStr[i])) return false;
    }
    
    return true;
}

bool parseDate(const char *dateStr, struct tm *tm) {
    if(sscanf(dateStr, "%d-%d-%d",
              &tm->tm_year,
              &tm->tm_mon,
              &tm->tm_mday) != 3) {
        return false;
    }
    
    tm->tm_year -= 1900;
    tm->tm_mon -= 1;
    tm->tm_hour = 0;
    tm->tm_min = 0;
    tm->tm_sec = 0;
    tm->tm_isdst = -1;
    
    return true;
}

void clearInputBuffer() {
    int c;
    while((c = getchar()) != '\n' && c != EOF);
}