Функция для обращения массива в C (K&R 2nd ed.)

Попытка выполнить Упражнение 1-19 из K&R 2-е изд., Например, написать функцию для обращения строки. Я думал, что справился, но вывод на печать выглядит странно:-) Если я использую STRINGSIZE 5 выходOriginal String: hello Reversed String: ollehhello, Если я использую STRINGSIZE 6 иметь в виду '\0' конец строки и измените цикл while на while ((outputString[STRINGSIZE - (i + 2)] = inputString[i]) != '\0')тогда я получаю Original String: hello Reversed String: olleh?helloЯ думаю, ? это какой-то случайный персонаж из '\0' добавлен к обратной строке в цикле 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]) != '\0')
        ++i;
}

2 ответа

Решение

Сначала я предлагаю вам изменить эту строку:

    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] = '\0';  // Terminate the string
}

Во-первых, массив символов reversedString[] не хватает места для хранения нулевого терминатора строки "hello", Один из вариантов - использовать массив переменной длины:

char reversedString[strlen(stringToReverse) + 1];

VLA были введены в C99 и сделаны необязательными в C11. Насколько я помню, K&R не включает покрытие массивов переменной длины, так как даже второе издание было опубликовано до этого.

Другой вариант, который будет совместим с C89, это использовать sizeof оператор:

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

Здесь результат от sizeof Оператор известен во время компиляции и может использоваться в объявлении массива фиксированного размера. Этот размер включает пространство для нулевого терминатора, в отличие от результата из strlen("hello"), Обратите внимание, что это не будет работать с char *stringToReverse = "hello";с тех пор sizeof Оператор даст размер указателя. Это также не будет работать, если stringToReverse сначала был передан в функцию, с тех пор имя массива исчезло бы до указателя на первый элемент stringToReverse,

в reverseString() функция, длина inputString необходимо определить (так как STRINGSIZE больше не используется); это можно сделать с помощью strlen()или в цикле. Тогда, что критически важно, функция должна обязательно добавить нулевой терминатор (\0) чтобы 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] != '\0') {
        ++length;
    }

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

    /* Add null terminator */
    outputString[i] = '\0';
}
Другие вопросы по тегам