Print function to an output file - c++

I am about to be finished with a program I am writing and have reached a roadblock.
I am trying to print the contents of a function called print which is called by a pointer.
My problem is I need to print the contents of the function to an output file and am not sure how.
This is my print function:
void English::Print(){
int formatlength = 38 - (static_cast<int>(firstName.size() + lastName.size()));
cout << firstName << " " << lastName;
cout << setw(formatlength) << finalExam;
cout << setprecision(2) << fixed << setw(11) << FinalGrade();
cout << setw(4) << Lettergrade() << endl;
}
This is the implementation of the print function:
for (int i = 0; i <= numStudents - 1; i++) {
if (list[i]->GetSubject() == "English") {
list[i]->Print();
}
}
Where the for loop is cycling through my list of Students.
My goal is that the list[i]->Print() will print to my output file.

Simply replace cout with an ostream object, something like :
void English::Print(ostream& fout){
//ofstream of("myfile.txt", std::ios_base::app);
int formatlength = 38 - (static_cast<int>(firstName.size() + lastName.size()));
fout << firstName << " " << lastName;
fout << setw(formatlength) << finalExam;
fout << setprecision(2) << fixed << setw(11) << FinalGrade();
fout << setw(4) << Lettergrade() << endl;
}
Also, you can overload << operator too in your class English
friend ostream& operator <<( ostream& os, const English& E )
{
//
return os;
}
And then can simply use:
fout << list[i] ;

