2012-04-02 16 views
2

我有一個結構如何使用malloc和realloc在C中讀取和存儲任意長度的字符串?

typedef struct store 
{ 
    char name[11]; 
    int age; 
} store; 

和主函數(下面是它的一部分):

int main() 
{ 
    int i=0; 
    int inputs; 
    char line[100]; 
    char name[11]; 
    char command[11]; 
    store read[3000]; 

    while(i < 3000 && gets(line) != NULL) 
    { 
     int tempage; 
     inputs = sscanf(line, "%10s %10s %d", command, name, &tempage); 
     if (inputs == 3) 
     { 
      if (strcmp(command, "register") == 0) 
      { 
      strncpy(read[i].name, name,10); 
      read[i].age = tempage; 
      i++; 
      .... 

我需要修改它,以便它可以讀取一行任意長度的,並存儲該行的名稱也是使用malloc和realloc的任意長度的字符串。

我該如何解決這個問題?

+5

首先,**從不使用gets()**。決不。 – 2012-04-02 19:27:29

+3

'寄存器讀取[3000]'嚇死我了! – 2012-04-02 19:29:20

+0

@Greg好的,我會用fgets() – Draygon 2012-04-02 19:32:35

回答

2

你需要做的是閱讀以較小的增量行,你去調整你的緩衝區什麼。

作爲一個例子(未測試,而不是意是特別優雅,只是一個例子):

char *readline(FILE *f) 
{ 
    char *buf = NULL; 
    size_t bufsz = 0, len = 0; 
    int keep_going = 1; 

    while (keep_going) 
    { 
     int c = fgetc(f); 
     if (c == EOF || c == '\n') 
     { 
     c = 0;    // we'll add zero terminator 
     keep_going = 0; // and terminate the loop afterwards 
     } 

     if (bufsz == len) 
     { 
     // time to resize the buffer. 
     // 
     void *newbuf = NULL; 
     if (!buf) 
     { 
      bufsz = 512; // some arbitrary starting size. 
      newbuf = malloc(bufsz); 
     } 
     else 
     { 
      bufsz *= 2; // issue - ideally you'd check for overflow here. 
      newbuf = realloc(buf, bufsz); 
     } 

     if (!newbuf) 
     { 
      // Allocation failure. Free old buffer (if any) and bail. 
      // 
      free(buf); 
      buf = NULL; 
      break; 
     } 

     buf = newbuf; 
     } 

     buf[len++] = c; 
    } 

    return buf; 
} 
+0

我想我明白代碼的作用。我必須用類似的代碼替換gets/fgets和sscanf,對吧? – Draygon 2012-04-02 20:01:07

+1

@Draygon用'line = readline(stdin)'替換你的'fgets'並確保1.檢查'NULL'爲'NULL',以便在失敗時不會崩潰,並且2.每次調用'readline'後當你完成它時,在緩衝區中調用'free'。你可以在返回的字符串上繼續使用'sscanf'。 – asveikau 2012-04-02 20:05:12

+0

雖然......如果您打算在'%s'上使用'sscanf',您需要確保參數的分配足夠大以保存結果。一個簡單的方法是將參數的分配大小設置爲'strlen(line)+ 1'。 (總的來說,我會說'sscanf'沒有一個很好的界面......) – asveikau 2012-04-02 20:11:43

1

將名稱[11]更改爲* name; 每次使用malloc爲其分配內存。

順便說一句,register是C語言的關鍵字。你不能像你那樣使用它!

+0

哦,我用商店而不是註冊在我目前的代碼,但我想如果會更清楚如果我使用註冊。 – Draygon 2012-04-02 19:36:20

+0

我不知道如何存儲無限長的線 – Draygon 2012-04-02 19:36:55

+0

我不想給代碼;-)從這個鏈接學習malloc,然後你可以很容易地自己做。或搜索谷歌,看看內存如何動態分配給結構。 – 2012-04-02 19:41:23

0

我想你要找的是什麼:

char* name; 

name = (char*)malloc(sizeof(char)); 
+1

首先,如果您使用的是C(而不是C++),那麼您絕對不會明確地拋棄void *。其次,我不認爲他想分配只有1個字符.... – asveikau 2012-04-02 19:51:37

+0

而且'sizeof(char)'保證總是一個...... – Joe 2012-04-02 20:02:24

0

這種替代方法類似於@ asveikau的,但通過複製節約使用的malloc()的在堆棧上。

請不要將此用於作業答案。

#include <string.h> 
#include <stdlib.h> 
#include <stdio.h> 
char * slurponeline(FILE *f, int s) { 
const int size = 4096; 
char buffer[size]; 
char * r; 
int c,i=0; 
while(i<size && (c = fgetc(f),c>=0 && c!='\n')) buffer[i++]=c; 
if (0 == s && 0 == i) return 0; 
r = (size==i)? slurponeline(f,s+size):malloc(s+i); 
memcpy(r+s,buffer,i); 
return r; 
} 
int main(int argc, char ** argv) { 
FILE * f = fopen(argc>1?argv[1]:"a.out","rb"); 
char * a,*command,*commandend,*name,*nameend; 
int age; 
while (a = slurponeline(f,0)) { 
    char * p = a; 
    while (*p && *p == ' ') ++p; // skip blanks. 
    command = p; 
    while (*p && *p != ' ') ++p; // skip non-blanks. 
    commandend = p; 
    while (*p && *p == ' ') ++p; // skip blanks. 
    name = p; 
    while (*p && *p != ' ') ++p; // skip non-blanks. 
    nameend = p; 
    while (*p && *p == ' ') ++p; // skip blanks. 
    age = atoi(p); 
    *commandend=0; 
    *nameend=0; 
    printf("command: %s, name: %s, age: %d\n",command,name,age); 
    free(a); 
} 
} 
相關問題