Использование указателей для обращения строки - PullRequest
1 голос
/ 30 января 2020

Попытка перевернуть строку в C с помощью указателей, и я не могу понять, что не так с моим кодом. Кто-нибудь знает, почему это не работает?

int main(void) 
{
    char sentence[100];
    printf("Enter any string: ");

    scanf("%[^\n]s", sentence);

    char *sPtr;
    sPtr = sentence;
    int length = 0;

    printf("Original string = %s\n", sentence);

    while (*sPtr != '\0') {
        ++length;
        ++sPtr;
    }

    printf("Reverse string = ");

    for (int i = length; i >= 0; --i) {
        printf("%c", *(sPtr + 1));
    }

    puts("");
    return 0;
}

Ответы [ 5 ]

2 голосов
/ 30 января 2020

Ошибка здесь:

while (*sPtr != '\0') {
    ++length;
    ++sPtr;
}

В этот момент точка sPtr находится в конце строки, поэтому во втором l oop она никогда не уменьшается.

for (int i = length; i >= 0; --i) {
    printf("%c", *(sPtr+1));
}

Возможное решение может быть таким:

for (int i = length; i >= 0; --i) {
    printf("%c", *(sPtr));
    --sPtr;
}
1 голос
/ 30 января 2020
  1. Напишите отдельные функции для таких задач.
  2. При тестировании функции попытайтесь уменьшить количество неизвестных факторов. В вашем случае не scanf просто используйте известные строки. Сканирование может произойти сбой, и вы не будете знать, если это ваша функция, или пользовательский ввод.

Простая функция, библиотечные функции не используются.

char *reverse(char *str)
{
    char *head = str, *tail = str;

    if(str && *str)
    {
        while(*tail) tail++;
        tail--;
        while(tail > head)   
        {
            int ch = *tail;
            *tail-- = *head;
            *head++ = ch;
        }
    }
    return str;
}

https://godbolt.org/z/EgNLpF

1 голос
/ 30 января 2020

Это решение, которое я придумал. Спасибо за оказанную помощь!

while (*sPtr != '\0') {
    ++length;
    ++sPtr;
}

printf("Reverse string = ");

sPtr = sentence;

for (int i = length; i >= 0; --i) {
    printf("%c", *(sPtr+length));
    --sPtr;
}
1 голос
/ 30 января 2020

Вы всегда печатаете символ после конца строки.

for (int i = length; i >= 0; --i) {
    printf("%c", *(sPtr+1));
}

должно быть

for (int i = length-1; i >= 0; --i) {
    printf("%c", *(sPtr-(length-i));
}

или

   for (int i = length; i >= 0; --i) {
        sPtr--; //decrement first as sPtr will be pointing to \0 char
        printf("%c", *sPtr);
    }
0 голосов
/ 30 января 2020

После этого l oop

while (*sPtr != '\0') {
    ++length;
    ++sPtr;
}

указатель sPtr указывает на конечный ноль. Итак, в следующем l oop вы начинаете выводить строку из неопределенного символа после завершающего нуля.

for (int i = length; i >= 0; --i) {
    printf("%c", *(sPtr+1));
}

Выражение *(sPtr+1) не изменяется в l oop.

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

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

char *last = sentence;

while ( *last ) ++last;

if ( sentence != last )
{
    for ( char *first = sentence; first < --last; ++first )
    {
        char c = *first;
        *first = *last;
        *last = c;
    }
}

printf( "Reversed string = %s\n", sentence );

Вот демонстрационная программа.

#include <stdio.h>

int main(void) 
{
    char sentence[100] = { '\0' };

    printf( "Enter any string: " );
    scanf("%99[^\n]s", sentence );

    char *last = sentence;

    while ( *last ) ++ last;

    if ( sentence != last )
    {
        for ( char *first = sentence; first < --last; ++first )
        {
            char c = *first;
            *first = *last;
            *last = c;
        }
    }

    printf( "Reversed string = %s\n", sentence );

    return 0;
}

Его вывод может выглядеть как

Enter any string: Hello Jordan
Reversed string = nadroJ olleH

Вы можете написать отдельную функцию, которая переворачивает строку. Просто переместите код, который переворачивает строку из main, в отдельную функцию, например

#include <stdio.h>

char * reverse( char *s )
{
    char *last = s;

    while ( *last ) ++last;

    if ( s != last )
    {
        for ( char *first = s; first < --last; ++first )
        {
            char c = *first;
            *first = *last;
            *last = c;
        }
    }

    return s;
}

int main(void) 
{
    char sentence[100] = { '\0' };

    printf( "Enter any string: " );
    scanf("%99[^\n]s", sentence );

    printf( "Revresed string = %s\n", reverse( sentence ) );

    return 0;
}

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

Вот, пожалуйста.

#include <stdio.h>

int main(void) 
{
    char sentence[100] = { '\0' };

    printf( "Enter any string: " );
    scanf("%99[^\n]s", sentence );

    const char *sPtr = sentence;

    while ( *sPtr ) ++ sPtr;

    printf( "Revresed string = ");

    while ( sPtr != sentence ) putchar( *--sPtr );
    putchar( '\n' );

    return 0;
}

Еще более простую реализацию вы можете сделать с помощью рекурсивной функции. Например

#include <stdio.h>

void reversed_output( const char *s )
{
    if ( *s )
    {
        reversed_output( s + 1 );
        putchar( *s );
    }
}

int main(void) 
{
    char sentence[100] = { '\0' };

    printf( "Enter any string: " );
    scanf("%99[^\n]s", sentence );

    printf( "Revresed string = ");

    reversed_output( sentence );
    putchar( '\n' );

    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...