2017-10-06 41 views
-1

比方说,我有:如何防止C中复制函数期间“str 0ing”溢出?

char a[] = "str\0ing" 

,我想这个字符串复制到另一个字符数组,

char b[]. 

然而,我的功能似乎被击中终止序列(或至少向前斜杠)并停止,这样复制到b []中的唯一东西就是“str”。到底发生了什么,我该如何解决这个问题?

我正在运行一个格式为b [i] == a [i]的简单For循环。谢谢。

编辑:我很抱歉,因为很不清楚,这是我的第一篇文章。 这是我当前的代码:

int copyStringN(char * in, char * out, int n) { 
    int i; 
    if (!in || !out) return -1; 
    for (i = 0; i < n; i++) { 
    *out++ = *in++; 
    } 
    *out= '\0'; 
    return 0; 
} 

int main() { 
#define N 8 
    char a[] = "th\0ing"; 
    char b[N]; 
    int err; 
    err = copyStringN(a, b, N); 
    assert (!err); 
    printf("%s\n", b); 
    return 0; 
} 

的限制是,它必须能够打印“\ 0”,如果它存在,所以在字符串中我不能简单地添加一个反斜杠。我必须以某种方式编码我的函数来将此字符序列解释为显式字符而不是终止符。

+5

请显示一些代码。 – babon

+0

然后告诉你的函数不要把'\ 0'当作终结符。 –

+1

你必须知道数组的长度。字符数组不是字符串(通常,就像您的示例所示)。 –

回答

0

为了得到输出看起来像 “海峡\ 0ing”,逃避一个额外的\ NULL字符:

int main(void) 
{ 
    char a[] = "str\\0ing"; 
    int len = strlen(a); 
    char b[len+1]; 
    for(int i=0;i<len+1;i++) 
    { 
     b[i] = a[i]; 
    } 
    printf("%s\n", b); 

    return 0; 
} 

输出:
enter image description here

+1

好吧,那假设OP希望数组包含两个字符的序列''\\'',''0'而不是空字符。他可能确实需要这样做,但他是否确实不清楚。 –

+0

@JohnBollinger--这里也不完全清楚,做出最好的猜测,并试图解决这个问题。至少,我希望OP让我知道我是否错过了这个意图。谢谢。 – ryyker

+0

我上面已经编辑过。我对缺乏信息表示歉意,并感谢你。 – admbmb

0

这是你如何做到这一点一个简单的for循环:

#include <assert.h> 
#include <stdio.h> 

int main() { 
    char a[] = "str\0ing"; 
    int length = sizeof a/sizeof(char); 
    char b[length]; 
    for (int i = 0; i < length; i++) { 
     b[i] = a[i]; 
    } 
    assert(b[0] == 's'); 
    assert(b[1] == 't'); 
    assert(b[2] == 'r'); 
    assert(b[3] == '\0'); 
    assert(b[4] == 'i'); 
    assert(b[5] == 'n'); 
    assert(b[6] == 'g'); 
    printf("It works\n"); 
} 

还有其他方法,co但是你说你正在使用for循环,所以这可能与你已经尝试过的最接近。

这里的想法是,a不是一个字符串。它是一个字符数组。 C中的字符串是以零字节结尾的字节序列。如果你想在你的字符串中有一个零字节,它不是一个字符串。它是一个字符数组。所以上面的代码将数组a中的字符复制到数组b

请注意分配b足够空间的重要性。

编辑现在已添加到您的问题

好了,我们可以看到,你知道如何复制。但是你的问题是,你期望printf显示一个零字节的字符串。它不会。如果你只是给它指向字符串开头的指针,那么不是。

如果要打印一个零字节的“字符串”,唯一的方法是将字符数据及其长度包装到一个对象中,并用特殊的打印功能打印。

或者,如果可以的话,就移动到C++,它没有麻烦可言:

#include <iostream> 
int main() { 
    std::string s("str\0ing", 7); 
    std::cout << s << '\n'; 
} 

它运行这么好:

$ g++ t.cpp && ./a.out 
string 

田田!

+0

我上面编辑得更清晰。谢谢 – admbmb

+0

更新了答案。如果你不能移动到C++,那么把字符数据与它的长度绑定到一个结构中的想法应该是一种方法。尽管给C++一个尝试,如果可以的话。 –

2

如果你想要的\0被视为NUL字符(\0)本身,而不是作为\0,你可以使用memcpy()

char b[sizeof(a)]; 
memcpy(b, a, sizeof(a)); 

sizeof(a)字节a复制到b

阅读关于memcpy()here

由于John指出的那样,如果你有a作为参数传递给函数像

void fn(char b[], char a[]); 
... 
... 
fn(b, a); 

sizeof(a)会给指针变量的大小,这是不行的只能是所有相同指针并且不管大小为a。这是因为将数组传递给函数时,数组的地址是传递的,函数中的a实际上是一个指针。

这是这样即使功能就像

int fn(char b[], char *a); 

甚至

int fn(char b[], char a[10]); 

所以,如果你路过a的功能,一定要通过它的大小,以及像

void fn(char b[], char a[], size_t len) 
{ 
    memcpy(b, a, len); 
} 
... 
... 
... 
size_t l=sizeof(a); 
fn(a, l); 
+2

需要注意的一点是:这只适用于原始的'a'数组声明可见的范围。如果移动到以'a'作为参数传递的函数,它将会中断。 –

+0

@JohnBollinger谢谢指出。我编辑它。 –

+1

我编辑了我的文章,包括我无耻地被遗漏的东西,我很抱歉。谢谢。 – admbmb