Что именно делает стринги?
Я пытаюсь изучить С++ со вчерашнего дня, и я использую этот документ: 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 (количество)."
Мое впечатление заключалось в том, что функция примет неотъемлемую часть строки и использует ее как входную.
(я точно не знаю, как задать вопрос здесь. Я также новичок в программировании)
Спасибо.
Ответы
Ответ 1
Иногда очень удобно использовать 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, отношения наследования между классами:
![string stream classes]()
Ответ 2
Чтобы ответить на вопрос. 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 и уточнил, но у меня нет оригинального автора.
Ответ 3
Из С++ Primer:
Тип istringstream читает строку, ostringstream записывает строку, а stringstream читает и записывает строку.
Я сталкиваюсь с некоторыми случаями, когда удобно и лаконично использовать stringstream.
случай 1
От одно из решений для эта проблема с идентификатором. Он демонстрирует очень подходящий случай, когда использование 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()
случай 2
Также из проблемы с ликетным кодом, который требует упрощения данной строки пути, одно из решений, использующих 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;
}
Без использования строкового потока было бы трудно написать такой сжатый код.
Ответ 4
Вы ввели буквенно-числовые и int, пустые разделители в mystr
.
Затем вы попытались преобразовать первый токен (пустой разделитель) в int
.
Первым токеном был RS, который не смог преобразовать в int
, оставив нуль для myprice, и все мы знаем, что в нулевое время ничего не дает.
Когда вы только вводили значения int во второй раз, все работало так, как вы ожидали.
Это был ложный RS, который вызвал ваш код.