Как перебрать обратно в массив в C? - PullRequest
1 голос
/ 03 октября 2010

Я пытаюсь ввести строку символов, а затем вывести их в обратном направлении, например

Ввод: Hello Выход: olleH

У меня есть рабочий пример, однако я получаю каждую буквукроме последнего.

#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100

int main(void) {
int my_stg2[MAX_SIZE];
int i = 0;
int j;
char my_stg[MAX_SIZE];

int input ;

input = getchar();

while (input != '\n'){//The new line is the stopping point.


    my_stg2[i] = input;
    ++i;
 input = getchar();


}
    for (j=0;i>=0;i--){



    my_stg[j]  = my_stg2[i];
    j++;
}

printf("%s\n" , my_stg);

}

Я попробовал приведенный выше код, однако получаю странный вывод с большими строками.Кто-нибудь может исправить петлю для меня?http://imgur.com/PK97b.png

Ответы [ 6 ]

28 голосов
/ 04 октября 2010

Хорошо.Чтобы разрешить подобные случаи, вы должны действительно делать то, что говорит Кристофер Джонсон , и пройти через это на бумаге, чтобы выяснить, как изменятся ваши переменные во время выполнения вашей программы.Ручка и бумага - одни из самых важных инструментов, которые есть у программиста.

Только потому, что я знаю, что это может быть трудно сделать, если вы не знаете, как это сделать, позвольте мне рассказать вам об этом.

Предположим, введен "Hello\n".Перед началом цикла у вас будут следующие значения:

i = 0 & input = 'H'

Затем вы перейдете к циклу:

while (input != '\n') { my_stg2[i] = input; ++i; input = getchar(); }

для каждой итерации в цикле ваши значения будут изменены на:

i = 1 & input = 'e' & my_stg2[0] = 'H'
i = 2 & input = 'l' & my_stg2[1] = 'e'
i = 3 & input = 'l' & my_stg2[2] = 'l'
i = 4 & input = 'o' & my_stg2[3] = 'l'
i = 5 & input = '\n' & my_stg2[4] = 'o'

Итак.i теперь равно 5.

Теперь вы переходите ко второму циклу и делаете следующее:

for (j = 0; j <= i; j++) { --i; my_stg[i] = my_stg2[j]; }

вы начинаете цикл, и после уменьшения я получаюследующие пары значений:

j = 0 & i = 5 & my_stg[4] = my_stg2[0] = 'H'
j = 1 & i = 4 & my_stg[3] = my_stg2[1] = 'e'
j = 2 & i = 3 & my_stg[2] = my_stg2[2] = 'l'

... и на третьем шаге цикл останавливается.Выход вы получите "leH".

Теперь, почему цикл остановился?Посмотрите ваши условия , и вы найдете свой ответ.

2 голосов
/ 05 октября 2010

В вашем коде несколько проблем:

  1. int my_stg2[MAX_SIZE]; - массив случайных целых чисел при объявлении. Они имеют размер size (int) на вашей платформе - вероятно, 32 или 64 бита;

  2. char my_stg[MAX_SIZE]; - массив случайных символов при объявлении. Они имеют размер size (char) на вашей платформе - вероятно, 8 бит;

  3. Вы заменяете целые и символы с назначением my_stg[j] = my_stg2[i]; без приведения.

  4. Вы не проверяете переполнение буфера в цикле while. Если кто-то набрал более MAX_SIZE символов до \n, вы переполните выделенный буфер;

  5. Вы не равны нулю, заканчивая строку. Если вы используете getchar(), это один символ. После этого вам нужно поставить NUL, иначе вы получите беглую строку с printf()

  6. В вашем цикле while необходимо проверить EOF

  7. Это противоречит интуиции, но getchar() - это своя маленькая петлевая конструкция. Он не войдет в цикл while до EOF или CR. Затем он сбросит все символы. Тогда вам не следует проверять CR на getchar ().

  8. Ваш второй цикл отключен на один; Вы копируете значение после последнего символа.

Этот код работает так, как вы ожидаете. Я верю:

#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100

int main(void) {
    char my_stg[MAX_SIZE], my_stg2[MAX_SIZE];
    int i,j,input = 0;

    while ((input=getchar())!=EOF) {
        if(input=='\n' || i>=MAX_SIZE-1) break;
        my_stg2[i++] = (char)input;
        my_stg2[i+1] = (char)0l;
    }

    printf("my_stg2= %s\ni=%i\n",my_stg2,i);

    for (j=0;i>0;i--,j++){
       my_stg[j]  = my_stg2[i-1];
       my_stg[j+1]=(char)0l;
       printf("i=%i %s\n",i,my_stg);
    }
    printf("%s\n" , my_stg);
    return EXIT_SUCCESS;
}

