从C中的函数返回一个字符串

时间:2012-02-21 14:11:00

标签: c string pointers

我有一个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);

    ...
}

7 个答案:

答案 0 :(得分: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字符串。

答案 1 :(得分:4)

这是因为你要返回一个指向local的指针。这是未定义的行为。

strtok返回指向line字符数组的指针。您将该指针放入fileNameString,然后返回给调用者。此时line内的内存变为无效:可以将任何垃圾写入其中。

要避免此问题,您应该为返回值传递缓冲区/长度对,或者对要返回的字符串使用strdup()。在后一种情况下,您应该记住通过strdup()释放为返回的字符串分配的内存。

在相关主题上,您应该避免使用strtok,因为它不是可重入的,并且会在多线程环境中引起问题。请考虑改为使用strtok_r

答案 2 :(得分:3)

当函数返回时,您将返回指向不再存在的局部变量的指针。你必须malloc存储并返回它。或者,您可以让调用者在缓冲区中传递以进行填充。在任何情况下,调用者都要负责free以后的内存。

答案 3 :(得分: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足够的空间并将字符串复制到新的内存块或

  • 让调用者提供您将数据写入的缓冲区。

答案 4 :(得分:2)

问题是你正在返回一个堆栈变量,当函数返回时会丢失。一种方法是在函数参数中使用char * arg,并有足够的保留空间,并使用它来存储所有信息并将其返回。

答案 5 :(得分:0)

Line是一个局部变量,在函数末尾被删除。

你应该使用malloc,或者将它strcpy到作为参数传递的字符串指针。

答案 6 :(得分:0)

有三种方法可以解决这个问题

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;
}

在这种情况下,您需要使用free

释放fileNameString指向的内存