How can I stop ostringstream (oss) from adding to/overwriting predefined variables? - c++

I'm relatively new to C++ and have come across the use of ostringstream oss as a way to include variables in an output and set it as a string.
Ex.
string getDate(){
oss << _month << "," << _day << "," << _year ; //date format
string date = oss.str(); //date as a string
return date;
}
My issue is that every time I call the method getDate() through an object, it adds the previously recorded output into, what I believe is called the "stream."
Ex.
//private variables w default values
int _day{-1};
int _month{-2};
int _year{-3};
int main() {
//init objects
Bday nothing{};
Bday Clyde (12,24,1993);
Bday Harry("Harry",11,05,2002);
//outputs
//expected to return default values (-2,-1,-3)
cout << "Default Values: "<< nothing.getDate() << endl;
//expected to return Clyde's date only: 12,24,1993
cout << "Date Only: " << Clyde.getDate() << endl;
// expect to return Harry's date: (11,05,2002)
cout << "Harry's Bday: " << Harry.getDate() << endl;
return 0;
}
But instead the output is the following:
Default Values:
Date Only: -2,-1,-3
Harry's Bday: -2,-1,-312,24,1993
Process finished with exit code 0
Any way to protect the value of oss or at least make it so that it gets updated rather than added to?

If you want to clear your stream, there are two choices.
Use local stream
string getDate(){
std::ostringstream oss;
oss << _month << "," << _day << "," << _year ; //date format
string date = oss.str(); //date as a string
return date;
}
Clear your stream after use
string getDate(){
oss << _month << "," << _day << "," << _year ; //date format
string date = oss.str(); //date as a string
oss.str(""); // clear stream
return date;
}

Related

How to read a stream with comma separated values in C++?

