在 C 中反转数组的函数(K&R 第 2 版)

function for reversing an array in C (K&R 2nd ed.)

正在尝试做 K&R 第二版的练习 1-19,例如编写一个函数来反转字符串。我以为我成功了,但打印输出看起来很奇怪 :-) 如果我使用 STRINGSIZE 5 输出是 Original String: hello Reversed String: ollehhello。如果我使用 STRINGSIZE 6 记住 '[=14=]' 字符串结束字符并将 while 循环修改为 while ((outputString[STRINGSIZE - (i + 2)] = inputString[i]) != '[=15=]'),那么我得到 Original String: hello Reversed String: olleh?hello,我猜 ? 是来自 '[=14=]' 的一些随机字符,添加到 while 循环中位置 5 的反向字符串;但是 hello 再次添加。任何人都可以解释为什么 hello 被添加到 olleh 的末尾,我怎样才能摆脱它以便我只得到正确的反转字符串?

代码如下:

#include <stdio.h>
#define STRINGSIZE 5

void reverseString (char inputString[], char outputString[]);

int main(void) {
    char stringToReverse[] = "hello";
    char reversedString[STRINGSIZE]; 
    reverseString(stringToReverse, reversedString);
    printf("Original String: %s\nReversed String: %s\n", stringToReverse, reversedString);
}

void reverseString (char inputString[], char outputString[]) {
    int i;
    i = 0;
    while ((outputString[STRINGSIZE - (i + 1)] = inputString[i]) != '[=10=]')
        ++i;
}

首先,我建议您更改此行:

    char reversedString[STRINGSIZE]; 

char reversedString[strlen(stringToReverse) + 1];  // + 1 to make room for the string termination

然后我会做类似的事情:

void reverseString (char inputString[], char outputString[]) {
    int i;
    int len = strlen(inputString);
    for(i=0; i<len; ++i)
    {
        outputString[len-i-1] = inputString[i];
    }
    outputString[len] = '[=12=]';  // Terminate the string
}

首先,字符数组reversedString[]没有足够的space来存储字符串"hello"的空终止符。一种选择是在此处使用可变长度数组:

char reversedString[strlen(stringToReverse) + 1];

VLA 是在 C99 中引入的,在 C11 中是可选的。我记得,K&R 不包括可变长度数组的覆盖范围,因为即使是第 2 版也是在此之前发布的。

另一个与 C89 兼容的选项是使用 sizeof 运算符:

char stringToReverse[] = "hello";
char reversedString[sizeof stringToReverse];

此处,sizeof 运算符的结果在编译时已知,可用于固定大小数组的声明。此大小 包括 space 的空终止符,与 strlen("hello") 的结果形成对比。请注意,这不适用于 char *stringToReverse = "hello";,因为 sizeof 运算符将给出指针的大小。如果首先将 stringToReverse 传递给函数,这也将不起作用,因为那时数组名称将衰减为指向 stringToReverse.

第一个元素的指针

reverseString()函数中,需要确定inputString的长度(因为STRINGSIZE已经不用了);这可以用 strlen() 或在循环中完成。然后,至关重要的是,该函数必须确定在返回之前将空终止符 ([=26=]) 添加到 outputString[]。另请注意,return 语句已添加到 main() 的末尾以使其真正与 C89 兼容:

#include <stdio.h>

void reverseString (char inputString[], char outputString[]);

int main(void) {
    char stringToReverse[] = "hello";
    char reversedString[sizeof stringToReverse];

    reverseString(stringToReverse, reversedString);
    printf("Original String: %s\nReversed String: %s\n",
           stringToReverse, reversedString);

    return 0;
}

void reverseString(char inputString[], char outputString[])
{
    int length = 0;
    int i = 0;

    /* Get inputString length; or use strlen() */
    while (inputString[length] != '[=12=]') {
        ++length;
    }

    /* Copy to outputString[] in reverse */
    while (i < length) {
        outputString[i] = inputString[(length - i) - 1];
        ++i;
    }

    /* Add null terminator */
    outputString[i] = '[=12=]';
}