2012-02-21 100 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

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