2016-12-23 34 views
0

我正在写一个简单的银行应用程序c 它将信息保存在一个文件中。 我想在每次应用程序运行时加载文件,并将文件中的信息添加到结构中,为此,我写了两个函数,称为“loadfile”和“分配”这个bug是关于什么的?结构,指针,动态内存分配,C

在函数“loadfile “如果我对注释行取消注释,操作系统会在我的脸上抛出”停止工作“:|

你能帮我吗? 当我在“loadfile”中使用(acc + i)时,出现错误。 是否有语法问题? :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; 
} 
+2

[为什么 - 是 - 同时-FEOF文件,总是出错(http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – LPs

+2

使用全局'account * acc;'IE'int allocate(account * acc){' - >'int allocate(void){' – BLUEPIXY

+0

不要强制返回void *'函数! – Stargateur

回答

-1

我无法解释你所有的问题。这将需要几个小时。我希望这个代码能够自我描述。如果您需要帮助,请在评论中询问我。

#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); 
} 
+0

不是downvoter,但是return realloc(account,sizeof * account * i)的范围是什么;'??? – LPs

+0

注意:如果'realloc'失败,使用'realloc'将其返回值反映到原始指针可能会泄漏先前分配的内存。 – LPs

+0

@LPs我虽然'realloc'免费,如果它无法找到内存,我会解决这个问题。我从来没有在我的程序中使用'realloc'。我返回'realloc'(这个不能失败,不是吗?),告诉我不使用超出我分配的内存http://stackoverflow.com/questions/7078019/using-realloc-to-shrink -THE分配内存。 – Stargateur

1

发布的代码有很多问题。目前还不清楚单独的分配函数是如何有用的,并且不建议使用文件范围变量acc。这里我看不到使用realloc()的意思,因为分配只能完成一次。如果确实使用realloc(),则应将结果存储在临时指针中,因为如果存在分配错误,该函数可以返回NULL指针。如果直接指定要重新分配的指针,会导致内存泄漏。我已经重写了代码来说明一些修补程序,试图维护原始代码的一般结构。

您应该检查您调用的函数的返回值。 realloc()malloc()返回一个指向分配内存的指针,或者在分配错误时返回一个NULL指针。你应该检查这个值并处理结果。 scanf()函数返回成功分配的数量。您应该检查此值以验证输入是否如预期。用feof()来控制一个循环是almost always a bad idea,因为这个函数依赖于文件结束指示符的设置,并且这个指示器只在I/O操作失败时才被设置。

在下面的程序中,fgets()用于从文件读取一行输入到缓冲区中,并且sscanf()用于从缓冲区中提取输入数据。在分配阶段,EOF或空行表示数据结束。这里没有解析,只有一些行。对于每行,空间分配为account。请注意,代码检查打开和关闭文件时出错,以及分配错误。

loadfile()函数再次使用fgets()将输入行读入buffer,然后使用sscanf()扫描缓冲区。请注意使用字符串的宽度说明符。这些数据比他们读入的数组的大小要小一些,以便为位于字符串末尾的'\0'留出空间sscanf()。另请注意,如果分配的分配少于4个,程序exit将显示错误消息。如果对临时变量的分配成功,则使用该数据更新account

该代码有很多方法可以改进(最明显的是通过摆脱全局变量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; 
} 
相关问题