I'm having trouble in understanding some part of this code I've found online, its goal is to print ASCII art from a .txt file. To be more accurate, I'm having trouble in undesrstanding the while loop in line 28 which is part of the string function "getFileContents". What's the meaning of 'TempLine'?
#include <iostream>
#include <fstream>
#include <string>
std::string getFileContents (std::ifstream&); //Gets file contents
int main(int argc, char *argv[])
{
std::ifstream Reader ("File1.txt"); //Open file
std::string Art = getFileContents (Reader); //Get file
std::cout << Art << std::endl; //Print it to the screen
Reader.close (); //Close file
return 0;
}
std::string getFileContents (std::ifstream& File)
{
std::string Lines = ""; //All lines
if (File) //Check if everything is good
{
while (File.good ())
{
std::string TempLine; //Temp line
std::getline (File , TempLine); //Get temp line
TempLine += "\n"; //Add newline character
Lines += TempLine; //Add newline
}
return Lines;
}
else //Return error
{
return "ERROR File does not exist.";
}
}
If you take a look at std::getline(), you can see that the string parameter is passed by non-const reference. This means that the string can (and is) edited by the std::getline() function. So line by line:
// Loop until the file stream cannot read any more input.
while (File.good ())
{
// Create a new, empty string called `TempLine`
std::string TempLine;
// Read a line from `File`, and write it into TempLine.
std::getline (File , TempLine);
// Add a newline character at the end of the string.
TempLine += "\n";
// Add the line we just read from the file to the `Lines` string,
// which holds the full file contents.
Lines += TempLine; //Add newline
// Repeat until all lines have been read from the file (or the file
// becomes otherwise unreadable).
}
The reason TempLine is needed is because std::getline() needs something to read the file content into, and if we passed Lines directly to the function, we'd only ever return the last line of the file (the previous lines would always get overwritten in the string).
Related
I am creating a program that justifies a paragraph to ensure that each line has a length of 75 char. I have created functions that will insert spaces and create these desired lengths as needed, but I am having problems reading a text file and trying to break it down line by line. Each line provided is less than the 75 char limit, and my functions do properly work when it is given only a line. But I do not know how to read line by line, manipulate it, and then write to my new .txt file. When I output this to the new text file, I am greeted by a justified line of text, not text that is in a paragraph block!
I have tried to create an if else loop that would only run when the string.length() is less than 75 char, and would create a new line when false, but I do not know how to create this new line in the program
string myString;
string line("\n");
while (getline(inFile, myString))
{
cout << myString << endl;
puncLoop(myString);
spaceLoop(myString);
}
}
In Order to output the file with new line you can use "\n".
#include <iostream>
#include <string>
#include <fstream>
int main() {
//in file object
std::ifstream inFile("example.txt");
//out file object
std::ofstream outFile ("example2.txt", std::ios_base::out | std::ios_base::trunc );
//Checking if file exist
if( inFile && outFile )
{
//temp valarable to store each line
std::string mystring;
//Loop through each line
while (getline(inFile, mystring))
{
//... Call Your Business Logic functions here, ( make use of pass by refernce or return to get back the string )
outFile << mystring.c_str() << "\n";
}
//closing file after completing
inFile.close();
outFile.close();
}
else
{
std::cout << "Could not open File to read or write"<<std::endl;
}
return 0;
}
I am looking for a way to search for a specific character in a text file and add a new-line after every ;
It's a pretty big document (2,7MB) if that matters.
You can't insert new characters into the middle of an existing file, only append to the end. You will have to create a new file, copying characters from the old file to the new file, inserting new characters as needed. For example:
#include <string>
#include <fstream>
int main()
{
std::ifstream inFile("input.txt");
if (!inFile.is_open())
{
std::cerr << "Failed to open input file";
return 1;
}
std::ofstream outFile("output.txt");
if (!outFile.is_open())
{
std::cerr << "Failed to create output file";
return 1;
}
std::string line;
while (std::getline(inFile, line, ';'))
{
outFile << line;
if (!inFile.eof())
outFile << ";\n";
}
return 0;
}
As SomeProgrammerdude points out in the comments, inserting into an existing file isn't really feasible and one of your options is to read it all into a single std::string and write back into the same text file.
Here is an example implementation. We read a charter at a time and check if it is a semicolon, and add a newline after every semicolon. Notice the reserve part, although advised, it is not mandatory:
#include <string>
#include <fstream>
#include <stdexcept>
int main()
{
std::fstream f("test.txt", std::ios::in);
if (!f.is_open()) {
throw std::runtime_error("Failed to open file");
}
std::string contents;
contents.reserve(10000); // reserve some space for better efficiency
char ch;
while (f.get(ch)) {
contents.push_back(ch);
if (ch == ';')
contents.push_back('\n');
}
f.close();
f.open("test.txt", std::ios::out);
if (!f.is_open()) {
throw std::runtime_error("Failed to open file");
}
f << contents;
f.close();
return 0;
}
Input:
line line line line; line line line line; line line line; line line
Output:
line line line line;
line line line line;
line line line;
line line
Note the leading spaces before lines. This is because we appended '\n' after every ';', did not replace the spaces.
I am fairly new to C++, and I'm trying write a code to run some analysis on large data files. I've managed to write code that produces a text file where only one word/number is displayed per line (there are millions of lines). However, the first ~3000 or so lines contain useless stuff not needed for my analysis.
The only problem is, the actual data starts at a different line number depending on the input file.
Is there any way to write a quick code which would search the text document and remove all lines up until the point the keyword "<event>" is found?
Update:
I got it to work! May be a little more complicated than what was suggested but it still works.
Thanks for the help!
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
int counter = 0;
ifstream FileSearch("OutputVector.txt"); // search OutputVector input file.
while(!FileSearch.eof())
{
counter++;
string temp;
FileSearch >> temp;
if(temp == "<event>")
{
break; //While loop adding +1 to counter each time <event> is not found.
}
}
std::ofstream outFile("./final.txt"); //Create output file "final.txt."
std::string line;
std::ifstream inFile("OutputVector.txt"); //open input file OutputVector again.
int count = 0;
while(getline(inFile, line)){
if(count > counter-2){
outFile << line << std::endl;
}
count++; //while loop counts from counter-2 until the end and writes them to the new file.
}
outFile.close();
inFile.close(); //close the files.
remove("OutputVector.txt"); //Delete uneeded OutputVector File.
}
Basic skeleton:
std::ifstream stream("file name goes here")
std::string line;
// optional: define line number here
while (std::getline (stream, line))
{
// optional: increment line number here
if (line.find("<event>") != line.npos)
{ // Deity of choice help you if <event> naturally occurs in junk lines.
// Extra smarts may be required here.
doStuffWithRestOfFile(stream);
break;
}
}
Not enough information on how you wish to modify the source file to answer that sub-question. Once you get the reader going, ask a new question if you haven't figured it out.
Edit: Short version
std::ifstream stream("file name goes here")
std::string line;
// optional: define line number here
while (std::getline (stream, line) && (line.find("<event>") == line.npos))
{
// optional: increment line number here
}
doStuffWithRestOfFile(stream);
If you want to override the file with the new version ( without the beginning ) you can either read all the file to memory and override it, or write to a second file while reading the first one, and move/rename it after
to read all line until you find <event> :
std::ifstream input_file( filePath );
std::string line;
int current_line = 0;
do
{
std::getline( input_file, line );
++current_line;
}
while( line.find("<event>") == line.npos );
// use input_line to process the rest of the file
Keep in mind that if "<event>" is a the first line, then after the do while, current_line will contain 1, not 0
I am trying to open a file and parse a file with separate functions.
when i parse the file, i want to read each line in my input file and i want to ignore any punctuation and make everything lowercase so that i can then print it out to a separate file into strings with no spaces or punctuation.
i have tried to implement it but i cannot figure out what i am doing wrong. I am not getting an error but my output is not correct.
this is my code:
#include <iostream>
#include <fstream>
#include <ostream>
#include <sstream>
#include <string>
using namespace std;
void processFile();
void parseFile(ifstream&, ofstream&);
int main()
{
//call function to open file and process
cout << "processing file" << endl;
processFile();
return 0;
}
void processFile()
{
string newString;
ifstream inFile;
ofstream outFile;
cout << "opening files" << endl;
// open files
inFile.open("inFile.txt");
outFile.open("outFile.txt");
cout << "parsing file" << endl;
//parse file for capitalization & punctuation
parseFile(inFile, outFile);
//close files
outFile.close();
inFile.close();
}
void parseFile(ifstream &inFile, ofstream &outFile)
{
//create and initialize variables
string newString;;
int i = 0;
if(!inFile)
{
cout << "ERROR!!! Cannot read file.";
}
else
{
do
{
//read each line in the input file until EOF
getline(inFile, newString, '\n');
//parse each string for punctuation
while(newString[i])
{
if(isalpha(newString[i])) //check each char in each
//string for punctuation
{
if(isupper(newString[i])) //check each string for
//capitalization
{
newString[i] = tolower(newString[i]); //convert
//string to
//lower case
}
outFile << newString[i]; //output each line to file
cout << newString[i];
}
i++;
if(newString[i] == '\n')
break;
}
} while(!inFile.eof());
}
}
this is my input:
racecar
RACEcar
rotator
rotor
civic
Red rum, sir, is murder!
Rats live on no evil star.
Neil, a trap! Sid is part alien!
Step on no pets.
Dammit, I’m mad!
my expected output is everything in the input printed in lowercase, without punctuation and spaces
this is my actual output:
racecarsirismurderraliena
You will need to initialize i after getline() . This is because each call of getline() will cause each line of data read from input file be overwritten (not appended) to the newString.
do
{
//read each line in the input file until EOF
getline(inFile, newString, '\n');
i = 0; // <== initialize 'i' to zero
//parse each string for punctuation
while(newString[i])
{
You need to reinitialize i after each call to getline(), otherwise it will continue at the offset where the previous string ended. getline() overwrites newString every time it's called.
do
{
//read each line in the input file until EOF
getline(inFile, newString, '\n');
i = 0;
//parse each string for punctuation
If you compare your input with your output it makes sense.
The first string "racecar" is parsed without problem. Now i is 7.
The next 4 calls to getline() get strings that are shorter than 7 so you get no new output in outFile.txt.
The call to getline() after that gets "Red rum, sir, is murder!", starting from 7 you get "sirismurder" and i is now 24.
The next call to getline() gets "Rats live on no evil star.", starting from 24 you get "r" and i is is now 26
The last call to getline() gets "Neil, a trap! Sid is part alien!", starting from 26 you get "alien".
How can I make my std::fstream object start reading a text file from the second line?
Use getline() to read the first line, then begin reading the rest of the stream.
ifstream stream("filename.txt");
string dummyLine;
getline(stream, dummyLine);
// Begin reading your stream here
while (stream)
...
(Changed to std::getline (thanks dalle.myopenid.com))
You could use the ignore feature of the stream:
ifstream stream("filename.txt");
// Get and drop a line
stream.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' );
// Get and store a line for processing.
// std::getline() has a third parameter the defaults to '\n' as the line
// delimiter.
std::string line;
std::getline(stream,line);
std::string word;
stream >> word; // Reads one space separated word from the stream.
A common mistake for reading a file:
while( someStream.good() ) // !someStream.eof()
{
getline( someStream, line );
cout << line << endl;
}
This fails because: When reading the last line it does not read the EOF marker. So the stream is still good, but there is no more data left in the stream to read. So the loop is re-entered. std::getline() then attempts to read another line from someStream and fails, but still write a line to std::cout.
Simple solution:
while( someStream ) // Same as someStream.good()
{
getline( someStream, line );
if (someStream) // streams when used in a boolean context are converted to a type that is usable in that context. If the stream is in a good state the object returned can be used as true
{
// Only write to cout if the getline did not fail.
cout << line << endl;
}
}
Correct Solution:
while(getline( someStream, line ))
{
// Loop only entered if reading a line from somestream is OK.
// Note: getline() returns a stream reference. This is automatically cast
// to boolean for the test. streams have a cast to bool operator that checks
// good()
cout << line << endl;
}
The more efficient way is ignoring strings with std::istream::ignore
for (int currLineNumber = 0; currLineNumber < startLineNumber; ++currLineNumber){
if (addressesFile.ignore(numeric_limits<streamsize>::max(), addressesFile.widen('\n'))){
//just skipping the line
} else
return HandleReadingLineError(addressesFile, currLineNumber);
}
HandleReadingLineError is not standart but hand-made, of course.
The first parameter is maximum number of characters to extract. If this is exactly numeric_limits::max(), there is no limit:
Link at cplusplus.com: std::istream::ignore
If you are going to skip a lot of lines you definitely should use it instead of getline: when i needed to skip 100000 lines in my file it took about a second in opposite to 22 seconds with getline.
Call getline() once to throw away the first line
There are other methods, but the problem is this, you don't know how long the first line will be do you? So you can't skip it till you know where that first '\n' is. If however you did know how long the first line was going to be, you could simply seek past it, then begin reading, this would be faster.
So to do it the first way would look something like:
#include <fstream>
#include <iostream>
using namespace std;
int main ()
{
// Open your file
ifstream someStream( "textFile.txt" );
// Set up a place to store our data read from the file
string line;
// Read and throw away the first line simply by doing
// nothing with it and reading again
getline( someStream, line );
// Now begin your useful code
while( !someStream.eof() ) {
// This will just over write the first line read
getline( someStream, line );
cout << line << endl;
}
return 0;
}
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string textString;
string anotherString;
ifstream textFile;
textFile.open("TextFile.txt");
if (textFile.is_open()) {
while (getline(textFile, textString)){
anotherString = anotherString + textString;
}
}
std::cout << anotherString;
textFile.close();
return 0;
}
this code can read file from your specified line from file but you have to make file in file explorer before hand my file name is "temp" code is given below
https://i.stack.imgur.com/OTrsj.png
hope this can help
You can use ignore function as follow:
fstream dataFile("file.txt");
dataFile.ignore(1, '\n'); // ignore one line
#include <fstream>
#include <iostream>
using namespace std;
int main ()
{
char buffer[256];
ifstream myfile ("test.txt");
// first line
myfile.getline (buffer,100);
// the rest
while (! myfile.eof() )
{
myfile.getline (buffer,100);
cout << buffer << endl;
}
return 0;
}