Nick_is_asking Ответов: 5

C упражнение на обратную струну


Привет.У меня есть упражнение на Си для практики в университете.
Итак, пользователь дает строку, и я должен ее отменить,но у меня есть небольшая проблема.
Я заметил, что когда длина строки нечетное число,программа завершается успешно, но когда четное, я получаю "ошибка сегментации (ядро сбрасывается)"
и я знаю,почему это происходит, но я не могу найти способ выяснить это.

Код ниже:

Что я уже пробовал:

#include <stdio.h>


char *string_end(char *str);
void string_reverse(char *str);


int main()
{
    char string[30];
    printf("Give a string and I will reverse it: ");
    scanf("%s" , string);
    printf("Your string: %s\n\n" , string);
    printf("The reversed string: \n");
    string_reverse(string);
    return 0;
}

char *string_end(char *str)
{
    while(1)
    {
        if(*str == '\0')
        {
            str =  --str;
            //printf("Here->%c|%p\n",*str,str);
            break;
        }
        printf("%c|%p\n",*str,str);
        str++;
    }
    //printf("\n\n\n");
    return str;
}


void string_reverse(char *str)
{
    //printf("%c|%p\n\n",*str,str);
    char *start = str;
    char temp;
    char *end = string_end(str);
    //printf("%c|%p\n",*end,end);
    //printf("%c|%p\n",*start,start);
    do
    {
        temp = *start;
        *start = *end;
        *end = temp;
    }
    while(start++ != end--);
    printf("\n%s\n" , str);
}



Заранее спасибо :)

5 Ответов

Рейтинг:
2

Nick_is_asking

Я нашел его.Я должен был сказать::

while(start++ != end-- && end > start);


Рейтинг:
2

KarstenK

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

int evenHalf = 42 / 2; //21
int unevenHalf = 43 / 2; // also 21 


Рейтинг:
1

Mircea Neacsu

Вы уже нашли ошибку, но, пожалуйста, продолжайте читать.

Комментарии в коде.

#include <stdio.h>


char *string_end(char *str);
void string_reverse(char *str);


int main()
{
    char string[30];
    printf("Give a string and I will reverse it: ");
    scanf("%s" , string);
    printf("Your string: %s\n\n" , string);
    printf("The reversed string: \n");
    string_reverse(string);
    return 0;
}

/* This function is not needed as it will be shown below */
char *string_end(char *str)
{
    while(1)
    {
        if(*str == '\0')
        {
            str =  --str;
/* Think what happens if str is an empty string: You would be returning a pointer
to the location BEFORE the start of string. This is not necessarily a bad thing,
but in the line below you are accessing that location. This IS a bad thing.*/
            //printf("Here->%c|%p\n",*str,str);
            break;
        }
        printf("%c|%p\n",*str,str);
        str++;
    }
    //printf("\n\n\n");
    return str;
}


void string_reverse(char *str)
{
    //printf("%c|%p\n\n",*str,str);

    char *start = str; //Not needed
/* Except for the last printf statement, you don't really need another variable.
In C functions are called by value. You can use the parameter any way you want.
It will not be returned to caller. */

    char temp;
//    char *end = string_end(str);

    char* end = str + strlen(str)-1; //do like this
/* strlen function returns the length of string not counting the final \0
The following line gives you a pointer to the last character in the string
IF THE STRING IS NOT EMPTY.*/

    //printf("%c|%p\n",*end,end);
    //printf("%c|%p\n",*start,start);

/* Think twice before using do...while loops. In most cases using a while...
loop is easier to read and safer. In this case, again, if the string is empty
you trash some memory.
    do
    {
        temp = *start;
        *start = *end;
        *end = temp;
    }
    while(start++ != end--);
*/
    while (start < end) //takes care of empty string
    {
       temp = *start;
       *start++ = *end;
       *end++ = temp;
    }
    printf("\n%s\n" , str);
}


Рейтинг:
0

Dave Kreskowiak

Вы можете довольно легко найти проблему с помощью отладчика.

То while утверждение в вашем обратном коде делает неверное предположение. Это предполагает, что при любых обстоятельствах начало в конечном итоге будет равно концу. Это никогда не бывает так, если у вас есть четное число символов. Например, если начало и конец равны 5 и 6, то на следующей итерации они будут равны 6 и 5.


Рейтинг:
0

OriginalGriff

Там есть какой-то странный код ...

str =  --str;

Это отвратительно ... Я действительно не рекомендую этого делать вообще. Проблема в том, что то, что вы используете, является оператором побочного эффекта, и именно то, что он даст вам, зависит от автора компилятора: Почему x = ++x + x++ дает мне неправильный ответ?[^]
И использование цикла, который не имеет Терминатора, не очень хорошая идея.
Я бы сделал это по-другому:
Создайте второй массив символов того же размера, что и входной буфер, плюс один символ. Поместите null в последний элемент, чтобы завершить строку.
Используйте цикл, который продолжается до тех пор, пока он не найдет нуль во входной строке.
Поместите первый символ входной строки непосредственно перед нулем, добавленным в выходные данные.
Переходите к следующему персонажу.
Поместите второй символ входной строки непосредственно перед последним символом, добавленным в выходные данные.
Повторяйте до тех пор, пока не встретите нуль во входных данных.
Выведите выходную строку из последней позиции.

Попробуйте это на бумаге, это намного проще, чем ваша версия!