简体   繁体   English

这个错误是关于什么的? 结构,指针,动态内存分配,C

[英]What is this bug about? Structs, Pointers, Dynamic Memory Allocation , C

I'm writing a simple banking application in c It saves the information in a file. 我正在用c编写一个简单的银行应用程序,它将信息保存在文件中。 I want to load the file each time the app runs, and add the information from the file to the struct, for this purpose, I have written two functions called "loadfile" and "allocate" 我想每次应用程序运行时加载文件,并将文件中的信息添加到结构中,为此,我编写了两个函数,分别称为“ loadfile”和“ allocate”

In the function "loadfile" if I un-comment the comment lines, the OS throws a "stopped working" in my face :| 在函数“ loadfile”中,如果我取消注释行,则操作系统会在我的脸上抛出“停止工作”信息:|

Can you help me with it ? 你能帮我吗? when I use (acc+i) in the "loadfile", the error shows up. 当我在“ loadfile”中使用(acc + i)时,显示错误。 Is there a syntax problem? 有语法问题吗? :o thanks :o谢谢

typedef struct {
    char name[20];
    int id;
    int balance;
    char branch[10];
} account;

account *acc;

int allocate ( account *acc )  {
    int num = 0 ;
    char tempname[20],tempbranch[10];
    int tempid = -1 ,tempbalance;
    FILE *file;
    file = fopen("D://bank.txt","r");
    while ( !feof(file) ) {
        fscanf(file,"%s %d %d %s ",tempname, &tempid, &tempbalance, tempbranch);
        if (tempid != -1)
            num++;
    }
    acc = ( account *) realloc ( acc, num * sizeof(account) );
    fclose(file);
    printf(" num in allocate function : %d",num);
    return num;
}

int loadfile (account *acc) {
    int num = allocate(acc);
    char tempname[20],tempbranch[10];
    int tempid ,tempbalance;
    if ( num != 0 ) {
        int i = 0 ;
        FILE *file;
        file = fopen("D:\\bank.txt","r+");
        for ( i = 0 ; !feof(file) && i < num ; i++ ) {
            fscanf(file,"%s ",tempname );
            fscanf(file,"%d ",&tempid );
            fscanf(file,"%d ",&tempbalance );
            fscanf(file,"%s ",tempbranch );
            printf("\n i is %d \n",i);
            /* strcpy( ((acc+i)->name) , tempname);
            (acc+i)->id = tempid;
            (acc+i)->balance = tempbalance;
            strcpy( ((acc+i)->branch) , tempbranch); */
        }
        fclose(file);
    }
    return num;
}

There are a lot of issues with the posted code. 发布的代码存在很多问题。 It is unclear how a separate allocation function is helpful, and the use of the file-scope variable acc is not advisable. 尚不清楚单独的分配功能如何发挥作用,建议不要使用文件范围变量acc I see no point in using realloc() here, since allocation is done only once. 我认为在这里使用realloc()没有意义,因为分配仅完成一次。 If you do use realloc() , you should store the result in a temporary pointer, because the function can return a NULL pointer if there is an allocation error. 如果确实使用realloc() ,则应将结果存储在临时指针中,因为如果发生分配错误,该函数可以返回NULL指针。 This leads to a memory leak if you assign directly to the pointer that you are reallocating from. 如果直接分配给您要重新分配的指针,则会导致内存泄漏。 I have rewritten the code to illustrate some fixes, trying to maintain the general structure of the original code. 我重写了代码以说明一些修复程序,试图维护原始代码的一般结构。

You should check the return values of the functions that you call. 您应该检查所调用函数的返回值。 realloc() and malloc() return a pointer to the allocated memory, or a NULL pointer in the event of an allocation error. realloc()malloc()返回指向已分配内存的指针,或者在分配错误的情况下返回NULL指针。 You should check this value and handle the result. 您应该检查该值并处理结果。 The scanf() functions return the number of successful assignments made. scanf()函数返回成功进行分配的次数。 You should check this value to verify that input is as expected. 您应该检查该值以验证输入是否符合预期。 It is almost always a bad idea to control a loop with feof() , because this function relies upon the end-of-file indicator being set, and this indicator is only set when an I/O operation has failed. feof()控制循环几乎总是一个坏主意 ,因为此函数依赖于设置的文件结束指示符,并且仅当I / O操作失败时才设置该指示符。

In the program below, fgets() is used to read a line of input from the file into a buffer, and sscanf() is used to extract the input data from the buffer. 在下面的程序中, fgets()用于将文件中的一行输入读取到缓冲区中,而sscanf()用于从缓冲区中提取输入数据。 In the allocation phase, EOF or an empty line signals the end of the data. 在分配阶段, EOF或空行表示数据结束。 No parsing is done here, only a count of lines. 此处不进行任何解析,仅计算行数。 For each line, space is allocated for an account . 对于每一行,为一个account分配空间。 Note that the code checks for errors on opening and closing the file, as well as for an allocation error. 请注意,该代码检查打开和关闭文件时的错误以及分配错误。

