Я пытаюсь изучить С++ со вчерашнего дня, и я использую этот документ: http://www.cplusplus.com/files/tutorial.pdf (стр. 32). Я нашел код в документе, и я его запустил. Я попытался ввести Rs 5.5 для цены и целое число для количества, а выход был равен 0. Я попытался ввести 5.5 и 6, и результат был верным.
// stringstreams
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main ()
{
string mystr;
float price = 0;
int quantity = 0;
cout << "Enter price: ";
getline (cin,mystr);
stringstream(mystr) >> price;
cout << "Enter quantity: ";
getline (cin,mystr);
stringstream(mystr) >> quantity;
cout << "Total price: " << price*quantity << endl;
return 0;
}
Вопрос: Что именно делает команда mystring? Цитирование из документа:
"В этом примере мы получаем числовые значения со стандартного ввода косвенно. Вместо извлечения числовых значений непосредственно из стандартный ввод, мы получаем линии от стандартного ввода (cin) в string object (mystr), а затем мы извлекаем целочисленные значения из эту строку в переменную типа int (количество)."
Мое впечатление заключалось в том, что функция примет неотъемлемую часть строки и использует ее как входную.
(я точно не знаю, как задать вопрос здесь. Я также новичок в программировании) Спасибо.
Иногда очень удобно использовать stringstream для преобразования строк и других числовых типов. Использование stringstream аналогично использованию iostream, поэтому нелегко учиться.
Stringstreams могут использоваться как для чтения строк, так и для записи данных в строки. Он в основном работает со строковым буфером, но без реального канала ввода/вывода.
Основными функциями-членами класса stringstream являются
str()
, который возвращает содержимое своего буфера в строковом типе.
str(string)
, которые устанавливают содержимое буфера в строковый аргумент.
Вот пример использования строковых потоков.
ostringstream os;
os << "dec: " << 15 << " hex: " << std::hex << 15 << endl;
cout << os.str() << endl;
Результат: dec: 15 hex: f.
istringstream
имеет более или менее одинаковое использование.
Подводя итог, stringstream - это удобный способ манипулировать строками, такими как независимое устройство ввода/вывода.
FYI, отношения наследования между классами:
Чтобы ответить на вопрос. stringstream
в основном позволяет рассматривать объект string
как a stream
и использовать на нем все stream
функции и операторы.
Я видел, что он использовался в основном для форматированного вывода/ввода.
Одним хорошим примером может быть реализация c++
преобразования числа в объект потока.
Возможный пример:
template <class T>
string num2str(const T& num, unsigned int prec = 12) {
string ret;
stringstream ss;
ios_base::fmtflags ff = ss.flags();
ff |= ios_base::floatfield;
ff |= ios_base::fixed;
ss.flags(ff);
ss.precision(prec);
ss << num;
ret = ss.str();
return ret;
};
Может быть, это немного сложно, но это довольно сложно. Вы создаете объект stringstream
ss
, изменяете его флаги, помещаете в него номер с помощью operator<<
и извлекаете его через str()
. Я предполагаю, что можно использовать operator>>
.
Также в этом примере буфер string
скрыт и не используется явно. Но было бы слишком долго писать о всех возможных аспектах и прецедентах.
Примечание: я, вероятно, украл его у кого-то на SO и уточнил, но у меня нет оригинального автора.
ret
не нужно, можно написать return ss.str();
,
Из С++ Primer:
Тип istringstream читает строку, ostringstream записывает строку, а stringstream читает и записывает строку.
Я сталкиваюсь с некоторыми случаями, когда удобно и лаконично использовать stringstream.
От одно из решений для эта проблема с идентификатором. Он демонстрирует очень подходящий случай, когда использование stringstream является эффективным и кратким.
Предположим, что a
и b
- это комплексные числа, выраженные в строчном формате, мы хотим получить результат умножения a
и b
также в строчном формате. Код выглядит следующим образом:
string a = "1+2i", b = "1+3i";
istringstream sa(a), sb(b);
ostringstream out;
int ra, ia, rb, ib;
char buff;
// only read integer values to get the real and imaginary part of
// of the original complex number
sa >> ra >> buff >> ia >> buff;
sb >> rb >> buff >> ib >> buff;
out << ra*rb-ia*ib << '+' << ra*ib+ia*rb << 'i';
// final result in string format
string result = out.str()
Также из проблемы с ликетным кодом, который требует упрощения данной строки пути, одно из решений, использующих stringstream, является самым элегантным, что я видел:
string simplifyPath(string path) {
string res, tmp;
vector<string> stk;
stringstream ss(path);
while(getline(ss,tmp,'/')) {
if (tmp == "" or tmp == ".") continue;
if (tmp == ".." and !stk.empty()) stk.pop_back();
else if (tmp != "..") stk.push_back(tmp);
}
for(auto str : stk) res += "/"+str;
return res.empty() ? "/" : res;
}
Без использования строкового потока было бы трудно написать такой сжатый код.
Вы ввели буквенно-числовые и int, пустые разделители в mystr
.
Затем вы попытались преобразовать первый токен (пустой разделитель) в int
.
Первым токеном был RS, который не смог преобразовать в int
, оставив нуль для myprice, и все мы знаем, что в нулевое время ничего не дает.
Когда вы только вводили значения int во второй раз, все работало так, как вы ожидали.
Это был ложный RS, который вызвал ваш код.
stringstream
использовал его таким образом. Я обычно загружаю строку, преобразую ее и затем извлекаю по частям, однако это, очевидно, имеет небольшое преимущество, посколькуcin
уже является входным потоком ... Итак,cin >> price >> quantity;
было бы намного проще. Это было бы хорошей причиной НЕ использовать учебники cplusplus.com.