所以当我反转“ hello”时它似乎起作用了,但是它打印出了一些奇怪的东西 “ol▒eh” 在中间。我修好了
i< length/2;
到
i<= length/2;
第一个不是正确的吗? C中的±字符是什么意思?是Null吗?
void reverse_copy(char dest[], const char src[]){
size_t i;
char temp;
size_t length = (size_t)strlen(src);
for(i = 0; i <= length/2; i++){ /*?? why i<length/2 is not working*/
dest[i] = src[length-i-1];
temp = src[i];
dest[length-i-1] = temp;
}
}
答案 0 :(得分:7)
i< length/2;
的主要问题在于,在src
的奇数字符串长度的情况下,它可能会忽略“中间”元素。因此,dest
中的中间元素可能保持未初始化状态,然后显示为某些“任意” ASCII值。
但是,通常,您的代码适用于reverse_in_place
,在这里您必须注意不要覆盖以后在复制循环中需要的内容。
但是,如果您进行了reverse_copy,那么简单地进行一个反向循环就足够了,甚至更好:
void reverse_copy(char dest[], const char src[]){
size_t i;
size_t length = strlen(src);
for(i = 0; i < length; i++){
dest[i] = src[length-i-1];
}
dest[i] = '\0';
}
答案 1 :(得分:3)
使用:
for(i = 0; i < length/2; i++){
您永远不会在dest
中设置中间字符(对于奇数长度)。
在您的示例"hello"
中,length/2
是2
,因此您进行了设置(对于i
= 0
):
dest[0] = src[5-0-1]; // dest[0] = src[4]
dest[5-0-1] = src[0]; // dest[4] = src[0]
然后(对于i
= 1
):
dest[1] = src[5-1-1]; // dest[1] = src[3]
dest[5-1-1] = src[1]; // dest[3] = src[1]
就是这样。您从未设置dest[2]
。
答案 2 :(得分:2)
因为i<length/2
已经基于整数除法,即:它将对结果取底。如果字符串长度为奇数,将跳过中间元素。
答案 3 :(得分:1)
要了解代码中发生了什么,调试器将提供帮助。
您需要逐行浏览代码,并观察i
和length - i - 1
的值。
中间出现一个奇怪字符的原因是,如果length
为奇数,则当条件为<
时,中间项将被跳过。
例如,当length == 5
时为5/2 == 2
(由于整数除法2.5
为2
)。
因此分析循环:
i=0
i < 2
。是的,所以继续代码块。dest[0] = src[4]
temp = src[0]
dest[4] = temp
i++
我是1 i < 2
。是的,所以继续代码块。dest[1] = src[3]
temp = src[1]
dest[3] = temp
i++
我是2 i < 2
。不,所以退出循环因此,在检查步骤时(尤其是步骤3、5、8、10),只有dest[0]
,dest[1]
,dest[3]
,dest[4]
是从源中写入的<
。
目的地2不变。
偶数不会出现此问题。
由于dest[2]
尚未更新,因此将显示已经存在的字符。可以是任何随机字符。如果将其初始化为0(空值),则表示0的字符。
但是看着那个字符,它看起来更像是一个值177(扩展的ASCII代码:http://www.asciitable.com/)
我也发现reverse_copy的定义很容易出错,因为它不知道目标缓冲区有多大。如果太小,它可以覆盖某些东西。
在这种情况下,我将使用哨兵标记字符串的结尾,并使用while循环:
void reverse_copy(char dest[], const char src[])
{
const char* src_end = src + strlen(src) - 1;
--src;
while (src_end > src)
{
*dest = *src_end;
++dest;
--src_end;
}
*dest = '\0';
}