Как вы модифицируете строку в C - PullRequest
0 голосов
/ 29 октября 2019

Я новичок в C и пытаюсь изменить имеющуюся у меня строку (я пытаюсь отменить ее), но я не уверен, почему программа не запускается так, как задумано (отображаетбез вывода).

void reverse(char *rTarget);

int main()
{
    char memes[] = "memes";
    reverse(memes);
    printf("%s", memes);
}

void reverse(char *rTarget)
{
    char swap;
    int length = (int) strlen(rTarget);

    for (int i = 0; i < length / 2; i++)
    {
        swap = rTarget[i];
        rTarget[i] = rTarget[length - i];
        rTarget[length - i] = swap;
    }
}

Ответы [ 7 ]

0 голосов
/ 29 октября 2019
#include <stdio.h>
#include <string.h>

void reverse(char *rTarget);

int main()
{
    char memes[] = "memes";
    reverse(memes);
    printf("%s", memes);
}

void reverse(char *rTarget)
{
    int length = (int) strlen(rTarget);

    for (int i = 0; i < length / 2; i++)
    {
        char swap = rTarget[i];
        rTarget[i] = rTarget[length - i - 1];
        rTarget[length - i - 1] = swap;
    }
}

Выражение * rTarget [i] анализируется как * (rTarget + i), а не * (rTarget) + i, как вы можете ожидать. И вам не нужно передавать символ ** здесь.

0 голосов
/ 04 ноября 2019
#include <stdio.h>
#include <string.h>

void reverse(char *rTarget);

int main()
{
    char memes[] = "memes";
    printf("Normal: %s\n", memes);

    reverse(memes);
    printf("Reversed: %s", memes);
}

void reverse(char *rTarget)
{
    char swap;
    int length = (int) strlen(rTarget);

    for (int i = 0; i < length / 2; i++)
    {
        swap = rTarget[i];
        rTarget[i] = rTarget[length - i - 1];
        rTarget[length - i - 1] = swap;
    }
}

Решением моей проблемы было то, что я не осознавал, что из-за того, что String является массивом символов, в строке хранится завершающий символ ... Поэтому я перезаписывал завершающий символ, создавая таким образомневерная строка.

0 голосов
/ 29 октября 2019

Если вы не собираетесь посылать несколько строк для обращения к функции, тогда для аргумента функции требуется только указатель на символ, представленный как "char a []". Во время обмена символами вам нужно пройти только 50% строки. Код может быть следующим.

void reverse(char a[]);

int main()
{
    char memes[] = "memes";
    reverse(memes);
    printf("%s", memes);
}

void reverse(char a[])
{
    char swap;
    int length = (int) strlen(a);
    for(int i = 0, j = (length - 1); i < (length / 2); i++, j--)
    {
        swap = a[i];
        a[i] = a[j];
        a[j] = swap;
    }
}
0 голосов
/ 29 октября 2019

Проблема здесь

*rTarget[i] = *rTarget[length - i]
*rTarget[length - i] = swap;

Основная проблема, кажется, приоритет оператора. [] имеет более высокий приоритет, чем *. Вы передаете «массив строк» ​​(потому что указатели могут использоваться в качестве массивов), поэтому, когда i равен 0, слева вы берете первый (и только существующий) массив с ссылками [0] и *его первый персонаж. На это вы назначаете глупость с правой стороны: первый символ массива [length] (который не существует), который является неопределенным поведением, так что то, что вы программируете после этого, не имеет смысла рассуждать. Вам нужно добавить круглые скобки, чтобы вы ссылались на указатель на массив, чтобы вы получили реальный массив, а затем используете [] для этого.

Но даже если вы добавите круглые скобки, ваш алгоритм неверен. В первом раунде i равен 0, поэтому вы копируете (*rTarget)[length] в начало строки. Это строка, оканчивающаяся 0, так что вы получите измененную длину строки 0 (первый байт равен 0). Для длины вам нужно -1.

Исправляя исходный код, он становится:

for (int i = 0; i < length / 2; i++)
    {
        swap = (*rTarget)[i];
        (*rTarget)[i] = (*rTarget)[length - i - 1];
        (*rTarget)[length - i - 1] = swap;
    }

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

0 голосов
/ 29 октября 2019

Здесь есть все виды ошибок разыменования. Помните, строка - это массив символов, а не массив символьных указателей. Итак, это

void reverse(char *rTarget[])

должно быть

void reverse(char rTarget[])

А здесь:

int length = (int) strlen(*rTarget);

Вам не нужно разыменовывать rTarget, поэтому удалите *. То же самое в свопе, удалите все *, которые у вас там есть.

И последнее, но не менее важное: в вашем свопе есть ошибка off on one. Вместо перехода к length - i вы хотите перейти к length - i - 1, в противном случае вы заменяете нулевой терминатор на начало.

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

for (int i = 0; i < length/2; i++)

В целом все должно выглядеть так:

void reverse(char rTarget[]);

int main()
{
    char memes[] = "memes";
    reverse(memes);
    printf("%s", memes);
}

void reverse(char rTarget[])
{
    char swap;
    int length = (int)strlen(rTarget);

    for (int i = 0; i < length/2; i++)
    {
        swap = rTarget[i];
        rTarget[i] = rTarget[length - i - 1];
        rTarget[length - i - 1] = swap;
    }
}
0 голосов
/ 29 октября 2019

Для начала это объявление функции

void reverse(char *rTarget[]);

эквивалентно

void reverse(char **rTarget);

Нет большого смысла объявлять его таким образом.

Вы должны объявитьфункция типа

void reverse( char rTarget[] );

и вызов ее как

reverse( memes );

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

for (int i = 0; i < length / 2; i++)

, и эти выражения

    swap = *rTarget[i];
    *rTarget[i] = *rTarget[length - i];
    *rTarget[length - i] = swap;

недопустимы. Они должны быть переписаны как

    swap = ( *rTarget )[i];
    ( *rTarget )[i] = ( *rTarget )[length - i -1];
    ( *rTarget )[length - i - 1] = swap;

Также переменная length должна иметь тип size_t, потому что в общем случае объект типа int не может вместить объект типа size_t и функцию strlen иметь тип возврата size_t. Таким образом, вы должны заменить это объявление

int length = (int) strlen(*rTarget);

Для этого объявления

size_t length = strlen(*rTarget);

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

И согласно стандарту C функция main без параметров должна быть объявлена ​​как

int main( void )

Вот демонстрационная программа, которая показывает, как функция может быть объявлена ​​и определена

#include <stdio.h>
#include <string.h>

char * reverse( char *s )
{
    for ( size_t i = 0, n = strlen( s ); i < n / 2; i++ )
    {
        char c = s[i];
        s[i] = s[n-i-1];
        s[n-i-1] = c;
    }

    return s;
}

int main(void) 
{
    char memes[] = "memes";

    puts( reverse( memes ) );

    return 0;
}

Вывод программы

semem
0 голосов
/ 29 октября 2019

Это должно сделать это:

void reverse(char rTarget[]);

int main()
{
    char memes[] = "memes";
    reverse(memes);
    printf("%s", memes);
}

void reverse(char rTarget[])
{
    char swap;
    int lastindex = (int) strlen(rTarget) - 1;

    for (int i = 0; i < lastindex / 2; i++)
    {
        swap = rTarget[i];
        rTarget[i] = rTarget[lastindex - i];
        rTarget[lastindex - i] = swap;
    }
}

В вашем коде есть пара проблем. Прежде всего, массивы всегда «передаются по ссылке», поэтому вам не нужно передавать указатель на массив. Любые изменения, сделанные вами в массиве, сохранятся после вызова функции. Во-вторых, индексы массива в C начинаются с 0. Таким образом, последний символ (не считая ноль) в строке длиной n равен string[n-1], а не string[n].

РЕДАКТИРОВАТЬ: Как упоминалось @roottraveller, так каквы меняете символы, вам не нужно бежать до конца строки. Вам нужно только идти до половины длины.

...