Outputting multiple lines to a text file - c++

I've done this before, but can't find the sample code...still new to c++.
I need to output multiple lines to a text file. Right now it only outputs the last line, so I assume its overwriting the prior line each time the loop is run. How do I get it to output a line and then output to the next line, etc. without writing over the prior line?
Here's a snippet:
int main()
{
int n = 1;
while (n <= 100)
{
int argument = 0 + n;
ofstream textfile;
textfile.open ("textfile.txt");
textfile << argument << endl;
textfile.close();
++n;
}
return 0;
}

Open the file before you enter the loop, and close it after you exit the loop.

It looks like the default open mode is override, so it's only going to write over anything in the file previously with what is being currently written into the file.
Below are to keep the file handle open instead of reopening many times. If you want to append still you should use this :
textfile.open ("textfile.txt", ios::out | ios::app);
This will open the file for output and append on the end of the file.
int main()
{
int n = 1;
ofstream textfile;
textfile.open ("textfile.txt");
while (n <= 100)
{
int argument = 0 + n;
textfile << argument << endl;
++n;
}
textfile.close();
return 0;
}

You should open and close the file outside of the loop. When the file is opened, it defaults to overwriting. You can specify an append mode, but since opening a file is a somewhat lengthy operation, you don't really want to do that in this case.

Use this instead :
int main()
{
int n = 1;
while (n <= 100)
{
int argument = 0 + n;
ofstream textfile;
textfile.open ("textfile.txt", ofstream::out | ofstream::app);
textfile << argument << endl;
textfile.close();
++n;
}
return 0;
}

Related

Error opening a text file using ifstream c++11

I am creating an object called SpellChecker that corrects the spelling of words in a string.
To check if the words are spelled correctly and if not to correct them, I have a text file of correct words (one per line). I also have a text file of words that are misspelled and their corrections separated by a tab.
My issue is reading in my text file. I have created an if statement to see if my file opens successfully. However, I believe my file should be readable and it is not. I am trying to find out why this is happening.
Here is my SpellChecker constructor:
SpellChecker::SpellChecker(string tempLanguage, string correctWordsFile,string wordCorectionsFile){
language=tempLanguage;
ifstream istream;
istream.open(correctWordsFile);
if(!istream.is_open()){
cout << "Error opening " << correctWordsFile << endl;
}
int count=0;
string temp;
while(!istream.eof()){
getline(istream,temp);
correctWords[count] = temp;
count++;
}
numCorrectWords = count;
istream.close();
istream.open(wordCorectionsFile);
if(!istream.is_open()){
cout << "Error opening " << wordCorectionsFile << endl;
}
int j=0;
int i=0;
char temp2;
while(!istream.eof()){
istream.get(temp2);
if(temp2 == '\t'){
j++;
}
else if(temp2 == '\n'){
i++;
j = 0;
}
else
wordCorections[i][j] += temp2;
}
numwordCorrections = i;
istream.close();
}
Here is my main:
int main(){
SpellChecker spellCheck("English","CorectWords.txt","WordCorections.txt");
spellCheck.viewCorrectWords();
spellCheck.viewCorrectedWords();
spellCheck.setEnd('~');
spellCheck.setStart('~');
cout << spellCheck.repair("I like to eat candy. It is greatt.");
}
The terminal returns:
"Error opening CorectWords.txt"
How can I solve this problem?
The call to library function is_open() is returning false, which could be due to one of many reasons.
Ensure that :
1. You have used correct name of the data file.
2. The data file is in the same folder as the executable of your program.
3. It has been closed by any previous program that read it.

I Can't print out a file that I wrote on

I have created a function to write some data on a text file, and it works fine. I created another function to read in all the content of the file, and print it out for me! But, it is not working for some reason. Could any one help please?
This is my function:
void myClass::displayFile() {
char line[LINE]; //to hold the current line
file.open("data.txt", ios::app);
//keep reading information from the file while the file is open and has data
while (!file.fail() && !file.eof()) {
int lineSize; //to loope through each line
file.getline(line, LINE);
lineSize = strlen(line);
//loop through the line to print it without delimiters
for (int i = 0; i < lineSize; ++i) {
if (line[i] == ';') {
cout << " || ";
} else {
cout << line[i];
}
}
}
file.close();
file.clear();
if (file.fail()) {
cerr << "Something went wrong with the file!";
}
}
Note: The function compiles and the loop is accessible, but the line string is empty.
This is the writing function:
void myClass::fileWriter() {
file.open("data.txt", ios::app);
file << name << ";" << age << ";" << "\n";
file.close();
file.clear();
}
Silly me, the cause of your problem was staring me right in the face from the beginning, and it's the app open-mode that's the problem. It is to open the file in write mode, which means you can't read from it.
And even if you could read from the file, the cursor is placed ad the end of the file the eofbit flag would have been set inside the first iteration anyway.
If you want to read from a file, then either use std::ifstream which automatically sets the in mode if you don't specify a mode, or you have to explicitly set the in mode when opening.

