使用C中包含多个Null字符的字符串

时间:2013-12-17 09:17:24

标签: c linux memory

我有一个char[]缓冲区,其中包含从内存中读取的数据,这意味着此缓冲区中有多个Null,而不是只有一个Null在末尾终止。

char *addr = (char *)memmem(buff, strlen(buff), needle, strlen(needle));

我需要处理此字符串并搜索并替换某些内容。 为此,我想使用memmem(),但不幸的是,它不起作用,因为缓冲区中有多个Null。

我试图用我认为不会出现的字符(Bell ASCII代码\ 7)替换缓冲区中的Null然后处理它,但这不起作用并破坏我的数据。

是否有另一种方法来处理具有多个Null的字符串?

3 个答案:

答案 0 :(得分:4)

memmem可用于执行此操作。但是,由于您的数据包含嵌入的空值,因此无法使用strlen来计算长度。您需要分别跟踪长度。

char *addr = (char *)memmem(buff, buffLen, needle, needleLen);

答案 1 :(得分:2)

在你的char数组上使用strlen,你自己承认包含终止是行不通的。您应该意识到strlen只计算字符数,直到它遇到零终结符。
顺便说一下,这也是strncat的工作原理,因此您也无法使用这些功能。

您可以做的是保持一个int,用于跟踪字符串的实际长度。
解决此问题的另一种方法是编写自己的d_strlen函数,并始终确保缓冲区末尾有两个零终止字符:

size_t d_strlen(const char *in)
{
    size_t len = 0;
    while( !(in[len] == '\0' && in[len+1] == '\0' )) ++len;
    return len;
}

再次:您的buffer 必须然后由两个终止零终止,而不仅仅是那个:

char buff[100] = "this \0 string contains \0 terminators \0";//adds second \0
printf("%d  != %d\n", strlen(buff), d_strlen(buff));//yields 5 != 37

正如Frerich Raabe指出的那样,放弃了strlen等经过试验的测试函数的优化和安全性,这可能是d_strlen <的更好版本/ p>

size_t d_strlen(const char *in)
{
    size_t len = 0;
    while(strlen(in+len)) len += strlen(in+len) + 1;
    return len ? --len : 0;//check for zero-length
}

然而,这会两次调用strlen,这是无意义的开销,所以你最好写这个:

size_t d_strlen(const char *in)
{
    size_t i, len = 0;
    do
    {
        i = strlen(in+len);//get substring length
        len += i + 1;//add to total length + 1 for \0 char
    }while(i > 0);
    return len > 1 ? len-2 : 0;//subtract 2, if possible, else return 0
}

答案 2 :(得分:0)

C字符串是由NUL终止的字符序列...根据定义,它不能包含多个NUL。你拥有的是更通用的东西,一块字符。为了处理任意的字符块,它们必须伴随一个长度 - 字符数的计数。鉴于您可以处理块而不关心它是否包含NUL。给定一个由指向某些字符和计数的指针组成的块,你可以使用count而不是strlen,所以

memmem(buff, buff_len, needle, needle_len);