更新文件中的记录文件

时间:2015-01-03 18:22:28

标签: c file

请帮帮我。到目前为止这是我的代码。删除记录功能不起作用,有人可以通过以下条件帮助更新记录功能:

- 要求用户输入玩家姓名 - 要求用户输入球员得分 - 要求用户输入玩家等级 - 如果列表中不存在播放器名称,则显示消息“未找到[播放器名称]的名称!”

非常感谢。

#include <stdio.h>
#include <string.h>

struct Player {
    char name[50];
    int score;
    int level;
};
struct Player data[50];
FILE *ptr;
FILE *ptr2;

int fileSize()
{
    int lSize;
    int end;
    ptr = fopen("text.txt", "r");
    lSize = ftell (ptr);
    fseek (ptr, 0, SEEK_END);
    end = ftell (ptr);
    fseek (ptr, lSize, SEEK_SET);

    return end;
}

int getNoOfRecords()
{
    return (fileSize()/(sizeof(struct Player)));
}

void deletePlayerRecord()
{
    char name[50];
    int counter=0, i=0;

    ptr2 = fopen("text2.txt","a");
    int records = getNoOfRecords();

    ptr = fopen("text.txt","a+");
    do {
        printf("Input player name[1..10]: ");
        scanf("%[^\n]s", name);
        fflush(stdin);
    } while (strlen(name)<1 || strlen(name)>10);
    while(counter!=records)
    {
        fread(&data,sizeof(struct Player),1,ptr);
        if(strcmp(data[i].name,name)==0)
        {

        }
        else
        {
            fwrite(&data,sizeof(struct Player),1,ptr2);
        }
        counter++;
    }
    fclose(ptr);
    fclose(ptr2);
    remove("text.txt");
    rename("text2.txt","text.txt");
    printf("\n%s successfully deleted.\n\n", name);
    printf("Press Enter to continue....\n\n");
    getchar();
}

void updatePlayerRecord()
{
    char name[50];
    int counter=0, i=0;
    int records = getNoOfRecords();
    ptr = fopen("text.txt","a+");
    do {
        printf("Input player name[1..10]: ");
        scanf("%[^\n]s", name);
        fflush(stdin);
    } while (strlen(name)<1 || strlen(name)>10);
    if(counter!=records)
    {
        fread(&data,sizeof(struct Player),1,ptr);
        if(strcmp(data[i].name,name)==0)
        {

        }
        counter++;
    }
    printf("\nScore and Level successfully updated.\n\n");
    printf("Press Enter to continue....\n\n");
    getchar();
}

void addPlayerRecord(){
    int i=0;
    do {
        printf("Input player name[1..10]: ");
        scanf("%[^\n]s", data[i].name);
        fflush(stdin);
    } while (strlen(data[i].name)<1 || strlen(data[i].name)>10);
    fflush(stdin);
    getchar();
    data[i].score=0;
    data[i].level=0;

    ptr = fopen("text.txt", "a");
    printf("\n");
    fprintf(ptr, "\r\n%s#%d#%d", data[i].name, data[i].score, data[i].level);
    fclose(ptr);

    printf("\nData successfully added.\n\n");
    printf("Press Enter to continue....\n\n");
    getchar();
}


void viewPlayerRecord(){
    int i=0;
    ptr = fopen("text.txt", "r");
    printf("Player Name\t\t|Average Score\t|Number of Playing\n");
    printf("=======================================================\n");
    while(fscanf(ptr, "%[^#]#%d#%d\n", data[i].name, &data[i].score, &data[i].level)!=EOF)
    {
        printf("%s\t\t\t|%d\t\t\t\t|%d\n", data[i].name, data[i].score, data[i].level);
        i++;
    }
    fclose(ptr);
}

int main() {
    int choice;
    do{
        printf("Score Record Dota Player\n");
        printf("========================\n");
        printf("1. View Record\n");
        printf("2. Update Player Record\n");
        printf("3. Add New Player\n");
        printf("4. Delete Player\n");
        printf("5. Save and Exit\n\n");
        do {
            printf("Input your choice[1..5]: ");
            scanf("%d", &choice);
            fflush(stdin);
            getchar();
        } while (choice < 1 || choice > 5);

        switch (choice) {
            case 1:
                viewPlayerRecord();
                break;

            case 2:
                updatePlayerRecord();
                break;

            case 3:
                addPlayerRecord();
                break;

            case 4:
                deletePlayerRecord();
                break;
        }
    } while(choice!=5);
    return 0;
}

1 个答案:

答案 0 :(得分:0)

您的代码存在许多问题:

  • 每个操作都适用于数据库文件。这可能是一个很好的设计,但更通常的方法是在启动时将数据库加载到内存中,即填充data然后再进行此操作。退出程序时,您将提交对数据库文件的所有更改。 (你的选项5命名为&#34;保存并退出&#34;,但实际上是一个空操作。该名称暗示了概述的方法。)

  • 您应该决定数据库是二进制文件还是文本文件。在添加和显示记录时使用fprintffscanf,它们用于文本文件,但是使用fwritefread,它们用于二进制文件,更新和删除记录时。在我看来,二进制访问更容易一些,因为你只需要存储和检索固定大小的块,即sizeof(struct Player)。文本文件更加用户友好,因为它们可以在文本编辑器中显示和修改,但必须进行解析并需要更高级的错误处理。

  • 您的fileSize()仅适用于二进制文件,但目前只编写文本文件。通常最好使用文件函数的返回值来确定读取或写入是否成功。

  • 当数据库文件不存在时,您的视图功能将崩溃。检查文件是否存在以及格式是否正确。

  • 目前,您仅将data用作临时空间。您访问data[i],但i在整个代码中为零。

有效的纠正删除功能是:

void deletePlayerRecord()
{
    struct Player p;
    char name[50];
    int del = 0;

    ptr2 = fopen("text2.txt", "w");
    ptr = fopen("text.txt", "r");

    do {
        printf("Input player name[1..10]: ");
        scanf("%[^\n]s", name);
        fflush(stdin);
    } while (strlen(name)<1 || strlen(name)>10);

    while (fscanf(ptr, "%[^#]#%d#%d\n", p.name, &p.score, &p.level) == 3) {
        if(strcmp(p.name, name) == 0) {
            printf("\n%s successfully deleted.\n\n", name);
            del++;
        } else {
            fprintf(ptr2, "%s#%d#%d\n", p.name, p.score, p.level);
        }
    }
    fclose(ptr);
    fclose(ptr2);
    remove("text.txt");
    rename("text2.txt", "text.txt");    

    printf("%d character(s) deleted\n\n", del);
}

此代码仍有许多缺点:

  • 未检查fopen的成功。

  • fscanffprintf格式必须从视图中逐字复制并添加记录选项。那种糟糕的风格。您应该编写readPlayerwritePlayer函数。

  • 输入代码也一样。编写执行错误检查的前端函数,这样您就不必一遍又一遍地重复整个代码。这使得代码难以阅读并且也容易出错。