Soru Stringstream tam olarak ne yapar?


C ++'yi dünden beri öğrenmeye çalışıyorum ve bu belgeyi kullanıyorum:http://www.cplusplus.com/files/tutorial.pdf (sayfa 32). Belgede bir kod buldum ve çalıştırdım. Fiyat için Rs 5.5 ve miktar için bir tamsayı girmeyi denedim ve çıktı 0 oldu. 5.5 ve 6 girişlerini denedim ve çıktı doğruydu.

// 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; 
}

Soru: Mystring komutu tam olarak ne yapar? Belgeden alıntı yapmak:

"Bu örnekte standart girdiden sayısal değerler alıyoruz   dolaylı. Sayısal değerleri doğrudan   Standart girdi, standart girdiden (cin) gelen hatlara   string nesnesi (mystr) ve sonra tamsayı değerleri   Bu dizge int (miktar) cinsinden bir değişkene.

Benim izlenimim, fonksiyonun bir dizenin ayrılmaz parçasını alacağı ve bunu girdi olarak kullanacağıydı.

(Burada bir soru sormayı tam olarak bilmiyorum. Programlamada da yeniyim) Teşekkür ederim.


76
2017-12-15 12:31


Menşei


Bu örnek biraz garip, hiç görmedim stringstream bu şekilde kullanılır. Genelde hattı yüklerim, dönüştürürüm ve sonra parçalar ile ayıklanırım, ancak bu durumun burada çok az avantajı olduğu için cin  olduğu zaten bir giriş akışı ... Yani cin >> price >> quantity; çok daha basit olurdu. Bu iyi bir sebep olurdu DEĞİL cplusplus.com eğitimlerini kullanmak. - Bartek Banachewicz
Bu öğretici, C ++'ya ilk kez maruz kalmamdı. Geçmişte, oldukça zayıf ve eksik. Öneririm iyi kitap yerine. - jrok
@BartekBanachewicz Belki sadece nasıl göstermek için örnek ile gelmek gerekiyordu stringstream Eserleri. Muhtemelen kötü olan bir tuhaftır =) Ama dizeyi bir akış olarak ele alabileceğinizi gösterir. - luk32
Daha gelişmiş kullanımlarına bir giriş değilse stringstream o zaman kesinlikle yanlış bir örnek. Ve eğer olsa bile, farklı bir şekilde yazılmalıdır. - j_kubik
@trojansdestroy Dayandığı tüm ilkelleri anlamadan stringstream'i anlayamıyorsunuz, bu yüzden bir öğreticinin okumasının bu açıdan nasıl yardımcı olduğunu göremiyorum. - Bartek Banachewicz


Cevaplar:


Bazen dizeleri ve diğer sayısal türleri arasında dönüştürmek için stringstream kullanmak çok uygundur. Kullanımı stringstream kullanımı benzer iostreamBu yüzden öğrenmek için bir yük değildir.

Dize akışları hem dizeleri okumak hem de veriyi dizilere yazmak için kullanılabilir. Esas olarak bir dize arabelleği ile çalışır, ancak gerçek bir G / Ç kanalı olmadan.

Stringstream sınıfının temel üye işlevleri

  • str(), arabelleğinin içeriğini dize türünde döndürür.

  • str(string)arabellek içeriğini dize argümanına ayarlar.

Dize akışlarının nasıl kullanılacağına dair bir örnek.

ostringstream os;
os << "dec: " << 15 << " hex: " << std::hex << 15 << endl;
cout << os.str() << endl;

Sonuç dec: 15 hex: f.

istringstream az ya da çok aynı kullanım içindir.

Özetlemek gerekirse, stringstream uygun bir yoldur Dizeleri bağımsız bir G / Ç aygıtı gibi manipüle.

FYI, sınıflar arasındaki kalıtım ilişkileri:

string stream classes


120
2017-12-15 13:28





Soruyu cevaplamak için. stringstream temelde bir string nesne gibi streamve hepsini kullan stream üzerindeki fonksiyonlar ve operatörler.

Daha çok formatlanmış çıktı / girdi iyiliği için kullanıldığını gördüm.

İyi bir örnek olurdu c++ sayıyı akış nesnesine dönüştürme uygulaması.

Olası örnek:

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;
};

Belki biraz karmaşık ama oldukça karmaşık. Sen yarat stringstream nesne ss, bayraklarını değiştirmek, içine bir sayı koymak operator<<ve üzerinden ayıkla str(). Sanırım bu operator>> kullanılabilir.

Ayrıca bu örnekte string arabellek gizlidir ve açıkça kullanılmaz. Ancak, her olası konu ve kullanım durumu hakkında bir yazı yazmak çok uzun sürecektir.

Not: Muhtemelen SO'lu ve rafine edilmiş birinden çalmıştım ama orijinal yazarımın olmadığını belirtmiştim.


15
2017-12-15 12:47



Not: kullanımı ret gereksizdir, biri yazabilir return ss.str();. - Matthieu M.
@MatthieuM. RVO'nun böyle yazılırsa ya da ss.str () tarafından döndürülen nesnenin çıkış noktasından kurtulabileceğinden emin değildim. Bu şekilde bir kopyasını yaptığımı biliyorum ve RVO işe yarayacak. Ama sen muhtemelen haklısın. - luk32
Aslında, RVO'nun iki türü vardır: URVO (adlandırılmamış, yani zamansallar için) ve NRVO (adlandırılmış); Çoğu derleyici RVO'yu uygular, ancak bazıları sadece URVO'yu (yapı seçeneklerine bağlı olarak) sınırlar. Genel olarak, dikkate alınması gereken birçok faktör daha vardır, bu yüzden mümkün olan en temiz kodu yazmalı ve RVO'nun içeri girip girmeyeceği konusunda endişelenmeyin. - Matthieu M.
NRVO yaygındır (URVO'da olduğu gibi), ancak bunlar, kurucuların taşınmasından dolayı bir sorun değildir. - Rapptz


itibaren C ++ Astar:

istringstream türü bir okur sicim, ostringstream yazıyor bir sicim, ve stringstream okur ve yazar sicim.

Kullanmak için hem uygun hem de özlü olduğu bazı durumlarda karşılaşıyorum stringstream.

dava 1

O çözümlerden biri için bu leetcode problemi. Kullanımının çok uygun olduğunu gösterir. stringstream verimli ve özlüdür.

varsaymak a ve b dize formatında ifade edilen karmaşık sayılardır, çarpım sonucunu elde etmek istiyoruz a ve b ayrıca dize formatında. Kod aşağıdaki gibidir:

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() 

vaka 2

Aynı zamanda Leetcode problemi Bu, verilen yol dizesini basitleştirmenizi gerektirir stringstream kullanan çözümlerden biri gördüğüm en zarif olanı:

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; 
 }

Stringstream kullanılmadan, böyle özlü kod yazmak zor olurdu.


12
2018-06-27 14:22





Alfasayısal ve int, boş bir sınır girdiniz. mystr.

Daha sonra, ilk belirteci (boş sınırlandırılmış) bir int.

İlk belirteci, dönüşemeyen RS oldu intmyprice için sıfır bırakıyor, ve hepimiz sıfırın bir şeyin ne kadarını verdiğini biliyoruz.

Sadece int değerlerini ikinci kez girdiğinizde, her şey beklediğiniz gibi çalıştı.

Kodunuzun başarısız olmasına neden olan sahte RS idi.


2
2017-08-11 02:09