Я просто собираюсь предупредить вас всех, что мой код содержит небольшие фрагменты французского и английского здесь и там, поэтому, если вы не понимаете переменную или что-то еще, спросите и рассмотрите это как бесплатный урок французского, ха-ха. Итак, у меня есть проект, который состоит из создания расписания для школ, и я отвечаю за управление «временной» частью, то есть создание временных промежутков и комнат для преподавателей для занятий. Чтобы убедиться, что все ситуации работают правильно, мне нужно убедиться, что 2 занятия не могут происходить одновременно и в одном месте. В моей функции rajoutcours, что по-французски означает «AddsClass», я использую несколько параметров:
В своей функции я создаю 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.
}
Как уже упоминалось, сузьте код, чтобы воспроизвести рассматриваемую ошибку. Это то, что считается минимальный воспроизводимый пример и требуется для того, чтобы задать здесь ваш вопрос по теме.
Кстати. есть очень простой способ преобразовать 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
.
Пожалуйста, используйте английские идентификаторы при показе вашего кода международной аудитории.
Я уже упоминал, что преобразовать 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'
Подумав дважды, я понял, что есть еще одна причина, по которой очистка состояния 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
- такой плохой выбор.
Добро пожаловать в Stack Overflow. Пожалуйста, прочтите страницы помощи, возьмите SO тур, прочтите про как задавать хорошие вопросы, а также этот контрольный список вопросов. Наконец, узнайте, как создать Минимальный, полный и проверяемый пример.