I'm using this code to extract certain part of each line of a text file:
std::ifstream file( "infile.txt" );
std::string in1, out1;
int blockNumber = 0;
while( getline( file, in1 ) )
{
int n = 0;
int i = 0;
while( i <= blockNumber )
{
n = in1.find_first_of("(", n + 1);
i++;
}
out1 = in1.substr( n + 1, ( in1.find_first_of(")", n) - n - 1) );
ofstream fmatch ("solo_matches.txt",ios::out);
fmatch.close();
fmatch.open("solo_matches.txt");
fmatch << out1;
fmatch.close();
}
But when I run the code, the result is not as I expect it to be. Only the last string is being written to the file. If I use this instead:
std::cout << out1 << std::endl;
I get the exact output I need. I do not understand what is the difference.
Well, ofstream probably overwrites existing contents every time you open it. I mean, every time you open file, write pointer will be placed at the begninning, so even without ios::trunc flag new data written into that file will overwrite existing contents.
To solve the problem, stop reopening ofstream twice for every line of text. File open operation can be slow.
Either that, or try using ios::app flag.
Move file open and file close operations outside while loop:
#include<iostream>
#include<fstream>
int main()
{
std::ifstream file( "infile.txt" );
std::string in1, out1;
int blockNumber = 0;
std::ofstream fmatch ("solo_matches.txt",std::ios::out);
while( getline( file, in1 ) )
{
int n = 0;
int i = 0;
while( i <= blockNumber )
{
n = in1.find_first_of("(", n + 1);
i++;
}
out1 = in1.substr( n + 1, ( in1.find_first_of(")", n) - n - 1) );
//fmatch.close(); //you don't need this
//fmatch.open("solo_matches.txt"); //you don't need this
std::cout << out1 << std::endl;
fmatch << out1 << std::endl;
}
fmatch.close();
}
And replace
fmatch << out1;
with
fmatch << out1 << endl;
if you need cout and fmatch agreement.
std::ofstream fmatch("solo_matches.txt", ios::out);
fmatch << ...;
fmatch.close();
opens the file, rewrites its content and saves it upon closing the stream. To append the content at the end of the file, you can use ios::app flag:
std::ofstream fmatch("solo_matches.txt", ios::out | ios::app);
or yet even better, instead of reopening the file in every iteration:
while (...) {
construct ofstream
write to file
close ofstream
}
you could do:
construct ofstream
while (...) {
write to file
}
close ofstream
Also note that this line:
out1 = in1.substr( n + 1, ( in1.find_first_of(")", n) - n - 1) );
relies on the correct format of the input, it would be safer to check the return value of find_first_of:
std::size_t pos = in1.find_first_of(")", n);
if (pos != std::string::npos)
{
out1 = in1.substr( n + 1, pos - n - 1 );
...
}
Related
I'm using C++ 20 with ifstream to read data from file.
For example I have file like this:
abc
def
ghi
and for length N = 3 I want output like this:
abc
bc\n
c\nd
\nde
...
ghi
(Yes I want to catch end of lines too).
How do I achieve this?
I want to do it somewhat like this but it does not work:
int main() {
std::ifstream file("test.txt");
if (!file.is_open()) {
std::cout << "File not found" << std::endl;
return 1;
}
size_t nlen = 3;
while (!file.eof()) {
auto fp = file.cur;
std::string s{};
for (size_t i = 0; i < nlen; i++) {
char c;
file.get(c);
s += c;
}
std::cout << s << std::endl;
file.seekg(fp);
file.ignore(); //or any other function to move file pointer only by one;
}
return 0;
}
The streaming operator >> will do formatted input.
Instead you can use
istream& istream::get (char* s, streamsize n)
to read the n raw character(s).
You can further use
istream& istream::putback (char c);
to insert any characters back to the stream.
You should be able to achieve your goal using a combination of one or both of these.
Please can you advise, why the inner loop runs only once?
I'd like to add suffix to each line of input file and then store the result in output file.
thanks
For example:
Input file contains:
AA
AB
AC
Suffix file contains:
_1
_2
Output file should contain:
AA_1
AB_1
AC_1
AA_2
AB_2
AC_2
My result is :
AA_1
AB_1
AC_1
Code:
int main()
{
string line_in{};
string line_suf{};
string line_out{};
ifstream inFile{};
ofstream outFile{"outfile.txt"};
ifstream suffix{};
inFile.open("combined_test.txt");
suffix.open("suffixes.txt");
if (!inFile.is_open() && !suffix.is_open()) {
perror("Error open");
exit(EXIT_FAILURE);
}
while (getline(suffix, line_suf)) {
while (getline(inFile, line_in))
{
line_out = line_in + line_suf;
outFile << line_out << endl;
}
inFile.close();
outFile.close();
}
}
IMHO, a better method is to read the files into vectors, then iterate through the vectors:
std::ifstream word_base_file("combined_test.txt");
std::ifstream suffix_file("suffixes.txt");
//...
std::vector<string> words;
std::vector<string> suffixes;
std::string text;
while (std::getline(word_base_file, text))
{
words.push_back(text);
}
while (std::getline(suffix_file, text))
{
suffixes.push_back(text);
}
//...
const unsigned int quantity_words(words.size());
const unsigned int quantity_suffixes(suffixes.size());
for (unsigned int i = 0u; i < quantity_words; ++i)
{
for (unsigned int j = 0; j < quantity_suffixes; ++j)
{
std::cout << words[i] << suffix[j] << "\n";
}
}
Edit 1: no vectors
If you haven't learned about vectors or like to thrash your storage device you could try this:
std::string word_base;
while (std::getline(inFile, word_base))
{
std::string suffix_text;
while (std::getline(suffixes, suffix_text))
{
std::cout << word_base << suffix_text << "\n";
}
suffixes.clear(); // Clear the EOF condition
suffixes.seekg(0); // Seek to the start of the file (rewind).
}
Remember, after the inner while loop, the suffixes file is at the end; no more reads can occur. Thus the file needs to be positioned at the start before reading. Also, the EOF state needs to be cleared before reading.
So, I'm trying to read a text file into a two dimensional array in C++.
The problem is that the number of words in each line is not always the same, a line can contain up to 11 words.
For example, the input file could contain:
ZeroZero ZeroOne ZeroTwo ZeroThree
OneZero OneOne
TwoZero TwoOne TwoTwo
ThreeZero
FourZero FourOne
Therefore, array[2][1] should contain "TwoOne", array[1][1] should contain "OneOne", etc.
I don't know how to make my program increase the row number every line. what I have obviously is not working:
string myArray[50][11]; //The max, # of lines is 50
ifstream file(FileName);
if (file.fail())
{
cout << "The file could not be opened\n";
exit(1);
}
else if (file.is_open())
{
for (int i = 0; i < 50; ++i)
{
for (int j = 0; j < 11; ++j)
{
file >> myArray[i][j];
}
}
}
You should use a vector<vector<string>> to store the data as you don't know in advance how much data will be there to read.
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
using namespace std;
int main()
{
const string FileName = "a.txt";
ifstream fin ( FileName );
if ( fin.fail() )
{
cout << "The file could not be opened\n";
exit ( 1 );
}
else if ( fin.is_open() )
{
vector<vector<string>> myArray;
string line;
while ( getline ( fin, line ) )
{
myArray.push_back ( vector<string>() );
stringstream ss ( line );
string word;
while ( ss >> word )
{
myArray.back().push_back ( word );
}
}
for ( size_t i = 0; i < myArray.size(); i++ )
{
for ( size_t j = 0; j < myArray[i].size(); j++ )
{
cout << myArray[i][j] << " ";
}
cout << endl;
}
}
}
I have created a program in c++ to remove the commments of a c/c++ file and put a comment-removed version in another file. However after hours of debugging it is still not working. Help please!
"input" is a string that has the folder location of the c/c++ files.
"files" is a vector with all the file names in the folder but not their locations.
I use "input" and "files" to get the file name and location.
for (unsigned int i = 0; i < files.size();i++ ){//for loop start
iteratora++;
string filename1 = input;
filename1.append("\\");
filename1.append(files[iteratora + 2]);
cout << "\n" << filename1 << ".\n";
cout << "Iterator: " << iteratora << ".\n";
programFile.clear();
ifstream afile (filename1);//(filename1);
fstream temp ("temp/temp.txt",std::ofstream::out | std::ofstream::trunc);
string line;//variable for holding the characters in one line
remove_comments(afile,temp);
if (temp.is_open())
{
while ( getline (temp,line) )
{
//cout << line << '\n';
if (line != ""){
cout << line;
programFile.push_back(line);
line = "";
}
}
temp.close();
}
temp.clear();
if (showVerbose == true){
print_vector(programFile);//used to know what is in the file
}
}
remove comments function
void remove_comments ( ifstream& Source , fstream& Target)
{
string line;
bool flag = false;
while ( ! Source.eof() ) // This loop is to get assure that the whole input file is read.
{
getline(Source, line); // To read line by line.
if ( flag )
{ if ( line.find("*/") < line.length() )
flag = false;
line.erase(0,line.find("*/") + 2);
}
if ( line.find("/*") < line.length() ) // searching for " /* " to eliminat it and all its content.
flag = true;
if ( ! flag )
{
for (int i = 0; i < line.length(); i++ )
{
if(i<line.length())
if ( ( line.at(i) == '/' ) && ( line.at(i + 1 ) == '/' ) ) // searching for " // " to eliminate all its content.
break;
else
Target << line[i]; // To copy lines in the output file.
}
Target<<endl;
}
}
Source.close(); // to close the opened files.
Target.close();
}
Thanks!
find method of string returns std::string::npos on unsuccessful search , so you should write this line
if(line.find("/*") < line.length())
as below:
if(line.find("/*") != std::string::npos)
Make similar changes and try.
Here is another solution.
It opens file.txt and loads the entire file into a string. Then it removes the
comments and writes the new data in string back into file.txt.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(void) {
string source;
ifstream readFile("file.txt");
getline(readFile, source, '\0');
readFile.close();
cout<<"\n---b e f o r e -----------------------------------\n\n";
cout << source;
while(source.find("/*") != string::npos) {
size_t Beg = source.find("/*");
source.erase(Beg, (source.find("*/", Beg) - Beg)+2);
}
while(source.find("//") != string::npos) {
size_t Beg = source.find("//");
source.erase(Beg, source.find("\n", Beg) - Beg);
}
ofstream writefile("file.txt");
writefile <<source;
writefile.close();
cout<<"\n\n-- a f t e r -------------------------------------------\n\n";
cout << source;
cout<<"\n---------------------------------------------\n\n";
cout<<"\n\n";
return 0;
}
I can't figure out why this is outputting a different file given that the start of the input file matches the first if statement. Also, if there are multiple finds, the next file name turns out to be the last file name plus the new file name together.
int main()
{
unsigned short n(0);
unsigned char y;
std::ostringstream filename;
std::ifstream input("data.dat", std::ios::binary);
input >> std::noskipws >> std::hex;
std::ofstream output;
output << std::ios::binary;
while (input.good()) {
filename.clear();
filename << n << ".dat";
output.open(filename.str());
while ( input.good() )
{
input >> y;
output << y;
if ( y == 0xFF ) {
input >> y;
output << y;
if ( y == 0xD9 ) {
input >> y;
output << y;
output.close();
break;
}
}
}
if (output.is_open())
output.close();
++n;
}
return 0;
}
#include <iostream> // for input/output
#include <fstream> // for file stream stuff
#include <sstream> // for ostringstream
int main()
{
unsigned short nFile = 0; // used to increment file name
std::ostringstream filename; // output filename
std::ifstream inFile; // input stream
std::ofstream outFile; // output stream
unsigned char buffer; // buffer between input and output
inFile.open("data.dat", std::ios::binary); // open input file
if ( inFile.fail() )
return 1;
while ( inFile.good() )
{
filename.str(""); // empties the stream
filename << nFile << ".dat"; // generate filename
// start the search loop
while ( inFile.good() )
{
// create a file
outFile.open(filename.str(), std::ios::binary);
if ( outFile.fail() )
return 1;
while ( inFile.good() )
{
inFile.read(reinterpret_cast<char*>(&buffer), sizeof(buffer)); // read a byte
if ( inFile.eof() )
break;
outFile.write(reinterpret_cast<char*>(&buffer), sizeof(buffer)); // write a byte
if ( buffer == 0xFF )
{
inFile.read(reinterpret_cast<char*>(&buffer), sizeof(buffer)); // read a byte
if ( inFile.eof() )
break;
outFile.write(reinterpret_cast<char*>(&buffer), sizeof(buffer)); // write a byte
if ( buffer == 0xD9 ) // full match; break loop
{
break;
}
}
}
// if search is done and file is still open, close it
if (outFile.is_open())
outFile.close();
++nFile;
}
return 0;
}
}