Невозможно преобразовать char в строку с помощью Stringstream C++

Я просто собираюсь предупредить вас всех, что мой код содержит небольшие фрагменты французского и английского здесь и там, поэтому, если вы не понимаете переменную или что-то еще, спросите и рассмотрите это как бесплатный урок французского, ха-ха. Итак, у меня есть проект, который состоит из создания расписания для школ, и я отвечаю за управление «временной» частью, то есть создание временных промежутков и комнат для преподавателей для занятий. Чтобы убедиться, что все ситуации работают правильно, мне нужно убедиться, что 2 занятия не могут происходить одновременно и в одном месте. В моей функции rajoutcours, что по-французски означает «AddsClass», я использую несколько параметров:

  • matiere = предмет
  • heure_deb = время, в которое он начинается
  • heure_fin = время, когда оно заканчивается
  • date = ну это дата урока
  • salle = комната.

В своей функции я создаю 3 переменные: heure_start (время, когда начинается другой класс), heure_end (время, когда заканчивается другой класс), день и комната (день, когда происходят другие классы, и комната, в которой они происходят). Я заполняю эти переменные, используя свойство строкового оператора "+", где я конвертирую каждый символ строки в моих файлах txt (которые являются другими классами) в строки с 1 буквой, чтобы я мог добавить их, используя библиотеку sstream. Как ни странно, только один символ преобразуется в строку, а другие - нет, и я действительно не понимаю, почему.

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

    void  Utilisateur::rajout_cours(string matiere, string heure_deb, string heure_fin, string date, string salle )
{
    ifstream user_in ("Cours.txt"); // txt file where classes are listed
    ofstream user_out;
    user_out.open("Cours.txt", ofstream::out | ofstream::app);
    user_out; //write
    string ligne; //line variable which reads the lines of the txt file
    string heure_start; // time at which the class starts
    string heure_end; // time at which the class ends 
    string day; // self explanatory
    string room; // ie before
    int i=0;
    int j=0;
    int cptr=0;
    int a,b,c,d;
    stringstream ss;  // this is supposed to convert char into string
    while (getline(user_in,ligne))
    {
        for(i=0;i<ligne.size();i++)
        {
            if (ligne.at(i)=='$' && cptr==0)
            {
                a=i;
                cptr++;
            cout << "Premier '$'" << endl;  // Keep in mind that the '$' is the delimiter when i write on the txt file, it's also a way to know where I am. 
                for(j=0;j<a;j++)
                {
                    char tmpc='\0';
                    string tmps;
                    tmpc=ligne.at(j);
                    ss << tmpc;
                    cout << "Lettre a la case " << j << " : "<< tmpc << endl; //I want to know what's the char in the j-th character of the word
                    ss >>tmps;
                    cout << "Lettre string a la case " << j << " : "<< tmps << endl; // I want to display it's string version
                    heure_start=heure_start+tmps;

                }
            }

           else if (ligne.at(i)=='$' && cptr==1)
            {
                b=i;
                cptr++;
            cout << "Deuxieme '$'" << endl;

                for(j=a+1;j<(b);j++)
                {
                    char tmpc = '\0';
                    string tmps;
                    tmpc=ligne.at(j);
                    ss << tmpc;// conversion char en string
                    cout << "Lettre char a la case " << j << " : "<< tmpc << endl; //I want to know what's the char in the j-th character of the word
                    ss >>tmps;// conversion complète à priori
                    cout << "Lettre string a la case " << j << " : "<< tmps << endl; // I want to display it's string version
                    heure_end=heure_end+tmps;

                }
            }
           else if (ligne.at(i)=='$' && cptr==2)
            {
                c=i;
                cptr++;
            cout << "3eme '$'" << endl;

                for(j=b+1;j<(c);j++)
                {
                    char tmpc='\0';
                    string tmps = "";
                    tmpc=ligne.at(j);
                    ss << tmpc;
                    cout << "Lettre a la case " << j << " : "<< tmpc << endl; //I want to know what's the char in the j-th character of the word
                    ss >>tmps;
                    cout << "Lettre string a la case " << j << " : "<< tmps << endl; // I want to display it's string version

                   room=room+tmps;

                }
            }
           else if (ligne.at(i)=='$' && cptr==3)
            {
                d=i;
                cptr++;
            cout << "4eme '$'" << endl;

                for(j=c+1;j<(d);j++)
                {
                    char tmpc='\0';
                    string tmps = "";
                    tmpc=ligne.at(j);
                    ss << tmpc;
                    cout << "Lettre char a la case " << j << " : "<< tmpc << endl; //I want to know what's the char in the j-th character of the word
                    ss >>tmps;
                    cout << "Lettre string a la case " << j << " : "<< tmps << endl; // I want to display it's string version

                   day=day+tmps;

                }

            }

        }
    }



    if (heure_deb==heure_start && heure_fin==heure_end && date==day && salle==room) // I make sure here that the class I'm writing isn't already written in the file and in that case we leave the program.
    {
        cout << "Impossible d'ajouter un cours ! Un cours de " << matiere <<"a deja lieu à ce moment! Changez d'horaires ou de salles. " << endl;
        exit(1);
    }

        cout <<"ecris" << endl;
        user_out << heure_deb << "$"<< heure_fin << "$" << salle  << "$" << date << "$" << matiere << endl; // If not, write the new class. 



}

