Перегрузка << оператор для изменения "" на "\ n" - PullRequest
0 голосов
/ 03 октября 2018

Я пытаюсь перегрузить

<< </p>

оператора.Например,

cout << a << "" << b << "";// мне не разрешено изменять эту строкуне работает.Так что я думаю, что литерал </p>

""

не является строкой.Если это не так, то что это.И как его перегрузить?Пожалуйста, помогите;

Полный код

//Begin Program
// Begin -> Non - Editable     
    #include <iostream>
    #include <string>
    using namespace std;

// End -> Non -Editable
//---------------------------------------------------------------------
// Begin -> Editable       (I have written )
    ostream& operator << (ostream& os, const string& str) {
        string s  = " ";
        if(str  ==  " ") {
            os << '\n';
        }
        else {
            for(int i = 0; i < str.length(); ++i)
                os << str[i];
        }
        return os;
    }

// End -> Editable
//--------------------------------------------------------------------------
// Begin -> No-Editable     
int main() {
        int a, b;
        double s, t;
        string mr, ms;
        cin >> a >> b >> s >> t ;
        cin >> mr >> ms ;
        cout << a << " " << b << " " ;
        cout << s << " " << t << " " ;
        cout << mr << " " << ms ;

        return 0;
    }
// End -> Non-Editable
//End Program

Входы и выходы Вход

 30 20 5.6 2.3 hello world 

Выход

30
20
5.6
2.3
hello
world

Ответы [ 3 ]

0 голосов
/ 03 октября 2018

" " является строковым литералом длины один и поэтому имеет тип const char[2].std::string не связано.

Теоретически , вы можете перегрузить его следующим образом:

auto& operator<<(std::ostream& os, const char (&s)[2]) {
    return os << (*s == ' ' && !s[1] ? +"\n" : +s);
}

Хотя это превосходит все другие перегрузки, теперь все становится по-настоящему волосатым,Проблема в том, что some_ostream << " ", вероятно, не редкость, даже в шаблонах, и теперь больше не разрешает вызов стандартной функции .Эти шаблоны теперь имеют другое определение в затронутых единицах перевода, чем в незатронутых, что нарушает правило одного определения.

То, что вы должны сделать, - это не пытаться применить глобальное решение кочень локальная проблема:

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

0 голосов
/ 03 октября 2018

Конечно, это возможно, как я уже проверял.Он должен быть переносимым, так как вы указываете переопределение шаблонной функции operator<<(), включенной из <iostream>.Строка " " в вашем коде - это не std::string, а скорее строка в стиле C (то есть const char *).Следующее определение работает правильно:

ostream& operator << (ostream& os, const char *str) {
    if(strcmp(str, " ") == 0) {
        os << '\n';
    } else {
        // Call the standard library implementation
        operator<< < std::char_traits<char> > (os, str);
    }
    return os;
}

Обратите внимание, что пробел после std::char_traits<char> необходим только если вы пре-c ++ 11.

Редактировать 1

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

0 голосов
/ 03 октября 2018

Возможно, вы захотите использовать пользовательский литерал, например,

struct NewLine {};

std::ostream& operator << (std::ostream& os, NewLine)
{
   return os << "\n";
}

NewLine operator ""_nl(const char*, std::size_t) // "nl" for newline
{
   return {};
}

. Это можно использовать следующим образом.

int main(int, char **)
{
    std::cout << 42 << ""_nl << "43" << ""_nl;

    return 0;
}

Обратите внимание на три вещи:

  • Вы можете передать любой строковый литерал, за которым следует буквенный идентификатор, ""_nl делает то же самое, что и " "_nl или "hello, world"_nl.Вы можете изменить это, настроив функцию, возвращающую объект NewLine.
  • Это решение более неловкое и запутанное.Единственный реальный вариант использования, который я могу себе представить, - это возможность легко изменить поведение в более поздний момент времени.
  • При выполнении чего-то нестандартного лучше всего сделать это очевидным и явным - здесь, пользовательопределенный литерал действительно сияет, потому что << ""_nl с большей вероятностью привлечет внимание читателей, чем << " ".
...