I would like to emphasize on a fundamental question below:
Assume you have a CSV file and fill cells with Input Headers
The code should read this from .csv file and write the results into .csv file. It is nice to also code output total number of cases, plus average of cases. Here is a taken sample form SO and I would like to see how this can be efficiently adopted to complete this basic example.
void create()
{
// file pointer
fstream fout;
// opens an existing csv file or creates a new file.
fout.open("reportcard.csv", ios::out | ios::app);
cout << "Enter the details of 5 students:"
<< " roll name maths phy chem bio";
<< endl;
int i, roll, phy, chem, math, bio;
string name;
// Read the input
for (i = 0; i < 5; i++) {
cin >> roll
>> name
>> math
>> phy
>> chem
>> bio;
// Insert the data to file
fout << roll << ", "
<< name << ", "
<< math << ", "
<< phy << ", "
<< chem << ", "
<< bio
<< "\n";
}
}
Also, Read a particular record
void read_record()
{
// File pointer
fstream fin;
// Open an existing file
fin.open("reportcard.csv", ios::in);
// Get the roll number
// of which the data is required
int rollnum, roll2, count = 0;
cout << "Enter the roll number "
<< "of the student to display details: ";
cin >> rollnum;
// Read the Data from the file
// as String Vector
vector<string> row;
string line, word, temp;
while (fin >> temp) {
row.clear();
// read an entire row and
// store it in a string variable 'line'
getline(fin, line);
// used for breaking words
stringstream s(line);
// read every column data of a row and
// store it in a string variable, 'word'
while (getline(s, word, ', ')) {
// add all the column data
// of a row to a vector
row.push_back(word);
}
// convert string to integer for comparision
roll2 = stoi(row[0]);
// Compare the roll number
if (roll2 == rollnum) {
// Print the found data
count = 1;
cout << "Details of Roll " << row[0] << " : \n";
cout << "Name: " << row[1] << "\n";
cout << "Maths: " << row[2] << "\n";
cout << "Physics: " << row[3] << "\n";
cout << "Chemistry: " << row[4] << "\n";
cout << "Biology: " << row[5] << "\n";
break;
}
}
if (count == 0)
cout << "Record not found\n";
}
[1]: https://i.stack.imgur.com/q6VfZ.png
I've mainly concentrated on adding overloads for operator<< and operator>> since you showed some interest in those earlier and describe what they are doing in comments in the code.
Since you are mixing input and output from streams that are comma separated and other streams I've added an adapter for CSV streaming as well as overloads for streaming to/from a user.
First, create a class to keep all data that belongs together in one data record. I've made it a simple struct here, which is a class with public access to its members per default.
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
// your student record
struct student {
std::string name; // It's usually good to have larger types first so name goes first
int roll;
int math;
int phy;
int chem;
int bio;
};
// read a student from an istream (like std::cin) - whitespace separated
std::istream& operator>>(std::istream& is, student& s) {
return is >> s.roll >> s.name >> s.math >> s.phy >> s.chem >> s.bio;
}
// write a student to an ostream (like std::cout)
std::ostream& operator<<(std::ostream& os, const student& s) {
return os << "Details of Roll " << s.roll << ":\n"
<< "Name: " << s.name << '\n'
<< "Maths: " << s.math << '\n'
<< "Physics: " << s.phy << '\n'
<< "Chemistry: " << s.chem << '\n'
<< "Biology: " << s.bio << '\n';
}
//--------------------------------------------------------------------------------------
// An adapter for comma separated streaming
struct CSVStudent {
CSVStudent(student& s) : stud(s) {}
CSVStudent(const CSVStudent&) = delete;
// The CSVStudent holds a reference to a "student"
student& stud;
};
// read a record from an istream - comma separated
std::istream& operator>>(std::istream& is, CSVStudent& csvstud) {
std::string line;
student& s = csvstud.stud; // an alias to the student to have to type less
if(std::getline(is, line)) { // read a complete line
// put the line in an istringstream for extraction:
std::istringstream ss(line);
char delim; // a dummy for reading commas
// Extract the comma separated values. "delim" is not checked so it could be
// any char breaking up the int:s.
//
// The below does things in the following order:
// 1. "ss >> s.roll >> delim"
// This extracts roll and a comma and returns
// a reference to ss, which is used in 2.
// 2. std::getline(ss, s.name, ',')
// Extracts a string until a comma is encountered.
// 3. Normal extraction for the rest of the int:s with the
// dummy variable "delim" where the commas are supposed to be.
if(not(std::getline(ss >> s.roll >> delim, s.name, ',') >> s.math >> delim >>
s.phy >> delim >> s.chem >> delim >> s.bio)) {
// If we get here, the extraction from the istringstream failed, so set
// the failstate on the istream too. Note the "not" on the line above.
is.setstate(std::ios::failbit);
}
}
return is;
}
// write a record to an ostream - comma separated
std::ostream& operator<<(std::ostream& os, const CSVStudent& csvstud) {
const student& s = csvstud.stud;
os << s.roll << ',' << s.name << ',' << s.math << ',' << s.phy << ',' << s.chem
<< ',' << s.bio << '\n';
return os;
}
//--------------------------------------------------------------------------------------
// get all students in the file as a std::vector<student>
std::vector<student> read_student_file(const std::string& filename) {
std::vector<student> retval;
std::ifstream fin(filename);
if(fin) { // file opened successfully
student stud;
CSVStudent csvstud{stud}; // holds a reference to stud
// loop for as long as student records can be read successfully
while(fin >> csvstud) // use the csv sdapter
retval.push_back(stud); // and put the stud in the vector
}
return retval;
}
//--------------------------------------------------------------------------------------
void create(const std::string& filename) {
// open an existing csv file or creates a new file.
std::ofstream fout(filename, std::ios::out | std::ios::app);
if(fout) {
std::cout << "Enter the details of 5 students:"
" roll name maths phy chem bio\n";
// Read the input
for(int i = 0; i < 5; i++) {
student stud;
std::cout << (i + 1) << ": ";
if(std::cin >> stud) {
// Insert the data to file if one was entered successfully
fout << CSVStudent(stud); // uses the adapters operator<<
} else {
std::cerr << "You failed to enter data for student " << (i + 1) << '\n';
break;
}
}
}
}
//--------------------------------------------------------------------------------------
int main() {
std::string filename = "reportcard.csv";
std::vector<student> students = read_student_file(filename);
std::cout << "There are " << students.size() << " students in the file.\n";
if(not students.empty()) {
// show the last record if there are any records in the file
std::cout << "Record " << students.size() << " is:\n\n";
std::cout << students.back() << '\n';
}
// create 5 new records
create(filename);
}
If reportcard.csv contains this:
1,Ted,1,2,3,4
2,Foo,2,3,4,5
3,Bar,3,4,5,6
4,Baz,4,5,6,7
5,Bork,5,6,7,8
The program should start up like this:
There are 5 students in the file.
Record 5 is:
Details of Roll 5:
Name: Bork
Maths: 5
Physics: 6
Chemistry: 7
Biology: 8
Enter the details of 5 students: roll name maths phy chem bio
1: <and here is where you're supposed to enter the first of 5 new students>

