2012-02-21 51 views
4

我有一個c函數,我想返回一個字符串。從C函數返回一個字符串

如果我打印返回之前然後我看到croc_data_0186.idx

如果我嘗試打印則返回我看到croc_data_á☼字符串字符串

任何人都可以看到我在做什麼錯?

問題功能:

char* getSegmentFileName(FILE *file, int lineLength, int lineNumber) 
{ 
    char* fileNameString; 

    fseek(file, lineNumber * lineLength, SEEK_SET); 

    char line[lineLength]; 
    fgets(line, lineLength, file); 

    char *lineElements[3]; 
    lineElements[0] = strtok(line, ":"); 
    lineElements[1] = strtok(NULL, ":"); 
    lineElements[2] = strtok(NULL, ":"); 

    fileNameString = lineElements[2]; 

    printf ("getSegmentFileName fileNameString is: %s \r\n", fileNameString); 

    return fileNameString; 
} 

調用代碼:

int indexSearch(FILE *file, char* value, int low, int high, char* segmentFileName) 
{ 
    ... 

    segmentFileName = getSegmentFileName(file, lineLength, mid); 
    printf ("indexSearch: segmentFilename3 is: %s \r\n", segmentFileName); 

    ... 
} 
+0

可能重複http://stackoverflow.com/questions/2341579/functions-returning -char-pointer) – Lundin 2012-02-21 14:49:09

+0

[從函數返回C字符串]可能的重複(https://stackoverflow.com/questions/1496313/returning-c-string-from-a-function) – 2017-12-12 14:09:41

回答

7

您正在返回一個指向本地數據的指針,該指針在函數返回後無效。您必須正確分配字符串。

這可以在調用函數中通過向被調用的函數提供緩衝區來完成,並將字符串複製到提供的緩衝區中。就像這樣:

char segmentFileName[SOME_SIZE]; 
getSegmentFileName(file, lineLength, mid, segmentFileName); 

getSegmentFileName功能:

void getSegmentFileName(FILE *file, int lineLength, int lineNumber, char *segmentFileName) 
{ 
    /* ... */ 

    strcpy(segmentFileName, fileNameString); 
} 

另一個解決辦法是分配的字符串存儲在getSegmentFileName

return strdup(fileNameString); 

但你要記住free以後的字符串。

4

這是因爲你是返回一個指針到本地。這是未定義的行爲。

strtok返回指向line字符數組的指針。您將該指針放入fileNameString,然後返回給調用者。此時line內的內存變爲無效:任何垃圾都可寫入其中。

爲避免此問題,您應該爲返回值傳遞一個緩衝區/長度對,或者在返回的字符串上使用strdup()。在後面的情況下,你應該記住釋放分配給返回字符串的內存strdup()

對於相關主題,您應該避免使用strtok,因爲它不可重入,並且會在多線程環境中引發問題。考慮改用strtok_r

+0

你很快,Johhny,如此快速 – 2012-02-21 14:17:15

+0

「返回值的緩衝區/長度對」 - 在這種情況下尤其直截了當,因爲'lineLength'大小的緩衝區足夠大。當呼叫者事先不知道一個好的上限時,它更加煩瑣。 – 2012-02-21 14:24:23

3

您正在返回一個指向當函數返回時不再存在的局部變量的指針。你必須爲它存儲malloc並返回它。或者,你可以讓調用者通過一個緩衝區來填充。在任何情況下,調用者稍後都要對內存負責。

+0

以及'free'也是'malloc'的內存。 – 2012-02-21 14:24:27

0

行是一個局部變量,在函數結束時被刪除。

您應該使用malloc或strcpy將它作爲參數傳遞給字符串指針。

2

這是因爲你返回無效指針。

char* fileNameString; 

只是一個指針。

char line[lineLength]; 

住在棧上,並填寫fgets()調用。

char *lineElements[3]; 
    lineElements[0] = strtok(line, ":"); 
    lineElements[1] = strtok(NULL, ":"); 
    lineElements[2] = strtok(NULL, ":"); 

這裏您將指針存儲在該數組中。其中之一是

fileNameString = lineElements[2]; 

return fileNameString; 

之後。

的解決辦法是在函數內部

  • 或者malloc的足夠的空間和您的字符串複製到新的內存塊或

  • 有來電提供您將數據寫入到緩衝區中。

2

問題是你正在返回一個堆棧變量,當函數返回時會丟失。一種方法是在函數參數中使用char * arg,並有足夠的保留空間,並使用它來存儲所有信息並將其返回。

0

有3種方法可以解決這個

1)製作 'fileNameString' 靜態

static char fileNameString[100]; 

2)功能 'getSegmentFileName' 應該通過一個字符緩衝區 'segmentFileName' 給被叫方的來電即

getSegmentFileName(file, lineLength, mid, segmentFileName); 

在這種情況下,你需要改變函數的參數

char* getSegmentFileName(FILE *file, int lineLength, int lineNumber, char *segmentFileName) { 

    ..... 

    strcpy(segmentFileName, fileNameString); // copying the local variable 'fileNameString' to the function argument 
         // so that it wont be lost when the function is exited. 

    return fileNameString; // there is no need to return anything and you can make this function void 
        // in order not to alter ur program I am putting the return also 
    } 

3)通過這種方式,您可以爲fileNameString動態分配內存。動態內存分配在堆中,並且函數返回時不會丟失。所以你可以放心地在indexSearch函數中使用它。

char* getSegmentFileName(FILE *file, int lineLength, int lineNumber) 
{ 
    char *fileNameString = (char *)malloc(100 * sizeof(char)); // allocate memory for 100 character string 

    ..... 
    return fileNameString; 
} 

在這種情況下,您將需要釋放使用fileNameString指向的內存free

的[返回功能,字符指針(