Writing CRC data to .txt file

This seems like it should be a basic C++ process, but I'm not familiar with the data output.
When I print the data without outputting to a text file, I get the correct values.
example: 00150017000 181
When printing to a text file, this is what I get:
11161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116111611161116
Here is my code:
ofstream myfile;
myfile.open("C:\\CRC.txt");
for (i = 0; i < 200; i++, id++)
{
myfile << sprintf(idstring, "%011d", id);
myfile << printf("%s %03d\n", idstring, computeCrc(idstring));
}
myfile.close();
Everything else works fine and I know the CRC is generated correctly. Just a matter of getting the correct output.
I was able to output the console screen to a text file by adding "> CRC.txt" to the Debugging Properties Command Arguments, but I just wanted to know how I could incorporate the ofstream method into this.
Thanks in advance.
You don't save to the file what you think you save. First you save the result of sprintf() function, which in your case is 11. Then you save the result of the printf() function which in your case is 11 + 1 (space) + 3 + 1 (\n) = 16. So the result is 200 times 1116.
What you wanted to do
char tempBuf[12];
ofstream myfile;
myfile.open("C:\\CRC.txt");
for (i = 0; i < 200; i++, id++)
{
sprintf(tempBuf, "%011d", id);
myfile << tempBuf << ' ';
sprintf(tempBuf, "%03d", computeCrc(tempBuf));
myFile << tempBuf << '\n';
}
myfile.close();
You are ouputing the return of sprintf() and printf() to the file. The returns of sprintf() and printf() are int and not the string you are creating. To output the string you need to change your code to
for (i = 0; i < 200; i++, id++)
{
sprintf(idstring, "%011d", id);
myfile << idstring;
myfile << computeCrc(idstring) << endl;
}

Writing a C++ program that can merge files from the command line in Linux

