функция для реверсирования массива в 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 ответа:
Сначала я предлагаю вам изменить эту строку:
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"
. Один из вариантов-использовать массив переменной длины здесь:Власы были введены в C99 и стали необязательными в C11. Насколько я помню, K&R не включает покрытие массивов переменной длины, так как даже 2-е издание было опубликовано до этого.char reversedString[strlen(stringToReverse) + 1];
Другой вариант, который был бы совместим с 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'; }