Besides the answers above, I think you should try this way, using the C's original file redirection function:
Put this instruction in the first line of your main function:
int main(){
freopen("out.txt", "w", stdout);
//your codes
The "out.txt" is the file you wanna to put the data in, "w" means you want to write in the file, and stdout is the standard output stream that has been redirected.

Related

Reading/ Writing from/to a file

I am working on an OOP project and I need to write into a file and I faced a problem that each time I do it the file is over written with only one object. How can I make it to write data of all the objects? I tried this but didnt work.
virtual void save(ofstream outfile) = 0;`// the base class
void AND2::save(ofstream outf) //derived
{
outf.open("test.txt");
outf << Component::getype() << " ";
outf<< Component::getid() << " ";
outf << Component:: graphicsinfomration().x1 << " ";
outf<< Component::graphicsinfomration().x2 << " ";
outf << graphicsinfomration().y1 << " ";
outf << graphicsinfomration().y2 << " ";
outf << endl;
outf.close();
}
else
{
ofstream outf;
for (int i = 0; i < (pApp->getcompcount()); i++)
{
//ask user to enter text name
c[i]->save( outf);
}
pOut->ClearStatusBar();
}
Because you're opening the file again and again you overwrite the contents again and again.
You probably want to open the stream outside the for loop once and pass it by reference.

Call by reference and ostream and string manipulation recursive

all!
I am trying to get my program to work correctly, and I do not think it is supposed to be recursive The program is supposed to print certain strings in a text file and put them in a text-made box.
However, I modified it incorrectly and made an infinite loop (it actually is a stack overflow, ha ha, how funny...). Any help would be much appreciated.
here is the code for the prototype (and yes #include is used):
void textBox(ostream & out, string text);
and the part in the main function and subprogram:
cout << "Part c: textBox(text)" << endl ;
cout << "---------------------" << endl ;
ofstream fout("myFile.txt");
string box = "Text in a Box!";
textBox(fout, box);
fout << endl;
string size = "You can put any text in any size box you want!!";
textBox(fout,size);
fout << endl;
string courage = "What makes the muskrat guard his musk? Courage!";
textBox(fout,courage);
void textBox(ostream & out, string text)
{
// ---------------------------------------------------------------------
// This routine outputs text surrounded by a box.
// ---------------------------------------------------------------------
ofstream myFile("myFile.txt");
textBox(cout, "Message to screen");
textBox(myFile, "Message to file");
int textSize = text.size();
out << '+' << setfill('-') << setw(textSize+1) << right << '+' << endl;
out << '|' << text << '|' << endl;
out << '+' << setfill('-') << setw(textSize+1) << right << '+' << endl;
out << setfill(' ') ;
}
It's recursive because textBox calls itself. Your program will run if you:
A) Remove both calls to textBox within textBox
or B) make textBox like this:
void textBox(ostream & out, string text)
{
int const textSize = text.size() + 1;
out << '+' << setfill('-') << setw(textSize) << right << '+' << endl;
out << '|' << text << '|' << endl;
out << '+' << setfill('-') << setw(textSize) << right << '+' << endl;
out << setfill(' ') ;
}
And create another function:
void textBoxWithInfo(ostream & out, string text)
{
textBox(cout, "Message to screen");
{ // Braces to deallocate + close myFile faster
ofstream myFile("myFile.txt");
textBox(myFile, "Message to file");
}
textBox(out, text);
}
And call the above function in main.

Using C++ stream for cout or text file

I have a very simple program where I ask the user if they want to print to screen or a file. Rather than create two sets of output sections, I thought I could switch a stream to either cout or an ofstream and then output to that stream. However, I'm getting screen output no matter what.
ostream &out = cout;
do
{
cout << "Write to file (f) or screen (s)?";
cin >> yes_or_no;
} while (yes_or_no != 'f' && yes_or_no !='s');
if (yes_or_no=='f')
{
ofstream out;
out.open("Report.txt");
cout << "Writing report to Report.txt" << endl;
system("pause");
}
out << "Day: Current Value ROI" << endl;
out << "------------------------------------------" << endl;
out << setw(5) << 0;
out << "$" << setw(20) << setprecision (2) << fixed << initial_value;
out << setw(12) << "1.00" << endl;
for (int day = 1 ; day < number_of_days ; day++)
{
current_value = generateNextStockValue(current_value, volatility, trend);
out << setw(5) << day;
out << setw(20) << setprecision (2) << fixed << current_value;
out << setw(12) << setprecision (2) << fixed << current_value / initial_value;
out << endl;
}
You could put all the writing logic inside a function, and let the caller decide which output stream to write to:
void do_the_stuff(std::ostream& os)
{
// write to os
os << "blah blah" ....
}
then
if (yes_or_no=='f')
{
ofstream out("Report.txt");
do_the_stuff(out);
} else {
do_the_stuff(std::cout);
}

getline not working as expected

I'm trying to display a text file data into columns using a class structure and getline() function to read through the textfile and the dump the data into a vector class. But it seems that the program didn't even run to my 'while' loop then quitting the program. The textfile is not empty.
Below is my code:
void ScrambleWordGame::displayScoreChart() {
//open file
fstream readScoreChart("ScoreChart.txt");
string line = "";
//vector to store data in
vector<personResult> perResult;
personResult person;
//while file is open, do stuff
if(readScoreChart.is_open())
{
//check through the file
readScoreChart.seekp(0,ios::end);
//get the size of the file's data
size_t size = readScoreChart.tellg();
if(size == 0)
cout << "No results yet. Please TRY to win a game. AT LEAST~" << endl;
else
{
//create the 1st row with 4 column names
cout << left
<< setw(20) << "Player Name "
<< setw(20) << "Winning Time "
<< setw(20) << "No. Of Attempts "
<< setw(20) << "Game Level " << endl;
//fill the second line with dashes(create underline)
cout << setw(70) << setfill('-') << "-" << endl;
//read the file line by line
//push the 1st line data into 'line'
cout << getline(readScoreChart,line);
while(getline(readScoreChart,line))
{
//create stringstream n push in the entire line in
stringstream lineStream(line);
//reads the stringstream and dump the data seperated by delimiter
getline(lineStream,person.playerName,':');
getline(lineStream,person.winningTime,':');
getline(lineStream,person.noOfAttempts,':');
getline(lineStream,person.gameLvl);
//sort the results based on their timing
//sort(perResult.begin(),perResult.end(),pRes);
//display the results
cout << left
<< setfill(' ')
<< setw(25) << person.playerName
<< setw(22) << person.winningTime
<< setw(17) << person.noOfAttempts
<< setw(16) << person.gameLvl
<< endl;
}
}
}
readScoreChart.close();
}
Edit: Example of the TextFile
Joel:3:1:1
Mary:5:2:2
John:25:3:1
Your file pointer is at the end of the file after your first seek. You need to reposition it to the beginning of the file.
if(size == 0)
{
cout << "No results yet. Please TRY to win a game. AT LEAST~" << endl;
}
else
{
readScoreChart.seekp(0,ios::begin);
// all you other stuff
}
You need to seek back to the beginning of the file to be able to read. Better still, just don't seek to the end in the first place.
I'd re-structure the code a bit -- write an operator>> to read a record from a file, and an operator<< to write a record to a file.
class person {
std::string name;
std::string winning_time;
std::string num_attempts;
std::string level;
public:
bool operator<(person const &other) const {
return std::stoi(winning_time) < std::stoi(other.winning_time);
}
friend std::istream &operator>>(std::istream &in, person &p) {
std::string buffer;
std::getline(in, buffer);
std::istringstream is(buffer);
std::getline(is,p.name,':');
std::getline(is,p.winning_time,':');
std::getline(is,p.num_attempts,':');
std::getline(is,p.level);
return in;
}
friend std::ostream &operator<<(std::ostream &os, person const &p) {
return os << std::setw(25) << p.name
<< std::setw(22) << p.winning_time
<< std::setw(17) << p.num_attempts
<< std::setw(16) << p.level;
}
};
With those in place, the rest gets quite a bit simpler:
void show_header(std::ostream &os) {
cout << left
<< setw(20) << "Player Name "
<< setw(20) << "Winning Time "
<< setw(20) << "No. Of Attempts "
<< setw(20) << "Game Level " << "\n";
std::cout << std::string(70, '-');
}
void game::displayScoreChart(){
std::ifstream in("ScoreChart.txt");
// read the data:
std::vector<person> people{std::istream_iterator<person>(in),
std::istream_iterator<person>()};
if (people.empty()) {
std::cout << "No scores yet."
return;
}
// sort it by winning time:
std::sort(people.begin(), people.end());
show_header(std::cout);
// display it:
for (auto const &p : people)
std::cout << p << "\n";
return 0;
}
As a simple replacement if you don't have a C++11 compiler, an stoi can be written something like this:
int stoi(std::string in) {
return strtol(in.c_str(), NULL, 10);
}

Ofstream not creating a new file correctly

I've tried to write a simple database program. The problem is that ofstream does NOT want to make a new file.
Here's an extract from the offending code.
void newd()
{
string name, extension, location, fname;
cout << "Input the filename for the new database (no extension, and no backslashes)." << endl << "> ";
getline(cin, name);
cout << endl << "The extension (no dot). If no extension is added, the default is .cla ." << endl << "> ";
getline(cin, extension);
cout << endl << "The full directory (double backslashes). Enter q to quit." << endl << "Also, just fyi, this will overwrite any files that are already there." << endl << "> ";
getline(cin, location);
cout << endl;
if (extension == "")
{
extension = "cla";
}
if (location == "q")
{
}
else
{
fname = location + name + "." + extension;
cout << fname << endl;
ofstream writeDB(fname);
int n = 1; //setting a throwaway inteher
string tmpField, tmpEntry; //temp variable for newest field, entry
for(;;)
{
cout << "Input the name of the " << n << "th field. If you don't want any more, press enter." << endl;
getline(cin, tmpField);
if (tmpField == "")
{
break;
}
n++;
writeDB << tmpField << ": |";
int j = 1; //another one
for (;;)
{
cout << "Enter the name of the " << j++ << "th entry for " << tmpField << "." << endl << "If you don't want any more, press enter." << endl;
getline(cin, tmpEntry);
if (tmpEntry == "")
{
break;
}
writeDB << " " << tmpEntry << " |";
}
writeDB << "¬";
}
cout << "Finished writing database. If you want to edit it, open it." << endl;
}
}
EDIT: OK, just tried
#include <fstream>
using namespace std;
int main()
{
ofstream writeDB ("C:\\test.cla");
writeDB << "test";
writeDB.close();
return 0;
}
and that didn't work, so it is access permission problems.
ofstream writeDB(fname); //-> replace fname with fname.c_str()
If you lookup the documentation of the ofstream constructor, you will see something like:
explicit ofstream ( const char * filename, ios_base::openmode mode = ios_base::out );
The second argument is optional, but the first one is a const char*, and not a string. To solve this problem the most simple way is to convert your string to something called a C-string (char*, which is basically an array of chars); to do that just use c_str() (it«s part of the library).
Other than that, you could just place the information directly on a C-str, and then pass it normally to the ofstream constructor.