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

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

  • matiere = тема
  • heure_deb = время начала
  • heure_fin = время окончания
  • дата = хорошо, это дата урока
  • Салле = комната.

В моей функции я создаю 3 переменные: heure_start (время начала другого класса), heure_end (время окончания другого класса), день и комната (день, когда происходят другие классы, и комната, в которой они находятся). Я заполняю эти переменные, используя свойство строкового оператора "+", где я преобразую каждый символ строки в моих текстовых файлах (которые являются другими классами) в строки с 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. 



}

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

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

Итак, для меня актуальный вопрос привел:

Зачем 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'

Живая Демо на Колиру


Подумав дважды, я понял, что есть еще одна причина, по которой 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'

Живая Демо на Колиру

Теперь это работает даже без 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

Живая Демо на Колиру

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

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