Formatting stream spaces

I have been trying to use .pushback to format my string so that it prints just a space between every word.
So I was trying to use a .push_back, however that doesn't work with integers.
std::string FormatVehicleString(std::string year,
std::string make,
std::string model,
double price,
double mileage)
{
year.push_back(5);
make.push_back(5);
model.push_back(5);
price.push_back(5);
mileage.push_back(5);
}
Can someone point me in the right direction, is there another value type that will incorporate strings and integers?
One option is to use a std::ostringstream.
std::string FormatCarInfo(std::string year,
std::string make,
std::string model,
double price,
double mileage)
{
std::ostingstream out;
out << year << " ";
out << make << " ";
out << model << " ";
out << price << " ";
out << mileag ;
return out.str();
}
Another option is to use std::to_string.
std::string FormatCarInfo(std::string year,
std::string make,
std::string model,
double price,
double mileage)
{
return ( year + " " + make + " " + model + " " +
std::to_string(price) + " " + std::to_string(mileage) );
}

Is it possible to use a Mutator within a Mutator in C++?

Good afternoon!
I did some quick searching around and I was having a hard time trying to figure out how I should go about doing what I need to do.
For this program, we are creating a basic work ticket class. Each attribute has its own mutator and accessor, but in addition there will be a mutator that takes all the attributes as parameters and set them all in one go.
The main reason I can't just use the constructor to place in the values, is because for this mutator we have to perform some validation on the values. For the individual attribute mutators, two of them already have the validation performed in their mutator. The other two only have to be validated when the setWorkTicket mutator is called.
Is there a way to call a mutator from within a mutator? Or would the only way to make sure it validates the two attributes be to copy and paste their validation from their mutators into the setWorkTicket?
If you need clarification, or what I'm asking is unclear just let me know. I have attached the class in question.
/** Lab2.cpp
* #desc SOME DESCRIPTION
* #author Aaron, Aaron
* #since 24 September 2014
**/
#include <iostream>
#include <iomanip>
#include <string>
#include "MyInputValidation.h"
#include <sstream>
#include <stdexcept>
using namespace std;
class WorkTicket
{
public:
/*** PARAMETERIZED CONSTRUCTOR ***/
WorkTicket(): myWorkTicketNumber(0), myClientID(""), myDay(1), myMonth(1), myYear(2000), myIssue("") {}
WorkTicket(int workTicketNumber, string clientID, int day, int month, int year, string issue);
/*** ACCESSORS ***/
int getWorkTicketNumber() const { return myWorkTicketNumber; }
string getClientID() const { return myClientID; }
string getDate(int myDay, int myMonth, int myYear) const;
string getIssue() const { return myIssue; }
void showWorkTicket() const;
/*** MUTATORS ***/
void setWorkTicketNumber(int workTicketNumber);
void setClientID(string clientID) { myClientID = clientID; }
void setDate(int day, int month, int year);
void setIssue(string issue) { myIssue = issue; }
bool setWorkTicket(int workTicketNumber, string clientID, int day, int month, int year, string issue);
private:
int myWorkTicketNumber;
string myClientID;
int myDay;
int myMonth;
int myYear;
string myIssue;
};
/*** MAIN ***/
int main ()
{
// Output an information header
cout << "=============================" << endl
<< "=== WorkTicket Class Demo ===" << endl
<< "=============================" << endl;
try
{
// DECLARATIONS
WorkTicket ticketOne(1, "Aaron", 24, 9, 2014, "Printer not accessible from networked computers.");
ticketOne.showWorkTicket();
}
catch(const exception& ex)
{
cerr << ex.what(); // display the exception message.
}
// done.
cout << endl << endl;
return 0;
}
/*** PARAMETERIZED CONSTRUCTOR ***/
WorkTicket::WorkTicket(int workTicketNumber, string clientID, int day, int month, int year, string issue)
{
setWorkTicketNumber(workTicketNumber);
setClientID(clientID);
setDate(day, month, year);
setIssue(issue);
}
/*** ACCESSORS ***/
string WorkTicket::getDate(int myDay, int myMonth, int myYear) const
{
stringstream dateReturn;
dateReturn << myDay << "-" << myMonth << "-" << myYear;
return dateReturn.str();
}
void WorkTicket::showWorkTicket() const
{
cout << setw(20) << "\nWork Ticket Number: " << myWorkTicketNumber << endl
<< setw(20) << left << "Client ID: " << myClientID << endl
<< setw(20) << left << "Ticket Date: " << myDay << "-" << myMonth << "-" << myYear << endl
<< setw(20) << left << "Issue: " << myIssue << endl;
}
/*** MUTATORS ***/
void WorkTicket::setWorkTicketNumber(int workTicketNumber)
{
// Local declarations
const int MIN_TICKET_NUMBER = 1; // Ace
if(workTicketNumber < MIN_TICKET_NUMBER)
{
// declare a stringstream object
stringstream strOut;
// build a descriptive error string.
strOut << "\nTicket Number argument: " << workTicketNumber << " is out of range. " << endl
<< "Ticket Number must be greater than or equal to " << MIN_TICKET_NUMBER << ". ";
// throw an out_of_range exception initialized with
// the error string
throw invalid_argument(strOut.str());
}
else // otherwise, the rank parameter is fine
{
// assign the parameter to the member variable
myWorkTicketNumber = workTicketNumber;
}
}
void WorkTicket::setDate(int day, int month, int year)
{
const int MIN_DAY_MONTH = 1;
const int MAX_DAY = 31;
const int MAX_MONTH = 12;
const int MIN_YEAR = 2000;
const int MAX_YEAR = 2099;
stringstream strOut;
if(day < MIN_DAY_MONTH || day > MAX_DAY)
{
// build a descriptive error string.
strOut << "\nDate argument: " << day << " is out of range. " << endl
<< "Day must be greater than or equal to " << MIN_DAY_MONTH
<< " and less than or equal to " << MAX_DAY << ". ";
// throw an out_of_range exception initialized with
// the error string
throw invalid_argument(strOut.str());
}
else if(month < MIN_DAY_MONTH || month > MAX_MONTH)
{
// build a descriptive error string.
strOut << "\nDate argument: " << month << " is out of range. " << endl
<< "Month must be greater than or equal to " << MIN_DAY_MONTH
<< " and less than or equal to " << MAX_MONTH << ". ";
// throw an out_of_range exception initialized with
// the error string
throw invalid_argument(strOut.str());
}
else if(year < MIN_YEAR || year > MAX_YEAR)
{
// declare a stringstream object
stringstream strOut;
// build a descriptive error string.
strOut << "\nDate argument: " << year << " is out of range. " << endl
<< "Year must be greater than or equal to " << MIN_YEAR
<< " and less than or equal to " << MAX_YEAR << ". ";
// throw an out_of_range exception initialized with
// the error string
throw invalid_argument(strOut.str());
}
else // otherwise, the rank parameter is fine
{
// assign the parameter to the member variable
myDay = day;
myMonth = month;
myYear = year;
}
}
bool WorkTicket::setWorkTicket(int workTicketNumber, string clientID, int day, int month, int year, string issue)
{
return true;
}
What's wrong with just doing:
bool WorkTicket::setWorkTicket(int workTicketNumber, string clientID, int day, int month, int year, string issue)
{
setWorkTicketNumber(workTicketNumber);
setDate(day, month, year);
setClientID(clientID);
setIssue(issue);
return true;
}
You can either let the exceptions propagate or catch them in setWorkTicket() and return false depending on what you need.