Поскольку думать о строках как об окончании NUL несколько утомительно, большинство людей используют стандартную библиотеку C для строк.

Вы также можете подумать о том, чтобы сделать этот цикл более эффективным. Обращение строки на месте с использованием 1/2 памяти и 1/2 шага с помощью рекурсивной функции, подобной этой:

void strrev ( char *buff, int start, int end )
{
    char tmp ;
    static int i=0;

    if ( start >= end ) {i=0; return;}

    printf("%i strrev=%s\n",++i,buff);

    tmp = *(buff + start);
    *(buff + start) = *(buff + end);
    *(buff + end) = tmp ;

    strrev (buff, ++start, --end );
}

Если вы посмотрите на вывод, вы увидите, что это 1/2 шага и без копирования в другой буфер:

Hello World!!!
my_stg2= Hello World!!!
i=14
i=14 !
i=13 !!
i=12 !!!
i=11 !!!d
i=10 !!!dl
i=9 !!!dlr
i=8 !!!dlro
i=7 !!!dlroW
i=6 !!!dlroW 
i=5 !!!dlroW o
i=4 !!!dlroW ol
i=3 !!!dlroW oll
i=2 !!!dlroW olle
i=1 !!!dlroW olleH
!!!dlroW olleH
Recursive:
1 strrev=!!!dlroW olleH
2 strrev=H!!dlroW olle!
3 strrev=He!dlroW oll!!
4 strrev=HeldlroW ol!!!
5 strrev=HelllroW od!!!
6 strrev=HelloroW ld!!!
7 strrev=Hello oWrld!!!
reverse the reverse: Hello World!!!
2 голосов
/ 05 октября 2010

В вашей программе 2 ошибки.

Во-первых, поймите, что значение «i» в вашем первом цикле всегда установлено на «индекс, в который мы будем записывать дальше».

i = 0; input = getchar();
while (input != '\n'){
    my_stg2[i] = input;
    ++i;
    input = getchar();
}

Выходя из этого цикла после написания «Hello!», Вы получите

my_stg2[] = {'H', 'e', 'l', 'l', 'o', '!'}, i=6

Когда вы начинаете читать значения из my_stg2, вы должны начать читать с (i-1), а не с i.

Вторая проблема заключается в том, что после копирования содержимого my_stg2 в my_stg вам необходимо выполнить:

my_stg2[j] = 0;

Это потому, что строки в C используют завершающий нуль для определения конца строки. Причина, по которой вы получаете символы мусора, следующие за вашей строкой на прикрепленной картинке, заключается в том, что код printf () будет продолжать печатать каждый последующий байт в памяти, пока он не достигнет 0, и вы никогда не поместите 0 в конце строки my_stg в явном виде.

В качестве альтернативы вы можете инициализировать все содержимое my_stg2 в 0 в начале вашей программы с помощью

memset(my_stg2, 0x00, sizeof(my_stg2));

Это важный урок с C - когда вы объявляете переменную, вам нужно инициализировать ее, или на некоторых платформах она будет заполнена тем, что ранее было сохранено в ячейке памяти.

2 голосов
/ 04 октября 2010

Это то, что у вас есть

// The following line is pseudo-code.
// The '\0' is required in C to mark end of a character string.
orig := 'H', 'e', 'l', 'l', 'o', '\0'

с количеством символов n = 6 (не забудьте \0).

Вот чего вы хотите достичь

reverse := 'o', 'l', 'l', 'e', 'H', '\0'

Итак, вот что мы должны сделать:

A. положить \0 в reverse[ n - 1 ]

B. Мы будем читать orig вперед , начиная с индекса i = 0, и писать в reverse назад , начиная с индекса j = n - 1. Для этого мы используем две индексные переменные:

  i, for indexing orig, starting at 0 and incrementing up to n - 1

  j, for indexing reverse, starting at n - 1 and decrementing down to 0

C. скопировать с orig[ i ] на reverse[ j ]

for( i = 0, j = n - 1; (i <= n - 1) && (j >= 0); ++i, --j ) {
   reverse[ j ] = orig[ i ];
}
2 голосов
/ 03 октября 2010

Настройте цикл for, как показано ниже

for (j=0; j < i; j++)
{
    my_stg[i - (j + 1)]  = my_stg2[j];
}

my_stg[i] = 0;
1 голос
/ 05 октября 2010

Посмотрите на обратное решение указателя для вашего вопроса о массиве:

const char *loop = my_stg2 + strlen(my_stg2);
...
do {
  my_stg[loop-my_stg2] = *loop;
} while( my_stg2 != loop-- );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...