Добро пожаловать в Stack Overflow. Пожалуйста, прочтите страницы помощи, возьмите SO тур, прочтите про как задавать хорошие вопросы, а также этот контрольный список вопросов. Наконец, узнайте, как создать Минимальный, полный и проверяемый пример.

Some programmer dude 06.10.2018 12:18

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

πάντα ῥεῖ 06.10.2018 12:42

Кстати. есть очень простой способ преобразовать char в std::string, поскольку последний имеет для этого специальный конструктор: std::string::string(size_t count, char ch). Вы могли пропустить это из-за параметра count. (Я лично считаю, что он был введен не только для удобства, но и для устранения неоднозначности такого количества конструкторов.) Однако вот как это работает: char c = 'A'; std::string str(1, c); или даже std::string str(1, 'A');. Et voilà - char преобразован в std::string.

Scheff's Cat 06.10.2018 13:16

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

n. 1.8e9-where's-my-share m. 06.10.2018 14:26
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
4
872
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я уже упоминал, что преобразовать char в std::string очень просто, просто используя соотв. конструктор std::string::string(size_t count, char ch):

 char c = 'A';
 std::string str(1, c); // constructs a string str with one character

Однако после того, как я прочитал вопрос в третий раз, я понял, что он действительно должен работать так, как пытался это сделать OP.

Итак, для меня фактический вопрос привел к:

Почему std::stringstream нельзя использовать повторно для попеременного ввода / вывода?

Спустя короткое время я вспомнил о «стриме» в stringstream.

Что ж, может - учитывая тот факт, что после заполнения его выводом (например, <<) и опорожнения его вводом (например, >>) его внутреннее состояние становится eof, где следующее чтение приведет к состоянию fail. Итак, (хотя я все же рекомендовал бы использовать описанный выше более простой метод),

  • либо сбросить состояние std::stringstream перед его повторным использованием (для этого подходит std::stringstream::clear()).
  • или просто используйте локальные экземпляры std::stringstream (заключив конструкцию stringstream и операторы ввода / вывода в дополнительную пару фигурных скобок { })

Небольшой пример:

#include <iostream>
#include <sstream>
#include <string>

int main()
{
  { // "recycle" one instance of std::stringstream
    std::stringstream sstr;
    for (char c = 'A'; c <= 'C'; ++c) {
      std::cout << "c: '" << c << "', ";
      sstr << c;
      std::string str;
      sstr >> str;
      std::cout << "str: '" << str << "', "
        << "sstr.good(): " << sstr.good() << ", "
        << "sstr.eof(): " << sstr.eof() << '\n';
      sstr.clear();
    }
  }
  { // one instance per I/O
    for (char c = 'A'; c <= 'C'; ++c) {
      std::cout << "c: '" << c << "', ";
      std::stringstream sstr;
      sstr << c;
      std::string str;
      sstr >> str;
      std::cout << "str: '" << str << "'\n";
    }
  }
  // done
  return 0;
}

Выход:

c: 'A', str: 'A', sstr.good(): 0, sstr.eof(): 1
c: 'B', str: 'B', sstr.good(): 0, sstr.eof(): 1
c: 'C', str: 'C', sstr.good(): 0, sstr.eof(): 1
c: 'A', str: 'A'
c: 'B', str: 'B'
c: 'C', str: 'C'

Live Demo on coliru


Подумав дважды, я понял, что есть еще одна причина, по которой очистка состояния eof необходима в этом конкретном случае:

  • на выходе ровно один char
  • ввод пытается заполнить std::string (что как-то гораздо более жадно) и читает до разделителя или конца файла (и всегда происходит последнее).

Проверил это:

#include <iostream>
#include <sstream>

int main()
{
  // "recycle" one instance of std::stringstream
  std::stringstream sstr;
  for (char c = 'A'; c <= 'C'; ++c) {
    std::cout << "c: '" << c << "', ";
    sstr << c;
    char cIO;
    if (sstr >> cIO) std::cout << "cIO: '" << cIO << "'\n";
    else std::cout << "reading cIO failed\n";
  }
  // done
  return 0;
}

Выход:

c: 'A', cIO: 'A'
c: 'B', cIO: 'B'
c: 'C', cIO: 'C'

Live Demo on coliru

Теперь он работает даже без sstr.clear(), поскольку он никогда не пытается читать дальше конца файла (он же stringstream).

Упоминание о «жадном» чтении operator>>(std::stringstream&, std::string) натолкнуло меня на другую мысль:

Что произойдет, если char в квесте является разделителем?

#include <iostream>
#include <sstream>
#include <string>

int main()
{
  char c = ' ';
  std::stringstream sstr;
  sstr << c;
  std::cout << "c: '" << c << "', ";
  std::string str;
  sstr >> str;
  std::cout << "str: '" << str << "'\n";
  std::cout
    << "sstr.good(): " << sstr.good() << '\n'
    << "sstr.eof(): " << sstr.eof() << '\n'
    << "sstr.fail(): " << sstr.fail() << '\n'
    << "sstr.bad(): " << sstr.bad() << '\n';
  // done
  return 0;
}

Выход:

c: ' ', str: ''
sstr.good(): 0
sstr.eof(): 1
sstr.fail(): 1
sstr.bad(): 0

Live Demo on coliru

Я должен признать, что (поскольку я никогда не пытался преобразовать char в std::string с помощью std::stringstream), я не знал, что std::stringstream - такой плохой выбор.

Другие вопросы по теме