我想将字符串的X到Y字复制到out char *数组。
unsigned char * string = "HELLO WORLD!!!" // length 14
unsigned char out[9];
size_t length = 9;
for(i=0 ;i < length ;++i)
{
out[i] = string[i+3];
}
printf("%s = string\n%s = out\n", string, out);
在查看out
的输出时,为什么在我的字符串的某一点之后会出现乱码?我看到字符串为LO WORLD!@
。为什么在我复制的内容之后出现了奇怪的字符,是不是应该是9的数组呢?我期望输出为
LO WORLD!
答案 0 :(得分:2)
在C中,您需要使用0x00值终止字符串,因此长度为9的字符串需要10个字节来存储它,最后一个设置为0.否则您的打印语句会运行到随机数据中。
unsigned char * string = "HELLO WORLD!!!" // length 14
unsigned char out[10];
size_t length = 9;
for(i=0 ;i < length ;++i)
{
out[i] = string[i+3];
}
out[length] = 0x00;
printf("%s = string\n%s = out\n", string, out);
答案 1 :(得分:1)
C字符串必须以null结尾。您只创建了一个足够大的数组,可以容纳8个字符+空终止符,但是您从未添加过终结符。
因此,您需要分配长度加1并添加终结符。
// initializes all elements to 0
char out[10] = {0};
// alternatively, add it at the end.
out[9] = '\0';
以这种方式思考;你传递了一个表示字符串的char*
。你怎么知道它有多长?你怎么看?好吧,在C中,一个哨兵值被添加到最后。这是空终止符。它是如何在C中读取字符串,并将未终止的字符串传递给期望C字符串导致未定义行为的函数。
然后......只需使用strncpy
复制字符串。
答案 2 :(得分:1)
9个字符的字符串需要10个字节,因为它必须为null(0)终止。试试这个:
unsigned char out[10]; // make this 10
size_t length = 9;
for(i=0 ;i < length ;++i)
{
out[i] = string[i+3];
}
out[i] = 0; // add this to terminate the string
更好的方法就是这一行:
strncpy(out, string+3, 9);
答案 3 :(得分:1)
如果你想从你的字符串中复制9个字符,你需要有一个10的数组才能做到这一点。这是因为C字符串需要将'\ 0'作为空终止字符。所以你的代码应该像这样重写:
unsigned char * string = "HELLO WORLD!!!" // length 14
unsigned char out[10];
size_t length = 9;
for(i=0 ;i < length ;++i)
{
out[i] = string[i+3];
}
out[9] = 0;
printf("%s = string\n%s = out\n", string, out);
答案 4 :(得分:1)
一个小问题,但是字符串文字的类型为char*
(或C ++中的const char*
),而不是unsigned char*
- 这些在您的实现中可能是相同的,但它们不是需要。
此外,事实并非如此:
unsigned char * string = "HELLO WORLD!!!" // length 14
该字符串实际占用 15 字节 - 末尾有一个额外的隐藏'\0'
,称为nul
字节,用于标记字符串的结尾。这些nul终结符非常重要,因为如果它们不存在,那么操作字符串的许多C库函数将继续运行,直到它们达到值等于'\0'
的字节 - 因此最终可能会读取或践踏他们不应该做的内存。这称为缓冲区溢出,是C程序中的经典错误(以及可利用的安全问题)。
在你的例子中,你没有在你复制的字符串中包含这个nul终结符,所以printf()
只是一直持续到它找到一个,因此你看到的是胡言乱语。一般来说,如果可能的话,只使用C库函数来操作C字符串是一个好主意,因为这些都是为您添加终止符。在这种情况下,来自strncpy
的{{1}}完全符合您的要求。