The loadfile() function again uses fgets() to read a line of input into buffer , and then uses sscanf() to scan the buffer. loadfile()函数再次使用fgets()将一行输入读取到buffer ,然后使用sscanf()来扫描缓冲区。 Note the use of width specifiers for the strings. 注意对字符串使用宽度说明符。 These are one less than the size of the arrays that they read into, to leave space for the '\\0' placed at the end of the strings by sscanf() . 它们比它们读入的数组的大小小1,以通过sscanf()在字符串末尾留出'\\0'空间。 Also note that in the event that fewer than 4 assignments are made, the program exit s with an error message. 还要注意,如果分配的少于4个,程序将exit并显示一条错误消息。 If the assignments to the temporary variables were successful, the account is updated with the data. 如果对临时变量的分配成功,则使用数据更新account

There are many ways that this code could be improved (most obviously by getting rid of the global variable acc ), but this should provide you with a good starting point. 有许多方法可以改进此代码(最明显的是,它摆脱了全局变量acc ),但这应该为您提供一个良好的起点。

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

typedef struct {
    char name[20];
    int id;
    int balance;
    char branch[10];
} account;

account *acc = NULL;

int allocate(void)
{
    int num = 0 ;
    char buffer[1000];
    FILE *file;

    file = fopen("D://bank.txt","r");
    if (file == NULL) {
        fprintf(stderr, "Unable to open file in allocate()\n");
        exit(EXIT_FAILURE);
    }

    while (fgets(buffer, sizeof(buffer), file) != NULL &&
           buffer[0] != '\n') {
        num++;
    }

    acc = malloc(num * sizeof(*acc));
    if (acc == NULL) {
        fprintf(stderr, "Allocation error in allocate()\n");
        exit(EXIT_FAILURE);
    }

    if (fclose(file) != 0) {
        fprintf(stderr, "Unable to close file in allocate()\n");
        exit(EXIT_FAILURE);
    }

    printf(" num in allocate function : %d\n",num);
    return num;
}

int loadfile(void)
{
    int num = allocate();
    char buffer[1000], tempname[20],tempbranch[10];
    int tempid ,tempbalance;
    if ( num != 0 ) {
        int i = 0 ;
        FILE *file;

        file = fopen("D://bank.txt","r+");
        if (file == NULL) {
            fprintf(stderr, "Unable to open file in loadfile()\n");
            exit(EXIT_FAILURE);
        }

        while (fgets(buffer, sizeof(buffer), file) != NULL
               && buffer[0] != '\n') {
            if (sscanf(buffer, "%19s %d %d %9s",
                       tempname, &tempid, &tempbalance, tempbranch) != 4) {
                fprintf(stderr, "%d: Malformed input data\n", i);
                exit(EXIT_FAILURE);
            }

            strcpy(acc[i].name, tempname);
            acc[i].id = tempid;
            acc[i].balance = tempbalance;
            strcpy(acc[i].branch, tempbranch);
            ++i;
        }

        if (fclose(file) != 0) {
            fprintf(stderr, "Unable to open file in loadfile()\n");
            exit(EXIT_FAILURE);
        }
    }

    return num;
}

int main(void)
{
    int num = loadfile();
    for (int i = 0; i < num; i++) {
        printf("%s %d %d %s\n",
               acc[i].name, acc[i].id, acc[i].balance, acc[i].branch);
    }

    return 0;
}

I can't explain all your problems. 我无法解释您所有的问题。 It will take me hours. 我要几个小时 I hope this code will be self-describing. 我希望这段代码可以自我描述。 Ask me in a comment if you need some help. 在评论中问我是否需要帮助。

#include <stdlib.h>
#include <stdio.h>

typedef struct {
  char name[20];
  int id;
  int balance;
  char branch[10];
} account_t;

static account_t *parse_account_file(FILE *file, size_t *size) {
  if (file == NULL || size == NULL) {
    return NULL;
  }

  size_t i = 0;
  account_t *account = malloc(sizeof *account);
  if (account == NULL) {
    return NULL;
  }

  int ret;
  while (
      (ret = fscanf(file, "%19s %d %d %9s\n", account[i].name, &account[i].id,
                    &account[i].balance, account[i].branch)) == 4) {
    account_t *old = account;
    account = realloc(account, sizeof *account * (++i + 1));
    if (account == NULL) {
      free(old);
      return NULL;
    }
  }

  if (ret == EOF) {
    if (ferror(file)) {
      perror("parse_account_file()");
    } else {
      *size = i;
      account_t *old = account;
      account = realloc(account, sizeof *account * i);
      if (account == NULL) {
        return old;
      }
      return account;
    }
  } else {
    fprintf(stderr, "error parsing\n");
  }

  free(account);

  return NULL;
}

int main(void) {
  char const *name = "D:\\bank.txt";
  FILE *file = stdin;

  size_t size;
  account_t *account = parse_account_file(file, &size);
  fclose(file);
  if (account == NULL) {
    return 1;
  }

  for (size_t i = 0; i < size; i++) {
    printf("%s %d %d %s\n", account[i].name, account[i].id, account[i].balance,
           account[i].branch);
  }

  free(account);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM