2014-12-02 131 views
0

我有一個函數有兩個問題,一個非常阻礙,另一個不太那樣。分配內存到char指針

我正在學習C的過程中,爲了便於閱讀,main和findWord函數應該將隨機選擇的單詞從.txt文件存儲到'wordToGuess'中。

findWord將單詞存儲到指針'wordToGuess'中就好了,但我似乎無法從函數中將其提取出來以便在main中使用它。我試着讓函數成爲'void'並直接修改函數中的'wordToGuess',並將其作爲char *返回,然後被main使用,無濟於事。在這兩種情況下,int * wordLength都沒有問題,這讓我認爲這個問題不是來自於對指針或內存分配的潛在誤解。

另一個不太重要的問題是免費(wordToFind)以某種方式崩潰了整個事情,但我並沒有對這個問題感到擔憂。

感謝您的任何幫助。

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

#define MIN 0 
#define MAX 10 
#define WORDSIZE 40 

char* findWord(char *wordToGuess , int *wordLength); 


int main(int argc , char *argv[]) 
{ 
    int *wordLength = NULL , lengthWord = 0; 
    char *wordToGuess = NULL ; 

    srand(time(NULL));            // For rand() in findWord 

    wordLength = &lengthWord; 

    printf("\n1: %s\n" , findWord(wordToGuess , wordLength);  // Sole purpose of this tester printf is to verify findWord function 

    return 0; 
} 


char* findWord(char *wordToGuess , int *wordLength) 
{ 
    int wordNumber = 0 , i = 0; 
    char word[WORDSIZE] = {0}; 

    FILE *wordFile = NULL; 

    wordFile = fopen("words.txt" , "r"); 

    if(wordFile != NULL) 
    { 
     wordNumber = (rand() % (MAX - MIN + 1)) + MIN;     // Random number to choose word form words.txt 

     for(i = 0 ; i < wordNumber ; i++) 
     { 
      while(fgetc(wordFile) != '\n');        // Move the cursor to line 'wordNumber' 
     } 

     fgets(word , WORDSIZE , wordFile);        // Get word from that line 
    } 

    *wordLength = strlen(word); 

    wordToGuess = malloc(*wordLength * sizeof(char)); 
    if(wordToGuess == NULL) 
     exit(0); 

    wordToGuess = word; 

    fclose(wordFile); 

    // free(wordToGuess); 

    return wordToGuess; 

}

+0

'wordToGuess = word;'或'strcpy()'?你想要什麼? – 2014-12-02 14:24:09

+0

首先,'strlen'不包含終止'null'字節。而真正的問題是'wordToGuess = word',你正在爲你的指針分配一個局部變量的地址。你應該使用'memcpy'。 – 2014-12-02 14:28:01

+0

我覺得這張海報比他能咀嚼的東西還要多。在您嘗試解決這種規模的練習之前,您需要使用更小的程序來學習C語言中指針和內存管理的基礎知識。 – 2014-12-02 14:55:09

回答

3

還有很多您的代碼存在問題。首要的是C通過值傳遞參數,這意味着它們在將參數傳遞給函數時被複制。所以在一個函數裏面,你只有一個拷貝,修改拷貝當然不會修改原文。

C沒有通過通過引用,但它可以通過使用指針來模擬。在你的情況下,你必須傳遞一個指針指針。這可以通過運營商地址&完成。當然,你必須修改這個函數,以便能夠將一個指針指向第一個參數。

你是,在某種程度上,與wordLength說法現在在做什麼呢,聲明它是在調用函數的指針和指向NULL,這意味着非關聯它裏面的功能將導致undefined behavior

所以有些正確的代碼會是這樣的

char* findWord(char **wordToGuess , int *wordLength); 

int main() 
{ 
    int wordLength = 0; 
    char *wordToGuess = NULL; 

    printf("%s\n", findWord(&wordToGuess, &wordLength)); 
    // Note use of address-of operator 
} 

然後在findWord功能,你當然不得不提領的指針字符串,例如

*wordToGuess = malloc(...); 

也有在findWord功能其他錯誤,就像你重新分配給指針,而不是複製它,會讓你失去你分配原來的指針,並使其指向局部變量,並且一旦函數返回將無效。而不是複製到內存。

findWord函數中的另一個主要問題是您將一個字節分配給很少。請記住,字符串包含的字符數多於strlen所報告的字符數,並且這是字符串終止符字符'\0'。當你分配內存時,你必須爲這個字符增加空間。

+0

最詳細的答案,非常感謝 – 2014-12-02 15:00:52

2

當分配

wordToGuess = word; 

您覆蓋的句柄分配的內存,有效地失去它。更糟糕的是,當您從函數返回時,您將wordToGuess指向一個超出範圍的本地數組。

你的想法,你返回分配內存的字符串是好的,但你必須複製字符串的內容,而不是字符串地址:

strcpy(wordToGuess, word); 

您必須分配一個字符比strlen更多終止空字符,這也將與strcpy複製。

如果您的系統有strdup,您可以一次性使用它來分配和複製。

2

第一你的字符串

wordToGuess = malloc(*wordLength * sizeof(char)); 

分配內存然後立即覆蓋指針

wordToGuess = word; 

這意味着:
1)wordToGuess現在指向的緩衝,這將是一旦無效作爲函數返回
2)分配的內存現在是孤立的

你可能想strcpy
你也必須爲最後的 '\ 0' 分配內存,所以malloc(1 + *wordLength)
注意sizeof(char)是1元定義

1

YOUT這裏有兩個重要的問題

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

#define MIN 0 
#define MAX 10 
#define WORDSIZE 40 

char* findWord(int *wordLength); 


int main(int argc , char *argv[]) 
{ 
    int lengthWord = 0; 
    char *wordToGuess; 

    srand(time(NULL));            // For rand() in findWord 
    wordToGuess = findWord(&lengthWord); 
    if (wordToGuess != NULL) 
    {  
     printf("\n1: %s\n" , wordToGuess);  // Sole purpose of this tester  printf is to verify findWord function 
     free(wordToGuess); // you should release resources. 
    } 
    return 0; 
} 


char* findWord(int *wordLength) // You don't need to pass wordToGuess as a parameter. 
{ 
    int wordNumber = 0 , i = 0; 
    char word[WORDSIZE] = {0}; 
    char *wordToGuess; 

    FILE *wordFile = NULL; 

    wordFile = fopen("words.txt" , "r"); 

    if(wordFile != NULL) 
    { 
     wordNumber = (rand() % (MAX - MIN + 1)) + MIN;     // Random number to choose word form words.txt 

     for(i = 0 ; i < wordNumber ; i++) 
     { 
      while(fgetc(wordFile) != '\n');        // Move the cursor to line  'wordNumber' 
     } 

     fgets(word , WORDSIZE , wordFile);        // Get word from that line 
    } 

    *wordLength = strlen(word); 

    //wordToGuess = malloc(*wordLength * sizeof(char)); // this is wrong 
    wordToGuess = malloc(*wordLength + 1); // sizeof(char) equals 1 always 
    if(wordToGuess == NULL) 
     exit(0); 

    // wordToGuess = word; this line is wrong, it should be 
    memcpy(wordToGuess, word, *wordLength); 
    wordToGuess[*wordLength] = '\0'; 

    fclose(wordFile); 

    // free(wordToGuess); 

    return wordToGuess; 
} 

你應該總是爲終止字節分配空間,你應該知道指針是如何工作的,因爲很顯然你不能從wordToGuess = word;那裏瞭解它們。

+0

沒有理由'wordToGuess'作爲參數進入 – sp2danny 2014-12-02 14:36:26

+0

@ sp2danny你是對的,我沒有看到。 – 2014-12-02 14:37:00

2

這不是內存分配問題。 您已使用{0}初始化數組,並嘗試使用「=」運算符分配它。

數組的值是在C未修改的,所以你不能只是說:

wordToGuess = word; 

你可以做這樣的事情pointer_a = pointer_b更改數組的內容,而不是,而是使用strcpy的,你的情況:

strcpy(wordToGuess, word); 

strcpy_s,它提供了相同的結果,但不會導致緩衝區overru如果您正確指定目標緩衝區的大小。

+0

'word'是數組,他不會嘗試分配給它。 – sp2danny 2014-12-02 15:09:52