I have written a C++ program that is supposed to open two text files (prog2a.dat and prog2b.dat) and write the contents of a specified range of lines to an output file (outfile.dat). I wrote a program that based on the example we were given (to take lines 5-15 from the first file and lines 4-12 of the second file and merge them into the output file) works perfectly. However, after asking my professor for some clarification on another part of the assignment, I found out I have not done this correctly. I have the code written so that it will always output the range of lines I mentioned earlier, but the program is actually supposed to allow the user to merge the files from the command line using whatever range they want by typing in the following command:
prog2 in1 5-15 in2 4-12 outfile
But I'm not sure how to tweak my current program to allow this to be done.
Here is the code that I have written, keep in mind that this works properly for the way it is written, but not how it is supposed to work for the purposes of the command line (hopefully that makes sense):
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
int main() {
// Create output file
std::ofstream outFile("outfile.dat", ios::out);
// Open input file 1, if can't be opened, exit
ifstream in1;
in1.open("prog2a.dat");
std::string line;
int count = 1;
if (!in1) {
cerr << "Open Failure" << endl;
exit(1);
} // end if
else {
while (std::getline(in1, line)) {
if (count >= 5 && count <= 15) {
outFile << line << "\n"; /*writes the contents of
lines 5-15 to outfile.dat*/
}
++count;
} // end while
} // end else
in1.close(); // close in1 (prog2a.dat)
outFile << "\n"; // add a blank line after the output from prog2a.dat
count = 1; // reset the line count to 1 before opening next file.
// Open input file 2, if can't be opened, exit
ifstream in2;
in2.open("prog2b.dat");
if (!in2) {
cerr << "Open Failure" << endl;
exit(1);
} // end if
else {
while (std::getline(in2, line)) {
if (count >= 4 && count <= 12) {
outFile << line << "\n"; /*writes the contents of the
lines 4-12 to outfile*/
}
++count;
} // end while
} // end else
in2.close(); // close in2 (prog2b.dat)
} // end main
Is there any simple way to make this work as I described using the command line? Also, I am supposed to break this up into three files, a header file, the program file, and a test file (the test file contains main() and should close the 3 open files and display any error messages), but I'm getting really confused as to what should go in the header file. I know the header file should contain class definitions and constructors, but don't really know how to make that work for this specific program? I'm extremely new to this so any pointers would be greatly appreciated.
The issue is that line numbers and file names are hardcoded in your main function. As mentioned in the comments, you need to handle main function arguments. Also your code contains duplication that can easily be moved to separate function (reading input files and copying required strings to output). I've removed some duplication by moving the related code to separate functions. You still need to check for errors: take a look at //TODO comments in the code:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
bool lineNumbersFromString(const std::string& aString, int& startPos, int& endPos)
{
std::size_t pos = aString.find('-');
if (pos < 0 || pos >= aString.length())
{
return false;
}
std::string start = aString.substr(0, pos);
std::string end = aString.substr(pos + 1, aString.length()-1);
if (start.length() == 0 || end.length() == 0)
{
return false;
}
startPos = atoi(start.c_str());
endPos = atoi(end.c_str());
return true;
}
bool copyLinesToOutFile(std::string& inputFileName, int startLine, int endLine, std::ofstream& outFileStream)
{
ifstream inputFileStream;
inputFileStream.open(inputFileName.c_str());
if (!inputFileStream)
{
cerr << "Cannot open file: " << inputFileName << endl;
return false;
}
int lineCount = 0;
std::string line;
while (std::getline(inputFileStream, line))
{
if (lineCount >= startLine && lineCount <= endLine)
{
outFileStream << line << "\n";
}
++lineCount;
}
inputFileStream.close();
}
int main(int argc, char** argv)
{
if (argc != 6)
{
//Invalid number of arguments
//TODO: report error
return -1;
}
std::string firstFileName = argv[1];
std::string firstFileRange = argv[2];
std::string secondFileName = argv[3];
std::string secondFileRange = argv[4];
std::string outFileName = argv[5];
int firstStartPos = 0;
int firstEndPos = 0;
bool ok = false;
ok = lineNumbersFromString(firstFileRange, firstStartPos, firstEndPos);
//TODO: check error
// Create output file
std::ofstream outFile(outFileName.c_str(), ios::out);
ok = copyLinesToOutFile(firstFileName, firstStartPos, firstEndPos, outFile);
//TODO: check error
int secondStartPos = 0;
int secondEndPos = 0;
ok = lineNumbersFromString(secondFileRange, secondStartPos, secondEndPos);
//TODO: check error
ok = copyLinesToOutFile(secondFileName, secondStartPos, secondEndPos, outFile);
//TODO: check error
outFile.close();
return 0;
}
P.S. Hope this helps. Splitting it to separate files should not be much of an issue.

To split a large data file into several small files (text format)

I am trying to split a large data file into several small text files. The following code opens and closes a new file every time, which is not feasible. Is there an alternative way of doing this?
ifstream infile(file_name);
if(infile)
{
char val;
while(!infile.eof())
{
ofstream ofile (ofile_name);
infile >> val;
ofile << val;
if( infile.peek() == '\n' )// last entry on the line has been read
{
row_counter++;
if (row_counter == win_size)
// generate new ofile_name
}
ofile.close();
}
infile.close();
}
You will not be able to create several output files without opening and closing the output files.
The reason is, that each output file should have a unique name. You will have to generate useful names for the output files. The connection between the file (content) and the file name will be done in the open call (or ofstream constructor).
Edit
To avoid open and close for each character you need status variable. In your example row_counter is usable for it. You need following steps:
open initial ofile before your while(!infile.eof()) loop
close your ofile, generate next name and open the new where where you wrote // generate new ofile_name
finally close your ofile after the loop.
This could be done in this way:
if(infile)
{
char val;
row_counter = 0;
ofstream ofile (ofile_name);
while(!infile.eof())
{
infile >> val;
ofile << val;
if( infile.peek() == '\n' )// last entry on the line has been read
{
row_counter++;
if (row_counter == win_size)
{
row_counter = 0;
ofile.close();
// generate new ofile_name
ofile.open(ofile_name); // you might change the nMode parameter if necessary
}
}
}
ofile.close();
infile.close();
}