1

如何实现一个子字符串函数,例如以下返回子字符串但不在malloc()进程中使用的函数,因此我不必担心使用该free()函数在代码中的其他地方释放关联的内存。这甚至可能吗?

const char *substring(const char *string, int position, int length)
{
    char *pointer;
    int c;

    pointer = malloc(length+1);

    if (pointer == NULL)
    {
        printf("Unable to allocate memory.\n");
        exit(EXIT_FAILURE);
    }

    for (c = 0 ; c < position -1 ; c++)
        string++;

    for (c = 0 ; c < length ; c++)
    {
        *(pointer+c) = *string;
        string++;
    }

    *(pointer+c) = '\0';

    return substr;
}

更新:2012 年 12 月 30 日

考虑了所有答案和评论后,很明显,基本上我想要做的是创建一个动态大小的数组(即子字符串),并且在 C 中如果没有在某个地方必须使用某种malloc()函数和一个随后free()调用子字符串指针或没有垃圾收集器的帮助。我尝试按照libgc@elhadi 的建议集成垃圾收集器,但到目前为止还不能让它在我的 Xcode 项目中工作。所以我选择坚持使用下面的代码malloc()free().

char * subStr(const char* srcString, const int offset, const int len)
{
    char * sub = (char*)malloc(len+1);
    memcpy(sub, srcString + offset, len);
    sub[len] = 0;
    return sub;
}

int main()
{    
    const char * message = "hello universe";
    char * sub = subStr( message, 6, 8 );
    printf( "substring: [%s]", sub );
    free(sub);
}
4

5 回答 5

6

我看到两个选项:

如果您可以销毁源字符串(通常是一件坏事):

{
    string[ position + length] = 0;
    return & string[ position ];
}

注意:(参见 Cole Johnsons 的注释:free 不再适用于返回的指针!)

如果您无法修改源字符串:修改您的方法签名,以便调用者担心它:

const char *substring(const char *source, char* destination, int position, int length)

并将修改后的字符串放入目的地(并返回)。

甚至不要考虑这个:

const char *substring(const char *string, int position, int length)
{
    char *pointer;
    int c;
    static char modifiedString[256];
 ...
    return modifiedString;
}

在函数内部使用静态变量来获取修改后的结果...(这不是线程安全的(不是可重入的!))

于 2012-12-28T08:03:46.180 回答
2
const char *substring(const char *string, char *substr, int position, int length)
{
    int c;

    for (c = 0 ; c < position -1 ; c++)
        string++;

    for (c = 0 ; c < length ; c++)
    {
        *(substr+c) = *string;
        string++;
    }

    *(substr+c) = '\0';

    return substr;
}

调用函数...

int main(int argc, char * argv[]) {
    char substr[10];

    substring("hello! World", &substr[0], 2, 4);
}
于 2012-12-28T08:08:56.293 回答
2

使用本地缓冲区(自动数组)和这样的函数:

void substr(char *dst, const char *src, size_t loc, size_t len)
{
    memcpy(dst, src + loc, len);
    dst[len] = 0;
}

像这样称呼它:

const size_t size = 3;
char buf[size + 1]; // this is an auto array, it will be "freed" at the end of the scope
substr(buf, "abcdFOObar", 4, size);

始终确保缓冲区至少为len + 1字节长以避免缓冲区溢出错误。

于 2012-12-28T08:10:56.237 回答
1

最好的方法是:

typedef struct vstr_t {
     char *s;
     int   len;
} vstr_t;

#define vstr_set(d, l)                  \
    ({                                  \
        vstr_t vs = {.s = d, .len = l}; \
                                        \
        vs;                             \
    })

#define vstr_fmt_arg(vs) (vs).len, (vs).s

int main()
{    
    const char *message = "hello universe";

    printf( "substring: [%.*s]\n", vstr_fmt_arg(vstr_set(smpl + 6, 8)));

    return 0;
}
于 2012-12-28T08:49:21.140 回答
0

您可以使用垃圾收集器,您第一次分配内存,垃圾收集器会在不需要时释放内存。
你应该包括

#include "gc.h"

主要是你应该做一些像

GC_INIT();  /* Optional on Linux/X86;*/

你的 substr 函数是:

char *substr(const char* buffer, const int offset, int len)
{
    char sub = (char*)GC_MALLOC(len+1);
    memcpy(sub, buffer + offset, len);
    sub[len] = 0;
    return sub;
}

你应该链接到libgc.a

于 2012-12-28T09:47:01.967 回答