I have a simple function that builds a string representation of a simple 'Movie' object. I'm doing this ...
string Movie::getDisplayText() {
ostringstream oss;
oss << "Title: " << this->getTitle() << "\tYear: "+this->getYear() << "\tGenre: " << this->getGenre();
string ret = oss.str();
return ret;
}
But the string that gets built and returned looks like this ...
\�tle: Star Wars�B
Genre: Science-Fiction
When I add this line to test the values are valid ...
cout << "DEBUG Title: " << this->getTitle() << "\tYear: "+this->getYear() << "\tGenre: " << this->getGenre() << "\n" << endl;
... it outputs to 'cout' a correct looking string so I know the values are all initialized correctly ...
DEBUG title='Star Wars'; year='1977'; genre='Science-Fiction';
What's wrong with my ostringstream code?
You have this:
string Movie::getDisplayText() {
ostringstream oss;
oss << "Title: " << this->getTitle() << "\tYear: "+this->getYear() << "\tGenre: " << this->getGenre();
string ret = oss.str();
return ret;
}
It should be
string Movie::getDisplayText() {
ostringstream oss;
oss << "Title: " << this->getTitle() << "\tYear: " << this->getYear() << "\tGenre: " << this->getGenre();
string ret = oss.str();
return ret;
}
Not the difference after the \tYear:. The reason is that adding a string literal and an int together does not result in concatenation.
Related
I am trying to write a string to a binary file, to that effect I made this snippet:
std::string outname = filename.substr(0, filename.size() - 4) + std::string("_bin") + std::string(".sdf");
std::cout << "Writing results to: " << outname << "\n";
std::ofstream outfile(outname.c_str(), std::ofstream::binary);
std::stringstream ss;
ss << phi_grid.ni << " " << phi_grid.nj << " " << phi_grid.nk << std::endl;
ss << min_box[0] << " " << min_box[1] << " " << min_box[2] << std::endl;
ss << dx << std::endl;
for (unsigned int i = 0; i < phi_grid.a.size(); ++i)
{
ss << phi_grid.a[i] << std::endl;
}
outfile.write(ss.str().c_str(), ss.str().size());
outfile.close();
This however always writes to a text file, not a binary file. I don't udnerstand why, the flag is explicitely passed to the constructor.
is there any library or example for reading a csv file in C++ like the csv module in Python?
What I need is a function to read a csv file and put each column element of a row in a map with the header name as the key value.
I can answer myself. I wrote a CSVDict class.
#include <iterator>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <map>
class CSVDict {
public:
CSVDict(std::string fileName, int headerRow) {
file = std::ifstream(fileName);
for (int i = 0; i < headerRow; i++){ readNextRow(file); }
m_header = m_data;
}
std::string const& operator[](std::size_t index) const {
return m_data[index];
}
std::string const& operator[](std::string index) const {
return m_dataMap.find(index)->second;
}
bool readNextRowMap() {
readNextRow(file);
if (!file) return false;
m_dataMap.clear();
auto it_data = m_data.begin();
for (auto it = m_header.begin(); it != m_header.end(); ++it) {
m_dataMap[*it] = *it_data;
++it_data;
}
return true;
}
private:
void readNextRow(std::istream& str) {
std::string line;
std::getline(str, line);
if (!str) return;
std::stringstream lineStream(line);
std::string cell;
m_data.clear();
while (std::getline(lineStream, cell, ';')) {
m_data.push_back(cell);
}
}
std::vector<std::string> m_data;
std::vector<std::string> m_header;
std::map<std::string, std::string> m_dataMap;
std::ifstream file;
};
int main()
{
CSVDict dict("1.csv", 2);
while (dict.readNextRowMap()) {
std::cout << dict[0] << " " << dict[1] << " " << dict[2] << " " << dict[3] << " " << dict[4] << " " << dict[5] << " " << dict[6] << "\n";
}
CSVDict dict1("1.csv", 2);
dict1.readNextRowMap();
std::cout << dict1["ipField"] << " " << dict1["mdBeamEnergy"] << " " << dict1["mdBeamCurrent"] << " " << dict1["mcoBeamSizeId"] << " " << dict1["mdGantryAngle"] << " " << dict1["miLayerNumber"] << "\n";
dict1.readNextRowMap();
std::cout << dict1["ipField"] << " " << dict1["mdBeamEnergy"] << " " << dict1["mdBeamCurrent"] << " " << dict1["mcoBeamSizeId"] << " " << dict1["mdGantryAngle"] << " " << dict1["miLayerNumber"] << "\n";
dict1.readNextRowMap();
std::cout << dict1["ipField"] << " " << dict1["mdBeamEnergy"] << " " << dict1["mdBeamCurrent"] << " " << dict1["mcoBeamSizeId"] << " " << dict1["mdGantryAngle"] << " " << dict1["miLayerNumber"] << "\n";
dict.readNextRowMap();
std::cout << dict[0] << " " << dict[1] << " " << dict[2] << " " << dict[3] << " " << dict[4] << " " << dict[5] << " " << dict[6] << "\n";
return 0;
}
Example csv file:
#VALUES;;;;;;
ipField;mdBeamEnergy;mdBeamCurrent;mcoBeamSizeId;mdGantryAngle;miLayerNumber;mbRoomSwitchingLayer
24.30815;172.152971;24.30815;4;65;1;1
24.30815;172.152971;24.30815;4;65;2;0
24.30815;172.152971;24.30815;4;65;3;0
24.30815;172.152971;24.30815;4;65;4;0
24.30815;172.152971;24.30815;4;65;5;0
24.30815;172.152971;24.30815;4;65;6;0
24.30815;172.152971;24.30815;4;65;7;0
24.30815;172.152971;24.30815;4;65;8;0
usage (see main function in example):
class constructor needs to have the csv filename and the csv header line number
every readNextRowMap gets the values of the next line in the csv file
you can address the values either by number index or by header name
downside:
csv file has to have a header line
My problem is that no method that used to work on string works on wstring.
So I'm asking how I could easily clear wstring for aesthetical purpose.
My code right now:
while (!foundRightOne)
{
wstring cTitle;
ForegroundWindow = GetForegroundWindow();
cout << "FRGW " << ForegroundWindow << endl;
int len = GetWindowTextLengthW(ForegroundWindow) + 1;
wchar_t * windowTitle = new wchar_t[len];
GetWindowTextW(ForegroundWindow, windowTitle, len);
title += windowTitle;
// OUTPUT
cTitle = L"Title: ";
cTitle += title;
wcout << cTitle << endl;
cTitle = ' ';
//OUTPUT
keyPress = getchar();
system("CLS");
if (keyPress == 'y' || keyPress == 'Y')
{
foundRightOne = true;
}
}
Basically it loops while I press y or Y, I press when I see the right cTitle and after ~20 cycles cTitle gets fully filled with text from last cycles.
std::wstring::clear should work, as both it and std::string are std::basic_strings. Check out std::basic_string documentation if you're somehow having trouble.
#include <iostream>
int main()
{
std::string regularString("regular string!");
std::wstring wideString(L"wide string!");
std::cout << regularString << std::endl << "size: " << regularString.size() << std::endl;
std::wcout << wideString << std::endl << "size: " << wideString.size() << std::endl;
regularString.clear();
wideString.clear();
std::cout << regularString << std::endl << "size: " << regularString.size() << std::endl;
std::wcout << wideString << std::endl << "size: " << wideString.size() << std::endl;
}
Output:
regular string!
size: 15
wide string!
size: 12
size: 0
size: 0
Here's an ideone link to that code.
The following statement pipes all sorts of output to the console as a single string of text
std::cout << "Hi, my name is " << name_as_string << " and I am " << age_as_int << " years old, while weighing " << weight_as_double << " kilograms.";
Can we use this same syntax to build a string in a string variable? How is it done?
#include <sstream>
std::ostringstream ss;
ss << "Hi, my name is " << name_as_string;
ss << " and I am " << age_as_int << " years old, while weighing ";
ss << weight_as_double << " kilograms.";
std::string str = ss.str();
You can also use std::istringstream for multiple input, and std::stringstream for both input and output.
std::string str = "1 2 3 4 5";
std::istringstream ss(str);
int i;
while( ss >> i) {
std::cout << i;
}
stringstream will rescue you here;
#include <sstream>
std::stringstream ss;
ss << stuff << to << output;
std::string s = ss.str();
Use std::ostringstream
By using std::stringstream :
#include <sstream>
#include <iostream>
int main()
{
std::stringstream ss;
ss << "Hi, my name is " << name_as_string << " and I am " << age_as_int << " years old, while weighing " << weight_as_double << " kilograms.";
std::cout<<ss.str()<<std::endl;
}
cout << setw(20) << setiosflags(std::ios_base::left) << stamp; // this is char stamp[200] dataype.
cout << setw(1) << setiosflags(std::ios_base::left) << " ";
cout << setw(10) << setiosflags(std::ios_base::left) << appName1; // this is stl string data dtype
cout << setw(1) << setiosflags(std::ios_base::left) << ":";
cout << setw(15) << setiosflags(std::ios_base::left) << myname; // this is stl string data type.
cout << setw(1) << setiosflags(std::ios_base::left) << ":";
cout << setw(10) << setiosflags(std::ios_base::left) << myotherappname; // this is stl string data type.
cout << endl;
cout << finallyMyMessage; // this is char finallyMyMessage[200];
now my requirement is to put the above formatted text to file also in addition to console. I know that we can do this with ostringstream, but not able to sampel code how we can do this. Can any one help me in providing an exampel code how we can do this using ostringstream, later i can write to file using using ostreamobject.
Thanks!
Streams are polymorphic. They all derive from a common base class. That common base class defines most operations. Derived classes just setup the right stream buffer.
So use them polymorphically:
void write(std::ostream& os)
{
os << setw(20) << setiosflags(std::ios_base::left) << stamp;
os << setw(1) << setiosflags(std::ios_base::left) << " ";
os << setw(10) << setiosflags(std::ios_base::left) << appName1;
os << setw(1) << setiosflags(std::ios_base::left) << ":";
os << setw(15) << setiosflags(std::ios_base::left) << myname;
os << setw(1) << setiosflags(std::ios_base::left) << ":";
os << setw(10) << setiosflags(std::ios_base::left) << myotherappname;
os << endl;
os << finallyMyMessage;
}
// ...
write(std::cout);
std::ostringstream oss;
write(oss);
std::ofstream ofs("file.txt");
write(ofs);
If you have boost available, you can use the boost format library:
#include <boost/format.hpp>
cout << format("%20s %10s %15s %10s") % stamp % appName1 % myname % myotherappname << endl;
you can send the output to any ostream-derived type.
What you actually need is an ofstream to write to a file. Writing to a ostringstream first and then writing that string to both console and file may indeed be faster, but let's start with how to write to a file:
ostream& st = use_file? ofstream("output.txt"): cout;
ofstream st("output.txt");
st << setw(20) << setiosflags(std::ios_base::left) << stamp; // this is char stamp[200] dataype.
st << setw(1) << setiosflags(std::ios_base::left) << " ";
st << setw(10) << setiosflags(std::ios_base::left) << appName1; // this is stl string data dtype
st << setw(1) << setiosflags(std::ios_base::left) << ":";
st << setw(15) << setiosflags(std::ios_base::left) << myname; // this is stl string data type.
st << setw(1) << setiosflags(std::ios_base::left) << ":";
st << setw(10) << setiosflags(std::ios_base::left) << myotherappname; // this is stl string data type.
st << endl;
st << finallyMyMessage; // this is char finallyMyMessage[200];
You can use the OS to do this.
On unix you have tee
./a.out | tee plop.txt
Dumps output to file "plop.txt" and console.
Pretty straightforward really...
#include <sstream>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>
int main(int argc, char* argv[])
{
std::ostringstream oss;
// defined just so my example will compile
std::string stamp, appName1, myname, myotherappname, finallyMyMessage;
oss << std::setw(20) << std::setiosflags(std::ios_base::left) << stamp; // this is char stamp[200] dataype.
oss << std::setw(1) << std::setiosflags(std::ios_base::left) << " ";
oss << std::setw(10) << std::setiosflags(std::ios_base::left) << appName1; // this is stl string data dtype
oss << std::setw(1) << std::setiosflags(std::ios_base::left) << ":";
oss << std::setw(15) << std::setiosflags(std::ios_base::left) << myname; // this is stl string data type.
oss << std::setw(1) << std::setiosflags(std::ios_base::left) << ":";
oss << std::setw(10) << std::setiosflags(std::ios_base::left) << myotherappname; // this is stl string data type.
oss << std::endl;
oss << finallyMyMessage; // this is char finallyMyMessage[200];
// ...
std::ofstream outfile("something.txt"); // open a file for writing
outfile << oss.str(); // output the ostringstream's string to the ofstream
outfil.close();
// or if you need a char*...
std::string str(oss.str());
usecharstar(str.c_str());
return 0;
}
You don't have to repeat the left adjust for each output, it sticks to the stream.
You also don't have to change width for each output, as it sets the minimum width for the field. That makes width(1) totally meaningless for a single character output.
This is easy. You are just trying too hard!