функция для реверсирования массива в C (K&R 2-е изд.)


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

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

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];
Власы были введены в C99 и стали необязательными в C11. Насколько я помню, K&R не включает покрытие массивов переменной длины, так как даже 2-е издание было опубликовано до этого.

Другой вариант, который был бы совместим с 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';
}