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?
Related
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";
}
Its probably an easy answer and i hope its easy to understand my question.
I have a text document that has a lot of lines and several paragraphs
Is there a way to merge all lines into one single line without doing it manually?
The reason i am asking this its because lets say I am searching for a specific word in a document that only has one paragraph.(let say the paragraph has 10 lines) If that word its in that one paragraph its suppose to return paragraph1 accepted. But what my program its doing something weird instead its giving me an output like this:
paragraph1:accepted
paragraph2:accepted
paragraph3:accepted
paragraph4:accepted
paragraph5:accepted
paragraph6:accepted
paragraph7:accepted
paragraph8:accepted
paragraph9:accepted
paragraph10:accepted
This is the code that reads my document
void processParagraph(std::string ¶graph, size_t paragraphNumber)
{
ifstream input;
input.open("data.txt"); //opens the text file with the documents
if (input.fail()) //if the file doesn't open
{
cout << "file not found" << endl;
return;
}
if (isMyWordThere(paragraph)) //if the word im looking its there
cout << "paragraph " << paragraphNumber << ": accepted" << endl;
else // if the word its not there
cout << "paragraph " << paragraphNumber << ": not accepted" << endl;
paragraph.clear(); // reset the paragraph to handle the next one.
std::string line;
std::string paragraph;
size_t paragraphNumber = 0;
while ( getline(input, line) ) // read a LINE
{
if ( !line.empty() ) // paragraph not finished
{
paragraph.append("\n").append(line);
}
else // paragraph finished, because we found an empty line
{
++paragraphNumber;
processParagraph(paragraph, paragraphNumber);
}
}
if ( !paragraph.empty() )
{
processParagraph(paragraph, paragraphNumber);
}
}
Its there a way to merge all lines into one, or a way that i can change my code so it doesnt count lines?
The input file looks like this:(im looking for the word "hello")
hello world
hello everyone
hello All
The output should look like this
paragraph 1: accepted
but what im getting is
paragraph 1: accepted
paragraph 2: accepted
paragraph 3: accepted
You're processing lines not paragraphs.
This will do it:
void processParagraph(std::string ¶graph, size_t paragraphNumber)
{
if (isMyWordThere(paragraph)) //if the word im looking its there
std::cout << "paragraph " << paragraphNumber << ": accepted" << std::endl;
else // if the word its not there
std::cout << "paragraph " << paragraphNumber << ": not accepted" << std::endl;
paragraph.clear(); // reset the paragraph to handle the next one.
}
void processFile(std::string filename)
{
std::ifstream input;
input.open(filename.c_str()); // open file
std::string line;
std::string paragraph;
size_t paragraphNumber = 0;
while ( getline(input, line) ) // read a LINE
{
if ( !line.empty() ) // paragraph not finished
{
paragraph.append("\n").append(line);
}
else // paragraph finished, because we found an empty line
{
++paragraphNumber;
processParagraph(paragraph, paragraphNumber);
}
}
if ( !paragraph.empty() )
{
processParagraph(paragraph, paragraphNumber);
}
}
It seems that you want to split this functionality out into a separate function, that can either take a filename or an open file stream. Then call this function once for each file.
void getBookData(bookType books[], int& noOfBooks)
{
ifstream infile;
string file = "bookData.txt";
infile.open(file.c_str());
if (infile.fail()) {
cout << "No file found!" << endl;
infile.clear();
}
while (true) {
string line;
getline(infile, line, '\r');
if (infile.fail()) {
break;
}
cout << "Line: " << line << endl;
}
infile.close();
}
I've tried putting the file in every location I can think of, but somehow it's not loading in. Or, more likely, I'm doing something else wrong. This isn't anything like what the end result of my code is supposed to be like, right now I'm just trying to read out my file line by line.
I guess you really need help debugging why this is happening to you.
Try adding some more code to your routine to help you determine what is going on. One thing to try is to call getcwd.
#include <unistd.h>
...
char buf[PATH_MAX];
std::cout << "cwd: " << getcwd(buf, sizeof(buf)) << std::endl;
...
This should report to you where your program thinks it is running from.
Start with that first, and I am guessing the next steps will become obvious to you.
I am trying to read a poorly formatted text file, and maybe I'm going about this the wrong way, but based on the getline documentation it sounded like it would pull values until the values weren't a delimiter value (' ', in my case):
"If the delimiter is found, it is extracted and discarded, i.e. it is
not stored and the next input operation will begin after it. If you
don't want this character to be extracted, you can use member get
instead."
But for some reason it returns nothing many times. See lines 604-607, all those commas in my output are returns of getline. Could someone tell me why it is returning blanks 6 times before it comes to the value? The text file only contains one space before the value. Thanks in advance. :)
Relevant screenshot: http://j.drhu.me/2011-09-07_1317.png
#include <iostream>
#include <fstream>
#include <string>
void CMuscleModel::LoadOpParams()
{
int i, j;
ifstream param("params.txt", ios::in);
if (param.is_open())
{
stringstream iss, isn;
string line, word;
i=0; j=0;
while (getline(param,line))
{
isn.clear();
isn << line;
if(i>27){
while (getline(isn,word,' ')) {
//LGma[i][j]=atof(word.c_str());
if(word == "SM"){
getline(param,line);
cout << line << endl << endl;
isn.clear(); isn << line;
getline(isn,word,' ');
int junk=0;
while (atof(word.c_str())==0){
junk++;
getline(isn,word,' ');
}
cout << atof(word.c_str()) << ", " << junk << endl;
}
if(word == "ST"){
cout << word << endl;
}
if(word == "BFL"){
cout << word << endl;
}
if(word == "BFS"){
cout << word << endl;
}
if(word == "MG"){
cout << word << endl;
}
if(word == "LG"){
cout << word << endl;
}
if(word == "RF"){
cout << word << endl;
}
if(word == "VM"){
cout << word << endl;
}
if(word == "VL"){
cout << word << endl;
}
if(word == "VI"){
cout << word << endl;
}
j++;
}
}
j=0; i++;
isn.clear();
}
}
param.close();
}
Ah, sorry for not including code.
If you're using space as a delimiter anytime it's encountered getline will return with whatever there was upto the delimiter. If the file had 5 spaces in a row before any other characters for example you'd now have to call getline 6 times.
Perhaps use the default newline character instead '\n'?
Edit: Didn't see code before. Perhaps restructure your code to read lines and then use find in conjunction with substr on each line to search for your keywords? Would be simpler code and less looping. There is no reason to read from the file only to output to a stringstream which you then read from.
Bi-directional I/O with std::stringstream is really ambiguous. I recommand that you use it a little differently.
ifstream param("params.txt", ios::in);
if (param.is_open())
{
stringstream iss;
string line, word;
i=0; j=0;
while (getline(param,line))
{
istringstream isn(line);
// ...
}
}
This creates a fresh string stream with clean state and contains the contents of the line read from the file each time. If you really want to re-use the instance for reading tokens on multiple lines, I recommand you use the .str(line) syntax rather than .clear() and operator<<.
If you want to clear the whitespace at the beginning of each line, you can use the std::ws manipulator:
istringstream isn(line);
isn >> ws;
// ...
I think the output text file I was reading from had trailing spaces and they were just being put into the stream so I was really confused about what was going on. I simply used .str("") at the end of each line to reset my current stream and things worked out marvelously. Thanks for all the help guys.
when running the following code, the amount of lines will read on less then there actually is (if the input file is main itself, or otherwise)
why is this and how can i change that fact (besides for just adding 1)?
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
// open text file for input
string file_name;
cout << "please enter file name: ";
cin >> file_name;
// associate the input file stream with a text file
ifstream infile(file_name.c_str());
// error checking for a valid filename
if ( !infile ) {
cerr << "Unable to open file "
<< file_name << " -- quitting!\n";
return( -1 );
}
else cout << "\n";
// some data structures to perform the function
vector<string> lines_of_text;
string textline;
// read in text file, line by line
while (getline( infile, textline, '\n' )) {
// add the new element to the vector
lines_of_text.push_back( textline );
// print the 'back' vector element - see the STL documentation
cout << "line read: " << lines_of_text.back() << "\n";
}
cout<<lines_of_text.size();
return 0;
}
The code you have is sound. Here's a small test case that might help:
void read_lines(std::istream& input) {
using namespace std;
vector<string> lines;
for (string line; getline(input, line);) {
lines.push_back(line);
cout << "read: " << lines.back() << '\n';
}
cout << "size: " << lines.size() << '\n';
}
int main() {
{
std::istringstream ss ("abc\n\n");
read_lines(ss);
}
std::cout << "---\n";
{
std::istringstream ss ("abc\n123\n");
read_lines(ss);
}
std::cout << "---\n";
{
std::istringstream ss ("abc\n123"); // last line missing newline
read_lines(ss);
}
return 0;
}
Output:
read: abc
read:
size: 2
---
read: abc
read: 123
size: 2
---
read: abc
read: 123
size: 2
I think I have tracked down the source of your problem. In Code::Blocks, a completely empty file will report that there is 1 line in it (the current one) in the gizmo on the status bar at the bottom of the IDE. This means that were you actually to enter a line of text, it would be line 1. In other words, Code::Blocks will normally over-report the number of actual lines in a file. You should never depend on CB, or any other IDE, to find out info on files - that's not what they are for.
Well, if the last line of your file is just '\n', you don't push it into the vector. If you want it to be there, change the loop to:
while (getline( infile, textline, '\n' ).gcount() > 0)
{
if (infile.fail()) break; //An error occurred, break or do something else
// add the new element to the vector
lines_of_text.push_back( textline );
// print the 'back' vector element - see the STL documentation
cout << "line read: " << lines_of_text.back() << "\n";
}
Use the gcount() member to check how many characters were read in the last read - this will return 1 if it only read a delimiter character.
Ok so here is an explanation that you will hopefully understand. Your code should work fine if the file we're talking about doesn't end with newline. But what if it does? Let's say it looks like this:
"line 1"
"line 2"
""
Or as a sequence of characters:
line 1\nline 2\n
This file has THREE lines -- the last one being empty but it's there. After calling getline twice, you've read all the characters from the file. The third call to getline will say oops, end of file, sorry no more characters so you'll see only two lines of text.