Data doesn't load into c++ vector correctly

I am trying to load a text file and import the contents into a vector of structs.
Here are my definitions
typedef struct
{
string pcName, pcUsername, pcPassword, pcMessage, pcAdvertisement; //I know that
//this is incorrect convention. It was originally a char*
}
ENTRY;
vector<ENTRY> entries;
fstream data;
Here is my display data function
void DisplayData()
{
std::cout << (int)(entries.size() / 5) <<" entries" << endl;
for(int i = 1; i <=(int)entries.size()/5; i++)
{
cout << endl << "Entry " << i << ":" << endl
<< "Name: " << entries[i].pcName << endl
<< "Username: " << entries[i].pcUsername << endl
<< "Password: " << entries[i].pcPassword << endl
<< "Message: " << entries[i].pcMessage << endl
<< "Advertisement: " << entries[i].pcAdvertisement << endl;
}
}
and here is my Load Data function
bool LoadData(const char* filepath)
{
std::string lineData ;
int linenumber = 1 ;
data.open(filepath, ios::in);
ENTRY entry_temp;
if(!data.is_open())
{
cerr << "Error loading file" << endl;
return false;
}
while(getline(data, lineData))
{
if(linenumber==1) {entry_temp.pcName = lineData;}
else if(linenumber==2) {entry_temp.pcUsername = lineData;}
else if(linenumber==3) {entry_temp.pcPassword = lineData;}
else if(linenumber==4) {entry_temp.pcMessage = lineData;}
else if(linenumber==5) {entry_temp.pcAdvertisement = lineData;}
entries.push_back(entry_temp);
if(linenumber == 5)
{
linenumber = 0;
}
linenumber++;
}
data.close();
puts("Database Loaded");
return true;
}
Here is the text file I am loading:
Name1
Username1
Password1
Message1
Ad1
And here is the result of the display data function after calling load data:
1 entries
Entry 1:
Name: Name1
Username Username1
Password:
Message:
Advertisement:
As you can see, the first two load but the last three don't. When I did this with an array instead of a vector, it worked fine so I don't know what I'm doing wrong. Thanks.
I suggest that you read each line directly into the data field where it goes:
getline(data, entry_temp.pcName);
getline(data, entry_temp.pcUsername);
getline(data, entry_temp.pcPassword);
getline(data, entry_temp.pcMessage);
getline(data, entry_temp.pcAdvertisement);
entries.push_back(entry_temp);
This makes your intent much clearer than your current while loop. It also creates a single entry for all 4 input lines rather than one for each input line (with the other three blank). Now you can read several "entries" by using a while loop that checks if you have reached the end of the file.
Doing this will also make printing out the data much easier since the vector will have exactly the number of entries rather than five times as many as you expect (which also eats up a lot more memory than you need to).
Your DisplayData function is a little weird, and so is your LoadData.
Your LoadData pushes back a new copy of the current ENTRIES entry with every line. Your DisplayData starts at 1 (which is not the beginning of any vector or array), and iterates only up to the 1/5th entry of the entire vector.
This needs a heavy rework.
First, the size() member of any standard container returns the number of elements that it contains, and will not take the number of fields in a contained struct into account.
For future reference, you'll want to post your question in a complete, standalone example that we can immediately compile to help. (see http://sscce.org/)
Try this modified data, which runs correctly, and see if you can tell what is being done differently:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
typedef struct
{
string pcName, pcUsername, pcPassword, pcMessage, pcAdvertisement;
}
ENTRY;
vector<ENTRY> entries;
fstream data;
bool LoadData(const char* filepath)
{
std::string lineData ;
int linenumber = 1 ;
data.open(filepath, ios::in);
ENTRY entry_temp;
if(!data.is_open())
{
cerr << "Error loading file" << endl;
return false;
}
while(getline(data, lineData))
{
if(linenumber==1) {entry_temp.pcName = lineData;}
else if(linenumber==2) {entry_temp.pcUsername = lineData;}
else if(linenumber==3) {entry_temp.pcPassword = lineData;}
else if(linenumber==4) {entry_temp.pcMessage = lineData;}
else if(linenumber==5) {entry_temp.pcAdvertisement = lineData;}
if(linenumber == 5)
{
entries.push_back(entry_temp);
linenumber = 0;
}
linenumber++;
}
data.close();
puts("Database Loaded");
return true;
}
void DisplayData()
{
std::cout << entries.size() <<" entries" << endl;
for(int i = 0; i < entries.size(); i++)
{
cout << endl << "Entry " << i << ":" << endl
<< "Name: " << entries[i].pcName << endl
<< "Username: " << entries[i].pcUsername << endl
<< "Password: " << entries[i].pcPassword << endl
<< "Message: " << entries[i].pcMessage << endl
<< "Advertisement: " << entries[i].pcAdvertisement << endl;
}
}
int main()
{
LoadData("/tmp/testdata");
DisplayData();
return (0);
}
While I think #code-guru has the right idea, I'd take the same idea just a little further, and make your code work a little more closely with the standard library. I'd do that by reading a data item with a stream extractor, and displaying it with stream inserter. So, the extractor would look something like this:
std::istream &operator>>(std::istream &is, ENTRY &e) {
getline(is, e.pcName);
getline(is, e.pcUsername);
getline(is, e.pcPassword);
getline(is, e.pcMessage);
getline(is, e.pcAdvertisement);
return is;
}
..and the inserter would look something like this:
std::ostream &operator<<(std::ostream &os, ENTRY const &e) {
os << e.pcName << "\n";
os << e.pcUsername << "\n";
os << e.pcPassword << "\n";
os << e.pcMessage << "\n";
os << e.pcAdvertisement << "\n";
return os;
}
With those in place, loading and displaying the data becomes fairly straightforward.
Load the data:
std::ifstream in("yourfile.txt");
std::vector<ENTRY> data((std::istream_iterator<ENTRY>(in)),
std::istream_iterator<ENTRY>());
Display the data:
for (auto const & e: data)
std::cout << e << "\n";
For the moment, I haven't tried to duplicate the format you were using to display the data -- presumably the modifications for that should be fairly obvious.

