2012-09-22 53 views
1

我有一個可以在EOF上返回char *(它檢測'\n')和NULL的函數。 在main()我試圖從該行識別特定的單詞。 我用的strtok:如何將char *放入數組中,以便我可以在qsort中使用它,然後移至下一行

int main(int argc, char **argv) 
{ 
    char *line, *ptr; 
    FILE *infile; 
    FILE *outfile; 
    char **helper = NULL; 
    int strtoks = 0; 
    void *temp; 

    infile=fopen(argv[1],"r"); 
    outfile=fopen(argv[2],"w"); 

    while(((line=readline(infile))!=NULL)) 
    { 
     ptr = strtok(line, " "); 

     temp = realloc(helper, (strtoks)*sizeof(char *)); 
     if(temp == NULL) { 
      printf("Bad alloc error\n"); 
      free(helper); 
      return 0; 
     } else { 
      helper=temp; 
     } 
     while (ptr != NULL) { 
      strtoks++; 
      fputs(ptr, outfile); 
      fputc(' ', outfile); 
      ptr = strtok(NULL, " "); 
      helper[strtoks-1] = ptr; 
     } 
     /*fputs(line, outfile);*/ 
     free(line); 
    } 
    fclose(infile); 
    fclose(outfile); 
    return 0; 
} 

現在我不知道如何把每一個切分的話到一個數組(我爲此設立char ** helper),以便它可以在qsort使用像qsort(helper, strtoks, sizeof(char*), compare_string);

Ad。 2即使它行得通 - 我不知道如何清除該行,然後繼續對下一行進行排序。怎麼做?

我甚至崩潰的valgrind(與上面的代碼提交) - >「的valgrind:在‘不可能’發生的事情: 由致命的信號終止」

哪裏錯了嗎?

+0

像在代碼中那樣,函數'lineget()'和開頭的spiel或'readline()'一樣嗎? –

+1

我相當肯定彼得的意思是'readline'。 –

回答

2

最明顯的問題(可能有其他問題)是,您將重新分配helper到strtoks的行的開始位置,然後遞增strtoks並以更高的strtoks值添加到數組中。例如,在第一行中,strtoks爲0,因此temp = realloc(helper, (strtoks)*sizeof(char *));將輔助程序作爲NULL,但您嘗試將該行上的每個單詞添加到幫助程序數組中。

我建議完全不同的方法在概念上是簡單的:

char buf[1000]; // or big enough to be bigger than any word you'll encounter 
char ** helper; 
int i, numwords; 

while(!feof(infile)) { // most general way of testing if EOF is reached, since EOF 
         // is just a macro and may not be machine-independent. 
    for(i = 0; (ch = fgetc(infile)) != ' ' && ch != '\n'; i++) { 
     // get chars one at a time until we hit a space or a newline 
     buf[i] = ch; // add char to buffer 
    } 
    buf[i + 1] = '\0' // terminate with null byte 
    helper = realloc(++numwords * sizeof(char *)); // expand helper to fit one more word 
    helper[numwords - 1] = strdup(buffer) // copy current contents of buffer to the just-created element of helper 
} 

我還沒有測試,所以讓我知道,如果它是不正確,或有什麼事,你不明白。我遺漏了文件的打開和關閉以及最後的釋放(記住,在釋放幫助器之前,必須釋放幫助器的每個元素)。

+0

我同意在'strtoks'中使用'realloc()'0幾乎肯定是問題所在。 –

+0

選擇最好的,但我決定採取另一種方法。提供很多信息的簡單答案。 –

2

正如你在strtok的原型看到:

char * strtok (char * str, const char * delimiters); 

... strconststrtok實際上的作用是將空字節(\0)中的發現分隔符替換爲str,並返回指向標記開頭的指針。

每例如:

char in[] = "foo bar baz"; 
char *toks[3]; 

toks[0] = strtok(in, " "); 
toks[1] = strtok(NULL, " "); 
toks[2] = strtok(NULL, " "); 

printf("%p %s\n%p %s\n%p %s\n", toks[0], toks[0], toks[1], toks[1], 
           toks[2], toks[2]); 
printf("%p %s\n%p %s\n%p %s\n", &in[0], &in[0], &in[4], &in[4], 
           &in[8], &in[8]); 

現在看看結果:

0x7fffd537e870 foo 
0x7fffd537e874 bar 
0x7fffd537e878 baz 
0x7fffd537e870 foo 
0x7fffd537e874 bar 
0x7fffd537e878 baz 

正如你所看到的,toks[1]&in[4]指向同一個位置:原來str已被修改,並在在toks指向在str某處的所有令牌的現實。

在你的情況你的問題是你免費line

free(line); 

...在helper所有的指針無效。如果您(或qsort)在釋放line後嘗試訪問helper[0],您最終將訪問已釋放的內存。

你應該複製令牌代替,例如:

ptr = strtok(NULL, " "); 
helper[strtoks-1] = malloc(strlen(ptr) + 1); 
strcpy(helper[strtoks-1], ptr); 

顯然,你將需要釋放的helper每個元素之後(除helper本身)。

+0

謝謝!還嘗試了這個strdup,但最終決定採取另一種方法。 –

1

,因爲你應該得到一個「壞的alloc」錯誤:

char **helper = NULL; 
int strtoks = 0; 

... 

while ((line = readline(infile)) != NULL) /* Fewer, but sufficient, parentheses */ 
{ 
    ptr = strtok(line, " "); 

    temp = realloc(helper, (strtoks)*sizeof(char *)); 
    if (temp == NULL) { 
     printf("Bad alloc error\n"); 
     free(helper); 
     return 0; 
    } 

這是因爲strtoks值是零,所以你問realloc()釋放內存指向由helper(這本身一個空指針)。一個外部機會是你的圖書館在realloc(0, 0)上崩潰,它不應該,但它是一個可能被忽略的奇怪邊緣案例。另一種可能性是realloc(0, 0)返回一個非空指針,指向不允許解引用的0字節的數據。當您的代碼解除引用時,它會崩潰。 C標準允許返回NULL和返回非NULL。不要編寫崩潰的代碼,無論realloc()顯示哪種行爲。 (如果您的realloc()的執行沒有返回realloc(0, 0)的非NULL指針,那麼我很懷疑您沒有完全向我們展示設法崩潰的代碼valgrind(這是一個公平的成就 - 恭喜),因爲您不是'牛逼看到在控制程序終止,因爲它應該,如果realloc(0, 0)返回null)

你應該能夠避免這樣的問題,如果你使用:

temp = realloc(helper, (strtoks+1) * sizeof(char *)); 

不要忘記增加strtoks本身在某些時候。

+0

謝謝你指出那個嚴重錯誤背後的原因。 –

相關問題