Перевернув строку, странный вывод c ++ - PullRequest
3 голосов
/ 11 июля 2011

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

Вот мой код:

 int main(){    

    char str[] = "string";
    int strSize = sizeof(str)/sizeof(char);

    char str2[strSize];

    int n = strSize-1;
    int i =0;


    while (&str+n >= &str){ 
        str2[i] = *(str+n);         
        n--;
        i++;
    }

    int str2size = sizeof(str)/sizeof(char);
    int x;

    for(x=0;x<str2size;x++){
        cout << str2[x];
    }

}

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

В этом конкретном случае я получаю вывод: "gnirts" В начале любого вывода есть раздражающий пробел, который, как я предполагаю, является нулевым символом? Но когда я пытаюсь избавиться от него, уменьшая переменную strSize, чтобы исключить его, я получаю другой символ на противоположном конце строки, вероятно, из другого блока памяти.

Есть идеи, как этого избежать? PS: (ребята, вы считаете это хорошей идеей перевернуть строку?)

Ответы [ 6 ]

7 голосов
/ 11 июля 2011

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

str2[strSize - 1] = str[strSize - 1]; // Copy the null at the end of the string

int n = strSize - 2; // Start from the penultimate character
1 голос
/ 11 июля 2011

@ ildjarn и @Blastfurnace уже дали хорошие идеи, но, думаю, я бы пошел дальше и использовал итераторы для построения обратной строки:

std::string input("string");

std::string reversed(input.rbegin(), input.rend());

std::cout << reversed;
1 голос
/ 11 июля 2011

В Стандартной библиотеке есть алгоритм для изменения последовательности. Зачем изобретать велосипед?

#include <algorithm>
#include <cstring>
#include <iostream>

int main()
{
   char str[] = "string";

   std::reverse(str, str + strlen(str)); // use the Standard Library

   std::cout << str << '\n';
}
1 голос
/ 11 июля 2011

Я бы позволил стандартной библиотеке C ++ сделать больше работы ...

#include <cstddef>
#include <algorithm>
#include <iterator>
#include <iostream>

int main()
{
    typedef std::reverse_iterator<char const*> riter_t;

    char const str[] = "string";
    std::size_t const strSize = sizeof(str);
    char str2[strSize] = { };
    std::copy(riter_t(str + strSize - 1), riter_t(str), str2);
    std::cout << str2 << '\n';
}
0 голосов
/ 11 июля 2011

Ваше условие цикла while (&str+n >= &str) эквивалентно (n >= 0).

Ваше *(str+n) эквивалентно str[n], и я предпочитаю последнее.

Как сказал HappyPixel, вашдолжен начинаться n с strSize-2, поэтому первый скопированный символ будет последним действительным символом строки, а не нулевым символом завершения строки.

Затем после того, как вы скопировали все обычные символы в циклевам нужно добавить нулевой символ завершения в конце str2, используя str2[strSize-1] = 0;.

Вот исправленный рабочий код, который выводит «gnirts»:

#include <iostream>
using namespace std;
int main(int argc, char **argv){    
    char str[] = "string";
    int strSize = sizeof(str)/sizeof(char);

    char str2[strSize];

    int n = strSize-2;  // Start at last non-null character
    int i = 0;

    while (n >= 0){ 
        str2[i] = str[n];         
        n--;
        i++;
    }
    str2[strSize-1] = 0;   // Add the null terminator.

    int str2size = sizeof(str)/sizeof(char);
    int x;

    cout << str2;
}
0 голосов
/ 11 июля 2011
 while (&str+n >= &str){

Это ерунда, вы просто хотите

while (n >= 0) {

и

 str2[i] = *(str+n);

должен быть гораздо более читабельным

str2[i] = str[n];
...