C语言 向文件添加活动

z9smfwbn  于 2023-11-16  发布在  其他
关注(0)|答案(2)|浏览(83)

当我尝试向我的文本文件添加Activity时,它看起来像这样:

S1,CM004;CM020;E001
S2,CM010;CM009;CM004;CM006;SM001;E001;SM002;PC007
S3,CM020;CM17;T001

字符串
我不能添加它。当我添加它到S1 student时,它不会添加行尾。有没有一种方法可以像这样在末尾添加Activity;E002或; CM 003。简单地说,我只是想将Activity添加到行尾。

typedef struct {
    char studentID[20];
    char activities[50][10];
    int activityCount;
} StudentDetails;

void addActivity(const char *studentID, const char *codeToAdd) {
    FILE *studentFile = fopen("StudentAccounts.txt", "r+");

    if (studentFile == NULL) {
        perror("Error opening student file");
        return;
    }

    StudentDetails studentDetails;
    int found = 0;

    // Read student's chosen activities
    while (fscanf(studentFile, "%19[^,],", studentDetails.studentID) == 1) {
        // Check if the student ID matches
        if (strcmp(studentDetails.studentID, studentID) == 0) {
            found = 1;
            studentDetails.activityCount = 0;

            // Read and store existing activities
            while (fscanf(studentFile, "%9[^;];", studentDetails.activities[studentDetails.activityCount]) == 1) {
                trimWhitespace(studentDetails.activities[studentDetails.activityCount]);
                studentDetails.activityCount++;

                if (studentDetails.activityCount >= 50) {
                    printf("Warning: Maximum number of activities reached.\n");
                    break;
                }
            }

            // Add the new activity if not already present
            int activityFound = 0;
            for (int i = 0; i < studentDetails.activityCount; i++) {
                if (strcmp(studentDetails.activities[i], codeToAdd) == 0) {
                    activityFound = 1;
                    break;
                }
            }

            if (!activityFound) {
                // Append the new activity code
                strncpy(studentDetails.activities[studentDetails.activityCount], codeToAdd, sizeof(studentDetails.activities[0]));
                studentDetails.activityCount++;

                // Move file pointer back to the beginning of the line
                fseek(studentFile, -strlen(studentDetails.studentID) - 1, SEEK_CUR);

                // Write updated activities to the file
                for (int i = 0; i < studentDetails.activityCount; i++) {
                    fprintf(studentFile, "%s;", studentDetails.activities[i]);
                }

                // Break out of the loop since we found and updated the student
                break;
            }
        }

        // Skip the rest of the line
        while (fgetc(studentFile) != '\n') {
            // Check for end of file
            if (feof(studentFile)) {
                break;
            }
        }
    }

    fclose(studentFile);

    if (!found) {
        printf("Student ID %s not found.\n", studentID);
    } else {
        printf("Activity code %s added to student %s.\n", codeToAdd, studentID);
    }
}

int studentRole(const char ID[20]) {
    int choice;
    char codeToChange[20];
    char codeToAdd[20];
    char codeToDelete[20];
    int coreCredits = 0;
    int coreModulesSelected = 0; // Count of selected core modules

    do {
        printf("\nMenu:\n");
        printf("1. View/Track activities and credits\n");
        printf("2. Select an Core Module\n");
        printf("3. Delete an Core Module\n");
        printf("4. Select Activity\n");
        printf("5. Delete an Activity\n");
        printf("6. Quit\n");
        printf("Enter your choice: ");
        if (scanf("%d", &choice) != 1) {
            printf("Invalid input. Please enter a number.\n");
            while (getchar() != '\n'); // Clear input buffer
            continue;
        }

        switch (choice) {
            case 1:
                ViewActivitiesWithPoints(ID); // Call the function to display credits and points
                break;
            case 2:
                ShowActivities("CM");
                printf("Enter the code of the activity to add: ");
                scanf("%s", codeToAdd);
                while (getchar() != '\n'); // Clear input buffer
                // Add the activity to the list of chosen activities and also write it to Activity.txt
                addActivity(ID,codeToAdd);
                break;
            case 3:
                printf("Enter the code of the activity to delete from your Activity.txt file: ");
                scanf("%s", codeToDelete);
                deleteActivity(ID, codeToDelete,"CM");
                break;
            case 4:
                ShowActivities("E");
                ShowActivities("SM");
                ShowActivities("W");
                ShowActivities("CS");
                ShowActivities("PS");
                ShowActivities("PC");
                ShowActivities("CMP");
                ShowActivities("T");

                break;
            case 5:
                printf("Enter the code of the core module to delete: ");
                scanf("%s", codeToDelete);
                //deleteData(activities, &count, "coreModules.txt", codeToDelete,"CM");
                break;
            case 6:
                printf("Goodbye!\n");
                break;
            default:
                printf("Invalid choice. Please try again.\n");
        }
    } while (choice != 6);
    return 0;
}


我试图改变seek_cur中代码的位置,但我不知道问题出在哪里。

7y4bm7vi

7y4bm7vi1#

一个文件是一个字节序列。当你的文件“看起来像”:

S1,CM004;CM020;E001
S2,CM010;CM009;CM004;CM006;SM001;E001;SM002;PC007
S3,CM020;CM17;T001

字符串
然后文件中的字节,从第一行的末尾开始,是E,0,0,1,换行符,S,2,逗号,C,M,等等。当你的程序查找到第一行的末尾并使用fprintf写入“;E002”时,它不会在文件中插入这些字节;它会覆盖文件中的字节。因此,新的字节会覆盖换行符和其后的S、2、C、M和其他字节,从而破坏文件的第二行。
标准的C库例程不提供任何在文件中插入字节的方法,大多数操作系统的I/O例程也不提供这种方法,因为文件的字节存储在磁盘上的连续位置,所以基本上没有可行的方法(一些在磁盘块内物理上连续,一些在多个块之间逻辑上连续),而插入几个字节则需要阅读文件中的每个后续字节,并将所有这些字节重写到新的位置。(插入整个磁盘块可能是可行的,尽管它会给文件系统带来复杂性。)
要以您想要的方式更新文件,必须写入一个新文件,例如通过阅读输入文件并将新版本写入不同的输出文件,之后您可以移动新的输出文件以替换原始输入文件(如果需要)。
商业数据库通过用各种数据结构组织文件来避免这个问题,这样内容就不是单一的字符流,而是以块或其他单元为单位的记录。

qcuzuvrc

qcuzuvrc2#

至少有四个问题是显而易见的:

  • 一旦你在内存中更新了记录,你就需要更新整个文件。因为行的长度是可变的,你不能只搜索到行的开头。
  • 为了覆盖整个文件,您需要将所有记录加载到内存中,即使您不会更新其中的大部分记录。
  • 如果加载时记录的活动计数超过50,则需要将其重置为50。否则,输出记录时会溢出数组。
  • 当前用于阅读文件的代码似乎无法识别新行。

相关问题