How to test if a line is empty? - c++

I'm actually trying to understand how does the getline() function works! But I'm facing difficulties to test if a line is empty or not!
Here is my code:
ifstream fichier("upload.txt",ios::binary);
string ligne;
while(getline(fichier,ligne))
{
cout<<ligne<<endl;
if(ligne=="")
cout<<"line below is empty"<<endl;
}
But, the if-condition seems to be not working :((

On Windows, a line break is normally CRLF (0x0D 0x0A). std::getline() will read until it encounters the LF and discard it from the returned std::string. If the std::ifstream is opened in text mode (the default mode), platform line breaks are normalized to LF and a leading CR will also be discarded. But, if opened in binary mode, the CR will not be discarded. So you will have to check for that:
ifstream fichier("upload.txt", ios::binary);
string ligne;
while (getline(fichier, ligne)) {
if (ligne.empty() || ligne == "\r") {
cout << "line is empty" << endl;
} else {
cout << ligne << endl;
}
}
Otherwise, don't use binary mode for text files:
ifstream fichier("upload.txt");
string ligne;
while (getline(fichier, ligne)) {
if (ligne.empty()) {
cout << "line is empty" << endl;
} else {
cout << ligne << endl;
}
}

Your problem is opening file in binary. Other than that, you should do few things :
Check if file is properly opened
Compare against empty()
Check if string only contains space , then it's considered empty.
Close file
ifstream fichier("upload.txt", std::ifstream::in ); //File opened for reading.
string ligne;
//Always Check if file is properly opened.
if (fichier.is_open() )
{
while(getline(fichier,ligne))
{
cout<<ligne<<endl;
if(ligne.empty() || str.find_first_not_of(' ') == std::string::npos)
cout<<"line below is empty"<<endl;
}
fichier.close();
}
else
{
// show message:
std::cout << "Error opening file";
}

Related

Infile stops reading command line arguments

**Edit: As it turns out, it was a simple typo under the if(i==0) statement. I missed putting {} to enclose both first_nonterminal statements.
I'm creating a CFG for an assignment, but I've gotten stuck. My program is supposed to read a file (of strings) by getting the file name from the command line, and then do certain things with the contents of the file.
using namespace std;
string current, first_nonterminal;
int main(int argc, char *argv[])
{
if(argc != 2)
{
std::cout << "No file name given" << std::endl; // if there is no file name in command line
exit(1);
}
ifstream infile(argv[1]);
if(!infile)
{
std::cout << "Given file " << argv[1] << " will not open."; // if file refuses to open
exit(2);
}
string word;
for(int i = 0; infile >> word; ++i)
{
cout << word << endl; // (debug) print input word
try // check if first word is in correct format
{
if (i == 0 && word.find(':') == string::npos) // check only first word,
{
throw runtime_error("File does not have correct format.");
}
}
catch(runtime_error &e)
{
cout << "Error:" << e.what();
exit(3);
}
if (i==0)
first_nonterminal = word;
first_nonterminal.pop_back(); // remove colon
insert(word); //put string through insert() method
}
randomize(); // randomize and replace
print(); // print end result
infile.close();
}
The above code intakes a file which is formatted like so:
STMT: THIS THAT OTHER
THIS: That carpet
THIS: Atlanta
THAT: is wild
OTHER: .
OTHER: , oooh OTHER2
OTHER2: oooh OTHER2
OTHER2: !
Any word that has a colon following it is considered a nonterminal, with the words following it considered terminals. Regardless, I've figured out the issue isn't my randomize() or insert() functions, as they work perfectly if I hard-code the file into the program. My issue is the file stops being read after a certain number of strings, and I'm not sure why. For example, when I put the above's file name into the command line, it runs through, but then after it puts "That" into the insert() function, it prints "carpet" via the debug cout, and then stops.

C++: std::ofstream method open() wipes open ifstream file on second iteration

I am trying to build a "fileUpdater" which will copy an original file into multiple directories, where a file with the same name and extension was previously found.
bool update_files(const string inputPath, const vector<string> outputPaths)
{
ifstream src(inputPath);
if(!src.is_open())
{
cout << "Unable to open input file\n" << inputPath <<endl;
return false;
}
else
{
ofstream dst;
for(unsigned int i=0; i<= outputPaths.size()-1; i++)
{
dst.open(outputPaths[i]);
try
{
dst << src.rdbuf();
dst.close();
}
catch(int e)
{
cout << "Unable to replace file\n" <<endl;
cout << outputPaths[i] <<"\n"<< endl;
cout << "Error code: " <<e<<endl;
}
}
};
src.close();
return true;
}
Exactly after executing
dst.open(outputPaths[i]);
in the second iteration, the original file opened by
ifstream src(inputPath);
gets wiped and only an empty file is copied into the remaining directories.
I also tried
dst.clear();
dst.close();
and
src.clear();
src.seekg(0,ios::beg);
before entering the next iteration, but it made no difference.
UPDATE
After trying different files, I realised the behavior depends on the input file. Above behavior appeared for .m-files (MatLab).
After testing it with .txt files, all files were wiped.
The way you're copying the file, with dst << src.rdbuf();, will leave the current file position at the end of your input file. On the second iteration, that same read won't read anything (leaving an empty copy of the file) because you're already at the end of the input file.
The solution is to seek back to the beginning of the input file before every read, using seekg. You should call tellg before reading anything (right after opening the file), then seek to that position.
auto startpos = src.tellg();
ofstream dst;
// ...
src.seekg(startpos);
dst << src.rdbuf();
None of the proposed methods work.
Neither resetting the pointer, nor pulling ifstream into the loop, which would result in opening the input file (which is not supposed to change) unnecessarily often.
It is still unclear why dst.open(outputPaths[i]); is wiping the input file. Also the exact moment of the wipe depends on used types of files.
I implemented following workaround, effectively reading the input file into a string and closing it beforehand, in order to protect it from further read/write action.
bool update_files( const string inputPath, const vector<string> outputPaths)
{
const char * in = inputPath.c_str();
ifstream src(in);
if(!src.is_open())
{
cout << "Unable to open input file\n" << inputPath <<endl;
return false;
}
else
{
string buffer;
streamsize s=src.gcount();
src.seekg(0,ios::end);
buffer.reserve(src.tellg());
src.seekg(0,ios::beg);
buffer.assign((istreambuf_iterator<char>(src)), istreambuf_iterator<char>());
src.close();
for(unsigned int i=0; i<= outputPaths.size()-1; i++)
{
const char * out = outputPaths[i].c_str();
ofstream dst(out);
try
{
dst << buffer;
dst.close();
}
catch(int e)
{
cout << "Unable to replace file\n" <<endl;
cout << outputPaths[i] <<"\n"<< endl;
cout << "Error code: " <<e<<endl;
}
}
};
src.close();
return true;
}

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.

Detect last line of file C++

I've been working on some code for a file parser function to learn some C++:
It's supposed to read in this text file:
>FirstSeq
AAAAAAAAAAAAAA
BBBBBBBBBBBBBB
>SecondSeq
TTTTTTTTTTTTTT
>ThirdSequence
CCCCCCCCCCCCCC
>FourthSequence
GGGGGGGGGGGGGG
and print out the names (lines with '>' at the start) and then the sequences.
However from the output:
AAAAAAAAAAAAAABBBBBBBBBBBBBB
TTTTTTTTTTTTTT
CCCCCCCCCCCCCC
FirstSeq
SecondSeq
ThirdSequence
FourthSequence
We see that the final line of G characters is not included. The code is below. What it does is loop over lines, if it finds a name, appends it to the vector of names, if it finds a sequence, appends it to a temporary string (incase the sequence is more than one line, like the first sequence), then when it finds the name of the next sequence, stores the built up temporary string in a vector and then proceeds by overwriting the temporary string and starting again. I suspect that it is because in the while loop of the function: The line fullSequence.push_back(currentSeq); which is called whenever a new name was detected previously to push the old temp string onto the vector would not be called for the last line of G's and so it is not being included, although the name "FourthSeq" is recorded, rather the line of G's is read into the temporary string, but then is not passed to the vector. So, how can I make it so as I can detect that this is the last line of the file and so should make sure the temporary string is pushed onto the vector?
Thanks,
Ben.
CODE:
#include<fstream>
#include<iostream>
#include<string>
#include<vector>
void fastaRead(string fileName)
{
ifstream inputFile;
inputFile.open(fileName);
if (inputFile.is_open()) {
vector<string> fullSequence, sequenceNames;
string currentSeq;
string line;
bool newseq = false;
bool firstseq = true;
cout << "Reading Sequence" << endl;
while (getline(inputFile, line))
{
if (line[0] == '>') {
sequenceNames.push_back(line.substr(1,line.size()));
newseq = true;
} else {
if (newseq == true) {
if(firstseq == false){
fullSequence.push_back(currentSeq);
} else {
firstseq = false;
}
currentSeq = line;
newseq = false;
} else {
currentSeq.append(line);
}
}
}
//Report back the sequences and the sequence names...
for ( vector<string>::iterator i = fullSequence.begin(); i != fullSequence.end(); i++) {
cout << *i << endl;
}
for ( vector<string>::iterator i = sequenceNames.begin(); i != sequenceNames.end(); i++) {
cout << *i << endl;
}
cout << fullSequence.size() << endl;
cout << sequenceNames.size() << endl;
inputFile.close();
} else {
perror("error whilst reading this file");
}
if(inputFile.bad()){
perror("error whilst reading this file");
}
}
int main()
{
cout << "Fasta Sequence Filepath" << endl;
string input = "boop.txt";
fastaRead(input);
return 0;
}
Getline() will "fail" when it finds an EOF in the line, so the last line you read will not go through your loop.
I've solved this problem two ways, either by having two flags or just by processing the last line after the loop.
For two flags, the loop requires both to be true, you set one to false when getline() fails, and you set the other one to false if the first one is false, this gives you one extra loop after EOF.
Good luck!

Reading through file using ifstream

I am trying to read from file:
The file is multiline and basically i need to go over each "word". Word being anything non space.
Sample input file would be:
Sample file:
test 2d
word 3.5
input
{
test 13.5 12.3
another {
testing 145.4
}
}
So I tried something like this:
ifstream inFile(fajl.c_str(), ifstream::in);
if(!inFile)
{
cout << "Cannot open " << fajl << endl;
exit(0);
}
string curr_str;
char curr_ch;
int curr_int;
float curr_float;
cout << "HERE\n";
inFile >> curr_str;
cout << "Read " << curr_str << endl;
The problem is when it reads new line it just hangs. I read everything before test 13.5
but once it reaches that line it doesnt do anything.
Anyone can tell me what I am doing wrong?
Any better suggestion on how to do this???
I essentially need to go through file and go one "word" (non white char) at the time.
I
Thanks
You open a file 'inFile' but are reading from the 'std::cin' any particular reason?
/*
* Open the file.
*/
std::ifstream inFile(fajl.c_str()); // use input file stream don't.
// Then you don't need explicitly specify
// that input flag in second parameter
if (!inFile) // Test for error.
{
std::cerr << "Error opening file:\n";
exit(1);
}
std::string word;
while(inFile >> word) // while reading a word succeeds. Note >> operator with string
{ // Will read 1 space separated word.
std::cout << "Word(" << word << ")\n";
}
Not sure how "in the spirit" of the iostream library this is, but you could do it with unformatted input. Something like:
char tempCharacter;
std::string currentWord;
while (file.get(tempCharacter))
{
if (tempCharacter == '\t' || tempCharacter == '\n' || tempCharacter == '\r' || tempCharacter == ' ')
{
std::cout << "Current Word: " << currentWord << std::endl;
currentWord.clear();
continue;
}
currentWord.push_back(tempCharacter);
}
Does that work?