0

我已经用 C 语言编写数据库有一段时间了,昨天我遇到了一个我无法处理的错误。情况是,当我在编写从.txt 函数加载时,程序从.txt 读取数据后出现了一些错误。(它是“84683-3478-”而不是“1993-5-13”)我试图改变某事然后发生了废话,从那时起我一直收到这样的错误:

“分段错误”-> 在 Linux 上“调用堆栈内存”-> 在 Windows 上

我真的不知道问题出在哪里,因为我没有改变太多(放置文本的方式),但是发生了废话。我正在为您粘贴该功能。你能帮忙吗?

void load(struct player *main)
{
    int bad;
    struct player *act, *prev;    // act- actual prev - previous
    FILE *plik;
    char a;
    char text[l];                 // l=15;
    if((plik = fopen("savings.txt", "r")) == NULL)
    {
        printf("No savings\n");
        return;
    }
    if(fgets(text, l, plik) == NULL)
    {
        printf("No saved things\n");
        return;
    }
    printf("These are your savings\n");
    do
    {
        printf("%s", text);
    }while(fgets(text, l, plik) != NULL);
    fclose(plik);
    printf("\nType the name of the file you want to load (with .txt) \n");
    do
    {
        gets(text);         // here program stops, no matter if the name is right or not
        char *text = (char*) malloc(30);
        while (getchar()!='\n')
            continue;
        strcat(text, ".txt");
        printf("%s", *text);
        if((plik = fopen(text, "r")) == NULL)
        {
            printf("There is no such file, type once again \n");
            bad=1;
        }
        else bad=0;
    }while(bad);
    act = main->next;
    while(act != NULL)              //cleaning the actual data base
    {
        prev = act;
        act = act->next;
        free(prev);
    }
    nr_of_players = 0;
    act = main;
    while(fscanf(plik, "%s", act->name)!=0)
    {
        fscanf(plik, "%s", biez->surname);
        fscanf(plik, "%d", &biez->date_y);
        fscanf(plik, "%d", &biez->date_m);
        fscanf(plik, "%d", &biez->date_d);
        fscanf(plik, "%s", biez->position);
        fscanf(plik, "%c", &a);
        fscanf(plik, "%d", &biez->nr_cart);
        fscanf(plik, "%d", &biez->salary);
        fscanf(plik, "%d", &biez->matches);
        act->id = ++nr_of_players;
        act->next = (struct player*) malloc(sizeof(struct player));
        prev = act;
        act = act->next;
    }
    free(act);
    prev->next = NULL;
    fclose(plik);
}
4

4 回答 4

2

代码审查

声明变量时初始化所有变量

void load(struct player *main)
{
    int bad = 0;
    struct player *act = NULL, *prev =  NULL;    
    FILE *plik = NULL;
    char a = '\0';

不要使用“l”作为常数,根据使用的字体很难区分 l 和 1。

    char text[l] = {0};                 // l=15;


    if((plik = fopen("savings.txt", "r")) == NULL)
    {
        printf("No savings\n");
        return;
    }

更喜欢在这里使用 sizeof(text) 而不是使用“l”

    if(fgets(text, sizeof(text), plik) == NULL)

    printf("\nType the name of the file you want to load (with .txt) \n");
    do
    {
        // here if user puts his elbow on the keyb it crashes the 
        // program use fgets(buffer,sizeof(buffer),stdin) instead.
        gets(text); 

永远不要在另一个范围内隐藏变量名,使用新的变量名

        char *mytext = malloc(30); // in C don´t cast malloc 

下面你在“文本”上执行 strcat 但是你只是 malloc:ed 它所以缓冲区中可能有任何东西,你应该在执行 strcat() 或使用 strcpy(_s) 之前清除缓冲区/或者它可能只是一个错字?

        strcat(text, ".txt");

C 中的字符串是一个字符序列,%s 告诉 printf 期望以 \0 结尾的字符串的地址,但是*text如果你给它一个字符值,那将不会很好地结束。

        printf("%s", *text);

尽可能使用 {} 是件好事,而不仅仅是有时

        if((plik = fopen(text, "r")) == NULL)
        {
            printf("There is no such file, type once again \n");
            bad=1;
        }
        else bad=0;  
    }while(bad);

在使用它之前检查“main”是否指向正确的东西。

    if ( main != NULL )
    {
      act = main->next;
      while(act != NULL)
      {
        prev = act;
        act = act->next;
        free(prev);
      }
    ...

在这里,我建议您改为使用 fgets() 读取数据,并使用 sscanf() 解析数据,因为这样做很脆弱。

    nr_of_players = 0;
    act = main;
    while(fscanf(plik, "%s", act->name)!=0)
    {
        fscanf(plik, "%s", biez->surname);
        fscanf(plik, "%d", &biez->date_y);
        fscanf(plik, "%d", &biez->date_m);
        fscanf(plik, "%d", &biez->date_d);
        fscanf(plik, "%s", biez->position);
        fscanf(plik, "%c", &a);
        fscanf(plik, "%d", &biez->nr_cart);
        fscanf(plik, "%d", &biez->salary);
        fscanf(plik, "%d", &biez->matches);
        act->id = ++nr_of_players;

这是不寻常的,通常当您找到要放入的东西时分配,而不是为可能有更多要放入的情况分配。

        act->next = malloc(sizeof(struct player));
        prev = act;
        act = act->next;
    }
于 2013-01-09T09:07:32.087 回答
1

你正在做:

char *text = (char*) malloc(30);
while (getchar()!='\n')
  continue;
strcat(text, ".txt");
printf("%s", *text);

最后一个 printf 应该是:

printf("%s", text);
于 2013-01-09T08:30:46.803 回答
0
char text[l];                 // l=15;
 .... deleted a bunch of lines ....
do
{
gets(text);         // here program stops, no matter if the name is right or not
char *text = (char*) malloc(30);
while (getchar()!='\n')
  continue;
strcat(text, ".txt");

请注意,text[l]用于gets()- 和 gets 是一个不好的函数,因为它不会阻止完全覆盖输入缓冲区的末尾。它只会崩溃(或做其他意想不到的事情)。

而不是gets(),使用fgets(stdin, ...).

代码也没有意义。

你为什么要分配一个新变量text,它会影响text你刚刚读到的东西

如果你想要一个 30 字节的字符串,只需首先创建一个 30 字节的字符串,而不是 15 字节。

另外,请,请,请不要使用称为l或的变量/常量O- 除非您进入“混淆 C 竞赛”。它们看起来太像数字一和零了。

于 2013-01-09T08:40:40.717 回答
0

char *text = (char*) malloc(30);

你为什么要命名它text,试试另一个名字,你已经text在函数开始时声明了。

char text[l];

于 2013-01-09T08:40:43.583 回答