2017-10-07 85 views
2

我需要一些有關C中指針數組動態分配的幫助。我試圖創建一個程序,它從用戶輸入中讀取一個單詞的句子,並將這些單詞存儲在字符數組字符串中。然後我想要將指針char *word保存到指針數組char **wordArray中的這些字中。來自用戶輸入的動態指針陣列

爲單詞創建一個動態分配的工作方法非常簡單,它從用戶輸入中逐個字符地讀取。但是,試圖使這種方法適用於指針數組更加棘手。

當前函數char **varArray顯然有缺陷,但我的想法是「當用戶輸入時,爲指針數組獲取單詞指針」。現在它有效地循環每個char c的第一個單詞。

我的問題是,我如何實現我的指針數組的動態內存分配的第二層(char **varArray())?功能如何檢測何時調用char *word()

對代碼,樣式或其他錯誤的反饋當然是讚賞的。我的水平是中級初學者。

/*CREATES AND ALLOCATES DYNAMIC VARIABLE ARRAY*/ 
#include <stdio.h> 
#include <stdlib.h> 

char **varArray(); 
char *word(); 

char **varArray() 
{ 
    char **tmp=NULL; 
    char **wordArray=NULL; 
    size_t size=0; 
    char c = EOF; 
    int words=0; 

    while(c) { 
    c=getc(stdin); 
    if (c == EOF || c == '\n') 
     c=0; 

    if (size <= words) { 
     size+=sizeof(char *); 
     tmp = realloc(wordArray,size); 

     if(tmp == NULL) { 
     free(wordArray); 
     wordArray=NULL; 
     printf("Memory allocation failed. Aborted.\n"); 
     break; 
     } 

     wordArray=tmp; 
    } 
    words++; 
    wordArray[words]= word(); 
    return wordArray; 
    } 

檢索一個單詞的方法:

/*GETS ONE WORD FROM USER INPUT*/ 
    char *word() 
{ 
    char *word=NULL, *tmp=NULL; 
    size_t size=0; 
    char c = EOF; 
    int letters=0; 

    while(c) { //reads character by character 
    c=getc(stdin); 

    if (c == EOF || c == '\n' || c==' ') //remove ' ' to read all input 
     c =0; 

    if (size <= letters) { //increase and reallocate memory 
     size = size + sizeof(char); 
     tmp = realloc(word,size); 

     if (tmp==NULL) { //check if allocation failed 
     free(word); 
     word=NULL; 
     printf("Memory allocation failed. Aborted.\n"); 
     break; 
     } 
     word= tmp; 
    } 
    letters=letters+1; 
    word[letters]=c; 

    } 
    /*ADD SENTINEL CHARACTER*/ 
    letters++; 
    size += sizeof(char); 
    word = realloc(word,size); 
    word[letters]='\n'; 
    return word; 
} 
+0

詳細信息:看起來像代碼讀取_LINE_(字符高達''\ n''),而不是一個[句子](https://開頭恩.wikipedia.org /維基/ Sentence_(語言學))。 – chux

+0

第1步:'char c = EOF;' - >'int c = EOF;' – chux

+0

正確,它讀取一行,我試圖表達它的目的:它讀取一行文字,例如一個句子,務實。 – waahlstrand

回答

1

這裏有你想要寫程序的骨架。

... 
    char* currentWord; 
    char **wordArray=NULL; 
    while ((currentWord = word()) != NULL) { 
     .... add current word to word array with realloc... 
    } 
.... 

char* word() { 
    int ch; 
    char* outputWord = NULL; 
    while ((ch = getch()) != EOF) { 
     if (... ch is a word character ...) 
      ... add ch to output word with realloc ... 
     else { 
      char* ret = outputWord; 
      outputWord = NULL; 
      return ret; 
     } 
    } 
    return NULL; 
} 

請注意兩個while循環如何完成同樣的事情。

while ((element = getNextElement()) != sentinelValue) { 
     .... process newly obtained element .... 
    } 
+0

謝謝@n.m。我欣賞概念大綱。如果我理解正確,內部while循環應該積累單詞字符,直到它指出空間爲止? 但是,我有點卡在我的舊代碼的推理。外層循環如何避免循環遍歷每個字符?如果是的話。 – waahlstrand

+0

是的,內部while循環應該像你說的那樣積累單詞字符。我的外部循環沒有看到單個字符,它在單詞上循環。由於過於複雜,你有點難以推理。你可能不想繼續它。 –

0

我現在已經成功實現了@ n.m提供的shell版本。然而,出現了另一個問題 - 因爲word()依賴於哨兵換行符\n退出,它也無法讀取最後一個字,並且不會在最後的重要時間進入循環。

我試圖實現一些if-cases,但這些當然因while-condition而失敗。另一個想法是實現一些開關情況,但我不確定這會避免while循環的糟糕嗎?

請注意,代碼幾乎沒有錯誤檢查,以儘量減少混亂。

char **wordArray() { 
    char *currentWord; 
    char **wordArray=NULL; 
    size_t size=0; 
    int i=0; 

    while((currentWord = word()) != NULL) { 
    size+=sizeof(char *); 
    wordArray=(char **) realloc(wordArray,size); 
    wordArray[i]=currentWord; 
    printf("Test - Current word: %s\n",currentWord); 
    i++; 

    } 
    return wordArray; 
} 

相關word()功能:

char *word() { 
    char ch; 
    int i=0; 
    size_t size=0; 
    char *returnWord = NULL; 
    char *outputWord = NULL; 
    char *tmp = NULL; 

    while((ch = getc(stdin)) != EOF && ch !='\n') { //&& ch !='\n' 
    if (ch != ' ') { //&& ch !='\n' 
     size += sizeof(char); 
     tmp = (char *) realloc(outputWord,size); 
     outputWord= tmp; 
     outputWord[i]=ch; 
     printf("Test1: %c\n",*(outputWord+i)); 
     i++; 
    } else { 
     printf("Test2: %s\n",outputWord); 
     returnWord=outputWord; 
     outputWord=NULL; 
     printf("Test3: %s\n",returnWord); 
     return returnWord; 
    } 
    } 
    return NULL; 
}