Функция для обращения массива в 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';
}