learning c++, outputting variable in structure

Say I have a structure as follows
struct stock{
string ticker;
double price;
double volume;
double eps;
};
If I want to output one of the variables such as price when asked for it would I have to do a large if/else or switch statement to match up the user input with the member or is there a more elegant way to do it because I know stock.userInput does not work.
there's no special keyword to find your variable(sorry to burst your bubble), You would have to use a logical statement. It would go along:
cout << "What would you like to see? (1)Price (2)etc...etc...";
cin >> input;
switch(input)
{
case 1:
cout << Obj.Price;
break;
case 2:
cout << //....
break;
}
I personally like using keys and a switch statement, it tends to be a lot cleaner and easier to go back and modify later in the program.
struct stock s1;
cout<<" price is:"<< s1.price;
If you want to get rid of the large switch/if statement, you can use map with string and a pointer-to-member. Assuming your stock struct, you can use:
Define the map (for doubles here) and initialize it:
std::map<std::string,double stock::*> double_members;
double_members["price"]=&stock::price;
double_members["volume"]=&stock::volume;
double_members["eps"]=&stock::eps;
And use it to look up some values:
stock stock1;
std::string input;
std::cin >> input;
if (double_members.find(input)!=double_members.end())
std::cerr << "Value for " << input << " is: " << stock1.*double_members[input] << std::endl;
else
std::cerr << "There's no field called " << input << std::endl;
It's limited to a single type, but you can't have a statement like std::cerr << A; and have A's type resolved during runtime. If you care only about string (or any other, but always the same) representation of the values, then you can wrap maps for different types in a class that searches all of them and outputs the value converted to a string (or something).
But it's probably easier to have the if statement, unless the struct is really big.
If it's okay with you that it doesn't work with g++ 4.7.1 and earlier (but does work with Visual C++ 11.0 and later), then like …
#include <sstream> // std::ostringstream
#include <string> // std::string
using namespace std;
struct Stock
{
string ticker;
double price;
double volume;
double eps;
string toString() const
{
ostringstream stream;
stream
<< "Stock("
<< "ticker='" << ticker << "', "
<< "price=" << price << ", "
<< "volume=" << volume << ", "
<< "eps=" << eps
<< ")";
return stream.str();
}
Stock(): ticker(), price(), volume(), eps() {}
};
#include <iostream>
#include <regex>
#include <stdexcept>
#include <stdlib.h>
bool err( string const& s )
{
cerr << "!" << s << endl;
exit( EXIT_FAILURE );
}
string lineFromUser( string const& prompt )
{
string line;
cout << prompt;
getline( cin, line )
|| err( "oh my, failed to read line of input" );
return line;
}
void cppMain()
{
Stock stock;
stock.price = 1.23;
string const s = stock.toString();
cout << s << endl;
string const fieldname = lineFromUser( "Which field u want? " );
regex const valuespec( fieldname + "\\s*\\=\\s*([^,\\)]*)" ); //
smatch what;
if( regex_search( s, what, valuespec ) )
{
cout << "As we all know already, " << what.str() << "." << endl;
}
else
{
cout
<< "!Sorry, there's no field named '"
<< fieldname << "'"
<< endl;
}
}
int main()
{
try
{
cppMain();
return EXIT_SUCCESS;
}
catch( exception const& x )
{
cerr << "!" << x.what() << endl;
}
return EXIT_FAILURE;
}
Example usage:
[d:\dev\test]
> foo
Stock(ticker='', price=1.23, volume=0, eps=0)
Which field u want? eps
As we all know already, eps=0.
[d:\dev\test]
> _