Обратная строка в стиле C? - C ++ - PullRequest
3 голосов
/ 04 февраля 2010

Я хочу использовать указатели для обращения к массиву символов в C ++. Мне было интересно, есть ли что-то, что я должен сделать по-другому? Я делаю это правильно? Есть ли более эффективный способ сделать это?

Моя маленькая программа:

int main ( )
{
    char buffer[80];

    PrintHeader();

    cout << "\nString reversal program";
    cout << "\nType in a short string of words.";
    cout << "\nI will reverse them.";
    cout << "\n:";
    cin.getline(buffer, 79);

    cout << "\nYou typed " << buffer;
    reverse (buffer);
    cout << "\nReversed: " << buffer;

    cout << endl;
    system("PAUSE");
    return 0;

}


void reverse(char* string)
{
    char* pStart, *pEnd;
    int length;
    char temp;

    length = strlen(string);

    pStart = string;
    pEnd = &string[length - 1];

    while(pStart < pEnd)
    {
        temp = *pStart;
        *pStart = *pEnd;
        *pEnd = temp;
        pStart++;
        pEnd--;
    }
}

Ответы [ 5 ]

9 голосов
/ 04 февраля 2010
void str_reverse( char *str ) {
    char *str_end = strchr( str, 0 );
    std::reverse( str, str_end );
}

, если предполагается написать цикл,

void str_reverse( char *str ) {
    std::size_t len = std::strlen( str );
    for ( std::size_t index = 0; index != len / 2; ++ index ) {
        std::swap( str[ index ], str[ len - index - 1 ] );
    }
}

или, конечно, если вы можете использовать строку C ++,

void str_reverse( std::string &str ) {
    std::reverse( str.begin(), str.end() );
}
3 голосов
/ 04 февраля 2010

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

  • избегать предварительного объявления переменных в начале функции. Это требование C (со стандартом 1990 года), но в C ++ более идиоматично объявлять и инициализировать переменные там, где вы их используете.

  • избегать выхода за пределы (уменьшая после начала строки), если строка пуста.

Так что-то вроде:

void reverse(char* string)
{
    char* first = string;
    char* last = string + strlen(string);

    while(first < last)
    {
        --last; //avoids decrementing last beyond start of string if string is empty
        char temp = *first;
        *first = *last;
        *last = temp;
        ++first;
    }
}
1 голос
/ 04 февраля 2010

Вы можете использовать std::swap(*pStart, *pEnd) вместо открытого кода подкачки.

Черт, вы можете просто использовать std::reverse(buffer, buffer + strlen(buffer)). Но я полагаю, что на самом деле вы сами не используете указатели, и с учетом этого требования все выглядит хорошо.

Ну, на самом деле, крошечная гнида: если length==0, то &string[length - 1] не указывает на массив символов и теоретически не является допустимым указателем.

0 голосов
/ 04 февраля 2010

Ваш код очень многословен и перечисляет каждую операцию, такую ​​как выбор длины строки или присвоение указателя на конец строки, или использование вспомогательной переменной для обмена значениями.

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

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

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

0 голосов
/ 04 февраля 2010

Ничего особенного в твоем. Я бы не стал использовать хорошо известные имена типов в качестве переменных, например, таких как string, так как это может сбить с толку других. Просто для еще одного способа вы можете сделать это.

void RevBuff(char* Buffer)
{

int length = strlen(Buffer);
char * CpBuff = _strdup(Buffer);
for(int i = length -1, x = 0; i >=0 ; i--, x++)
{
    Buffer[x] = CpBuff[i];
}
free(CpBuff);
}

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

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