I am trying to logg my events so i thought of using ostringstream to save the output and then send it to a function where i print the output on screen and on file fstream fileOut. It wont work, it just gives me random numbers and seem not to output all new outputs on the same file but just creates a new file everytime and deletes what was on it before. How do i do this?
where the print happens:
void Event::output(ostringstream* info) {
std::cout << info << std::endl;
fileOut << info << std::endl;
}
where the output happens:
ostringstream o;
if (time < SIM_TIME) {
if (status->tryAssemble(train)) {
Time ct;
ct.fromMinutes(time);
o << ct << " Train [" << train->getTrainNumber() << "] ";
Time t(0, DELAY_TIME);
o << "(ASSEMBLED) from " << train->getStart() << " " << train->getScheduledStartTime() <<
" (" << train->getStartTime() << ") to " << train->getDest() << " " << train->getScheduledDestTime() <<
" (" << train->getDestTime() << ") delay (" << train->getDelay() << ") speed=" << train->getScheduledSpeed() <<
" km/h is now assembled, arriving at the plateform at " << train->getStartTime() - t << endl << endl;
fileOut.open("testfile.txt", std::ios::out);
if (!fileOut.is_open())
exit(1); //could not open file
output(&o);
train->setStatus(ASSEMBLED);
time += ASSEMBLE_TIME;
Event *event = new ReadyEvent(simulation, status, time, train);
simulation->addEvent(event);
It wont work, it just gives me random numbers
You are passing the ostringstream to your function by pointer. There is no operator<< that takes an ostringstream* pointer as input and prints its string content. But there is an operator<< that takes a void* as input and prints the memory address that the pointer is pointing at. That is the "random numbers" you are seeing. ANY type of pointer can be assigned to a void* pointer.
You need to dereference the ostringstream* pointer to access the actual ostringstream object. Even so, there is still no operator<< that takes an ostringstream as input. However, ostringstream has a str() method that returns a std::string, and there is an operator<< for printing a std::string:
void Event::output(ostringstream* info) {
std::string s = info->str();
std::cout << s << std::endl;
fileOut << s << std::endl;
}
That being said, you should pass the ostringstream by const reference instead of by pointer, since the function does not allow a null ostringstream to be passed in, and it does not modify the ostringstream in any way:
void Event::output(const ostringstream &info) {
std::string s = info.str();
std::cout << s << std::endl;
fileOut << s << std::endl;
}
...
output(o);
seem not to output all new outputs on the same file but just creates a new file everytime and deletes what was on it before.
That is because you are not opening the file with either the app or ate flag 1, so it creates a new file each time, discarding the contents of any existing file. If you want to append to an existing file instead, you need to either:
use the ate flag to "seek to the end of stream immediately after open":
fileOut.open("testfile.txt", std::ios::out | std::ios::ate);
use the app flag to "seek to the end of stream before each write":
fileOut.open("testfile.txt", std::ios::out | std::ios::app);
1: if fileOut is a std::ofstream, you do not need to specify std::ios::out explicitly.
Related
I have a bit of an issue with my program. I have a function void loadData() which will load the data from a text file customers.txt and store each line of data into a Linked List. My concern is, specifically with how I/O works. I managed to get the data from the text file into and stored into a linked list data member variable. When i call that variable i get the answer i want printed onto the console.
std::cout << "Group Name: " << tempCustomer->groupName << std::endl;
However, i decided to run a console output command later in the function to test if all the variables had the right data, i realize that it was all over the place. I'm not sure why its not working.
Here is the loadData() function
void Groups::loadData(){
fin.open("customers.txt");
char holder[MAX_SIZE];
if(!fin.is_open())
std::cerr << "Could not access file" << std::endl;
else{
while(!fin.eof()){
Customers *tempCustomer = new Customers;
fin.getline(holder,MAX_SIZE,';');
tempCustomer->groupName = holder;
std::cout << "Group Name: " << tempCustomer->groupName << std::endl;
fin.getline(holder,MAX_SIZE,';');
tempCustomer->name = holder;
fin.getline(holder,MAX_SIZE,';');
tempCustomer->email = holder;
fin >> tempCustomer->choice;
fin.get(); //gets the last character, which is '\n'
fin.ignore(); //ignores the next character which is the '\n'
tempCustomer->next = NULL;
std::cout << "What does the temp Node Store?" << std::endl;
std::cout << "Group Name: " << tempCustomer->groupName << std::endl;
std::cout << "Name: " << tempCustomer->name << std::endl;
std::cout << "Email: " << tempCustomer->email << std::endl;
std::cout << "Choice: " << tempCustomer->choice << std::endl;
//addCustomerToLL(tempCustomer);
tempCustomer = NULL;
delete tempCustomer;
}
}
fin.close();
}
Here is the Console out put:
Group Name: Jonathan Group
What does the temp Node Store?
Group Name: vazquez.jonathan#pcc.edu
Name: vazquez.jonathan#pcc.edu
Email: vazquez.jonathan#pcc.edu
Choice: 2
Here is the text file customers.txt
Jonathan Group;Jonathan;vazquez.jonathan#pcc.edu;2
This is a school assignment, i'm to store all the customers from the text file into a linked list. I'm also to use c strings as strings rather than c++ version of strings. Let me know if the other files are necessary, i didnt include them since well nothing in this function utilize anything else outside the func besides the ifstream fin; private variable i have in the class and the const int MAX_SIZE = 256; global variable.
Assuming you're not allowed to use std::string, you need to allocate memory for each string.
So replace this:
fin.getline(holder,MAX_SIZE,';');
tempCustomer->groupName = holder;
with:
fin.getline(holder, MAX_SIZE, ';');
char *s = new char[strlen(holder) + 1];
strcpy(s, holder);
tempCustomer->groupName = s;
You should release the memory you allocate when you no longer need it, so create a destructor for your Customers class:
Customers::~Customers()
{
delete[] groupName;
}
It's because the holder changes when you read a new line,but your all string in your Customer points to the same holder which stores the last line you read.
Change the type of name,email etc to char[MAX_SIZE] may help.
// Update the server status xml
string filelocation ("/var/www/html/index.xml");
string firstline ("<server>\n");
string secondline ("\t<current>" + msg.getCount() + "</current>\n");
string thirdline ("\t<highest>" + "--" + "</highest>\n");
string fourthline ("\t<status>Online</status>\n")
string finalline ("</server>");
fstream file;
file.open(filelocation);
file.write(firstline + secondline + thirdline + fourthline + finalline);
string updateFlush ("Server Status updated.");
printf("%s\n", updateFlush);
file.close();
Note that msg.getCount() is a function in the same file to get player count from the central server.
Gives out errors about an operands const char*. Something to do with + or -
Thanks
Take a look at the line
string secondline ("\t<current>" + msg.getCount() + "</current>\n");
"\t<current>" is a const char *
msg.getCount() looks like an int or size_t
</current>\n again is a const char *
Adding a const char * to an int or size_t creates a new const char * pointing to a different address.
The same happens in the line
string thirdline ("\t<highest>" + "--" + "</highest>\n");
Here you are adding pointers together. The result is a pointer pointing to a more or less random address.
And in these two lines:
string updateFlush ("Server Status updated.");
printf("%s\n", updateFlush);
You are creating a C++ string-object and trying to print it using a C print function with a format string that requires a char *.
You are mixing C and C++ or stream based I/O with conventional I/O.
In current C++ you should do it this way:
string filelocation ("/var/www/html/index.xml");
fstream file;
file.open(filelocation);
file
<< "<server>\n"
<< "\t<current>" << msg.getCount() << "</current>\n"
<< "\t<highest>" << "--" << "</highest>\n"
<< "\t<status>Online</status>\n"
<< "</server>";
string updateFlush ("Server Status updated.");
cout << updateFlush << std::endl;
file.close();
Or even more readable:
auto file = std::ofstream("/var/www/html/index.xml");
file
<< "<server>" << std::endl
<< "\t<current>" << msg.getCount() << "</current>" << std::endl
<< "\t<highest>" << "--" << "</highest>" << std::endl
<< "\t<status>Online</status>" << std::endl
<< "</server>";
file.close();
std::cout << "Server status updated." << std::endl;
If operating with streams use std::endl to output a newline. It outputs the correct newline for the operation system (CRLF or LF or whatever) and it flushes the stream.
To use std::cout you have to include <iostream> and for std::ofstream include <fstream>.
If you like it short, you could even do this:
std::ofstream("/var/www/html/index.xml")
<< "<server>" << std::endl
<< "\t<current>" << msg.getCount() << "</current>" << std::endl
<< "\t<highest>" << "--" << "</highest>" << std::endl
<< "\t<status>Online</status>" << std::endl
<< "</server>";
std::cout << "Server status updated." << std::endl;
I have to print some objects fields to a file. I overloaded operator<<, and I have a method "draw" that uses it.
How can I print it to file?
ostream& operator <<(ostream& out, const Widget& obj)
{
int* colors2 = new int[3];
colors2 = obj.getbackgroundColor().getColor();
int* colors = new int[3];
colors = obj.getTextColor().getColor();
out << "[position (" << obj.getPosition().getX() << ","
<< obj.getPosition().getY() << ") ,";
out << "width (" << obj.getWidth() << ") ";
out << "height (" << obj.getHeight() << ") ,";
out << "text (" << obj.getText() << ") ,";
out << "colors (" << colors[0] << "," << colors[1] << "," << colors[2]
<< ") ,";
out << "background colors(" << colors2[0] << "," << colors2[1] << ","
<< colors2[2] << ") ,";
delete[] colors;
delete[] colors2;
return out;
}
You would want to use C++ ofstream (output file stream). You need to create an ofstream object, open the file you want to write to, and then you could use the default << operator already defined for output file stream in order to print to the file.
Take a look at the C++ documentation for ofstream; that should help you get a better understanding of file I/O.
Since you have operator<<() overloaded, use it:
std::ofstream my_file("data.s");
Widget w;
my_file << w;
The easy way to do this:
void draw(const std::string & filename)
{
std::ofstream file(filename.c_str()); //open a file for writing.
//Can use filename directly on newer compilers
file << wiget1; //use the << operator overload
file << wiget2;
...
}
The above version will open, overwrite, and close filename for every call to draw. This may not be what you want if you plan on having multiple calls to draw and the output of all those draws in the same file.
Rather than passing in the file name and opening file, you can open file elsewhere and pass it in to draw. This will allow multiple calls to draw for the same file.
Elsewhere:
std::ofstream file(filename.c_str());
new Draw:
void draw(std::ofstream & file)
{
file << wiget1; //use the << operator overload
file << wiget2;
...
}
I'm trying to convert a string streamed phone lookup program into file streamed.. I'm missing something, but I'm stuck.. what members can I use in the ofstream process to get this working?
ofstream& process (ofstream &os, vector<PersonInfo> people)
{
// for each entry in people
for (vector<PersonInfo>::const_iterator entry = people.begin();
entry != people.end(); ++entry) {
ofstream formatted, badNums; // objects created on each loop
// for each number
for (vector<string>::const_iterator nums = entry->phones.begin();
nums != entry->phones.end(); ++nums) {
if (!valid(*nums)) {
badNums << " " << *nums; // string in badNums
} else
// ``writes'' to formatted's string
formatted << " " << format(*nums);
}
if (badNums.empty()) // there were no bad numbers
os << entry->name << " " // print the name
<< formatted.str() << endl; // and reformatted numbers
else // otherwise, print the name and bad numbers
cerr << "input error: " << entry->name
<< " invalid number(s) " << badNums.str() << endl;
}
return os;
}
First, you don't want an ofstream, except at the point you're opening
the file (creating the instance). The output stream interface is
defined by std::ostream; std::ofstream derives from this, as does
std::ostringstream (output can become an std::string), and in most
applications, a couple of others written by the local programmers. In
your case (if I've understood the problem correctly), what you want is:
std::ostream& process( std::ostream& os,
std::vector<PersonInfo> const& people )
// Note the use of a const reference above. No point
// in copying the entire vector if you're not going to
// modify it.
{
for ( std::vector<PersonInfo>::const_iterator entry = people.begin();
entry != people.end();
++ entry ) {
std::ostringstream formatted;
std::ostringstream badNums;
// ...
if ( badNums.str().empty() ) {
os << ... << formatted.str() << std::endl;
} else {
os << ... << badNums.str() << std::endl;
}
}
return os;
}
Note the different types: std::ostream formats output, independently
of the destination type. std::ofstream derives from it, and provides
a file as destination. std::ostringstream derives from it, and
provides a std::string as destination type. And the std::ostream
takes a std::streambuf* as argument, and you provide the destination
type.
You never associate a file with ostream, so the compiler doesn't know what to do with the data you write into it.
ofstream& process (ofstream &os, vector<PersonInfo> people)
{
os.open("Data.txt"); //open file to be used
if(!os.is_open())
std::cerr << "Error opening file!\n";
//rest of code goes here
}
EDIT: after reading through your program again, i noticed you're using ofstream wrong. Ofstream is for opening and writing FILES.The program has a lot of syntax and logical errors i would read up on it more here.
It looks like you don't need to use ofstreams for the internal parts of this function. In fact you don't need to use streams at all, a std::string would do:
ofstream& process (ofstream &os, vector<PersonInfo> people)
{
// for each entry in people
for (vector<PersonInfo>::const_iterator entry = people.begin();
entry != people.end(); ++entry) {
string formatted, badNums; // objects created on each loop
// for each number
for (vector<string>::const_iterator nums = entry->phones.begin();
nums != entry->phones.end(); ++nums) {
if (!valid(*nums)) {
badNums += " " + *nums; // string in badNums
} else
// ``writes'' to formatted's string
formatted += " " + format(*nums);
}
if (badNums.empty()) // there were no bad numbers
os << entry->name << " " // print the name
<< formatted << endl; // and reformatted numbers
else // otherwise, print the name and bad numbers
cerr << "input error: " << entry->name
<< " invalid number(s) " << badNums << endl;
}
return os;
}
Hi below is my function:
string Employee::get_print(void) {
string out_string;
stringstream ss;
ss << e_id << " " << type << endl;
out_string = ss.str();
return out_string;
}
e_id and type are int and they contain values from the class Employee. But when I pass them into the stringstream they just clear the string when I try to out put it. But if I don't have a int in the ss << "Some text" << endl; this output fine. What am I doing wrong =S
//Edit
Ok;
This is the calling code:
tmp = cur->get_print();
Where tmp is a string and cur is an Employee Object.
This code...
stringstream out;
out << "Test " << e_id << " " << e_type;
return out.str();
Retruns "Test " and nothing else. If I take out "Test " << my returned string is ""
I'm using GCC 4.2 on Mac OS/X 10.6.2 if that makes any difference.
I too am unable to reproduce this error. As has been mentioned, don't include the endl, as this actually appends a \n and is supposed to flush the write buffer. For this use, it is completely unnecessary and may actually lead to undesirable results...However, the code in your edit/update works just fine for me.
int main(int argc, char* argv[])
{
int e_id = 5;
int e_type = 123456;
stringstream out;
out << "Test " << e_id << " " << e_type;
cout << out.str();
return 0;
}
Produces:
Test 5 123456
My suggestions would be to double check that e_id and e_type are really just native int.
For further testing, you may want to force a cast on the values to see if it helps as such:
out << "Test " << (int)e_id << " " << (int)e_type;
Since I'm unable to reproduce this error, I'm afraid I'm unable to help any further. But best of luck to you!
Ok I have no idea what is going on with stringstream I've tried using it in other parts of my code and it doesn't work with integers. Therefore, I have reverted to using the sprintf C function:
string Employee::get_print(void) {
char out[50];
sprintf(out, "%d %d", e_id, e_type);
string output = out;
return output;
}
This returns the string which is needed.
I have moved into Netbeans and I don't have this problem. So it is an issue with Xcode.
I think the endl is not needed. You only need to write endl if you want to write a newline on a file on on std::cout.
Since you write endl, your stringstream will contain a string with 2 lines of which the second is empty. This probably confuses you. Remove the endl to get only one line.
I've got exactly the same problem - GCC and stringstream returning nothing.
As I found out, the trick is that you have to put some text data before anything else into the stringstream.
This code...
stringstream ss(stringstream::out);
ss << 3.14159;
cout << "'" << ss.str() << "'" << endl;
gets you this result:
''
But if we put a single "" inside the stringstream first...
stringstream ss(stringstream::out);
ss << "" << 3.14159;
cout << "'" << ss.str() << "'" << endl;
the result is as expected:
'3.14159'