Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

reading text file in c++

Posted on 2007-11-22
30
Medium Priority
?
454 Views
Last Modified: 2008-05-25
Hi,

I have a text file & it is having content as
2|50000|1000|S|Abc|0
I would like to read the above file and assign values to six variables: integer and string.

Here, I am using C++ and solaris is the Operating system.
Please tell me like how to do that in C++?

thanks,
shankarraj
0
Comment
Question by:shankarraj
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 8
  • 7
  • +4
30 Comments
 
LVL 53

Assisted Solution

by:Infinity08
Infinity08 earned 100 total points
ID: 20333741
Here's a good introduction to I/O with files in C++ :

        http://www.cplusplus.com/doc/tutorial/files.html


An easy way would be to use getline to read a line from the file :

        http://www.cplusplus.com/reference/string/getline.html

and then use string operations (substr, find) to extract the tokens from the line :

        http://www.cplusplus.com/reference/string/string/find.html
        http://www.cplusplus.com/reference/string/string/substr.html
0
 
LVL 11

Assisted Solution

by:Deepu Abraham
Deepu Abraham earned 100 total points
ID: 20333794
For pipe delimited files
http://www.augustcouncil.com/~tgibson/tutorial/iotips.html
This may as well help you.
Best Regards,
DeepuAbrahamK
0
 
LVL 17

Assisted Solution

by:rstaveley
rstaveley earned 100 total points
ID: 20334000
A combination of getline and extraction on an istringstream does the trick nicely with this sort of thing. Experience says don't do it directly with the ifstream, because one bad line thrhows it all out of kilter otherwise.

The not-so-secret weapon here is using '|' as the delimiter to getline.
#include <fstream>
#include <sstream>
#include <iostream>
 
int main()
{
	std::ifstream fin("x.dat");
	std::string str;
	while (getline(fin,str)) {
		std::istringstream istr(str);
 
		// For the likes of "2|50000|1000|S|Abc|0"
		std::string str1,str2;
		int i1,i2,i3,i4;
		char junk;
 
		if (
			(istr >> i1) && (istr >> junk) && (junk == '|')
		&&	(istr >> i2) && (istr >> junk) && (junk == '|')
		&&	(istr >> i3) && (istr >> junk) && (junk == '|')
		&&	getline(istr,str1,'|')
		&&	getline(istr,str2,'|')
		&&	(istr >> i4) /*&& (istr >> junk) && (junk == '|')*/
		) {
			std::cout << i1 << '|' << i2 << '|' << i3 << '|' << str1 << '|' << str2 << '|' << i4 << '\n';
		}
	}
}

Open in new window

0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 39

Assisted Solution

by:itsmeandnobodyelse
itsmeandnobodyelse earned 100 total points
ID: 20334030
You can read the file with

#include <fstream>
#include <string>
using namespace std;

       

        ifstream  file("file.dat");
        string line;
        while (getline(file, line))
        {
             ...
        }
        file.close();


That reads the file line by line.

For the ...

you should parse the string line like that:

     line += '|';   // add a final delimiter
     int pos = 0;
     int lpos = 0;
     int nitem = 0;
     while ((pos = (int)line.find('|', lpos)) != string::npos)
     {
            string item = line.substr(pos, lpos - pos);
            ...
            nitem++;
            lpos = pos + 1;
     }


Put the following below includes and above all code or in a header file:

#include <sstream>

enum { FLD0, FLD1 , FLD2, FLD3, FLD4, FLD5, FLD_MAX };

struct Record
{
     int ifld0;
     int ifld1;
     int ifld2;
     char cfld3;
     string sfld4;
     int ifld5;
     
};
 
For the ...  you may evaluate the columns like taht:

          Record rec;
          switch(nitem)
          {
              case FLD0:  
              {
                     istringstream iss(item);
                     if (!iss >> rec.ifld0)
                     {
                             cout << "wrong item " << item << endl;
                             return;
                     }
               }
               break;
              case FLD1:  
              {
                     // dito to FLD0
              }
              break;
              ...
              case FLD3:  
              {
                     if (item.length() != 1)
                     {
                             cout << "wrong item " << item << endl;
                             return;
                     }
                     rec.cfld3 = item[i];
               }
               break;
              case FLD4:   rec.sfld4 = item; break;
              case FLD5:  
              {
                     // dito to FLD0
              }
                 
          }
          ...

Finally you  have to store the Record rec to some container and array. I would suggest

   std::vector<Record> records;

Then the ... would be


       records.push_back(rec);


Regards, Alex


         

0
 
LVL 53

Expert Comment

by:Infinity08
ID: 20334212
Heh ... as usual, you're more elaborate in your replies than me, Alex ... ;)
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20334390
>>>> you're more elaborate in your replies than me, Alex ...

'elaborate' ??? you mean chatty?

Rob, only needs one third of that I needed ... most likely you'll get the points ... oh the world is bad ...
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 20334477
>> 'elaborate' ??? you mean chatty?

http://www.merriam-webster.com/dictionary/elaborate    ;)

That was a compliment btw !!
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20334996
I like the Latin 'elaboratus'  ;-)

0
 
LVL 17

Expert Comment

by:rstaveley
ID: 20335144
There is nothing wrong with a good chat, lubricated of course by an excellent Belgian beer.

Infinity08, do you get an "Attach beer snippet" checkbox in your locale? 8-)
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 20335237
>> Infinity08, do you get an "Attach beer snippet" checkbox in your locale? 8-)

I wish ... I would probably add a good Rochefort 8 trappist beer (one of my favorite Belgian beers) :) Mmm ... with a bit of cheese on the side, it's just perfect heh
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20335291
>>>> by an excellent Belgian beer.
it is 'perfumed', isn't it? Did you never hear of 'beer purity law' ?

BTW, I have draft beer (Philipps system 6 liters, mostly with Becks) in my home bureau. Nearly as good as a checkbox and much more real ;-)  The only problem is that I am 'on the road' from Monday to Thursday ...
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 20335364
>> id you never hear of 'beer purity law' ?

No, but a short look on the internet reveals that the ingredients of beer can only be barley, hops and water. That's quite limiting, and doesn't permit "alive" beer, since you can't use yeast ... it also doesn't include sugar which is commonly used for the "good" beers.

These are the 5 ingredients of a Rochefort trappist beer : water, hops, barley, yeast and sugar.
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 20335398
It's liquid bread really. I'll look out for Rochefort. I'm still a Trappist newbie, but eager to learn more.
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 20335427
Here's my general solution (religion/culture permitting):
not_so_std::beerstream beer("Rochefort");
while (beer >> rstaveley >> Infinity08 >> itsemeandnobodyelse)
    ;

Open in new window

0
 
LVL 17

Expert Comment

by:rstaveley
ID: 20335434
Hmmm... I think Infinity08 had too much, he got syntax highlighted!
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 20335439
Why do you get served first ? lol

On the upside, my name is in purple ... hehe
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20335492
>>>> yeast
Actually there is no beer without yeast. But they didn't mention it in the law (most likely they didn't want to confuse the customers?)

>>>> sugar
Brrrrrrrrr. Didn't I say it it is 'perfumed'. Ever heard that a 'real' man drinks sweet beer?

>>>> Why do you get served first ? lol
You can get my share. I've heard the dregs contain most of the sugar....
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 20335739
>> >>>> sugar
>> Brrrrrrrrr. Didn't I say it it is 'perfumed'. Ever heard that a 'real' man drinks sweet beer?

Oh, but the beer is not sweet. The sugar is converted to alcohol, and is added to have a higher alcohol percentage. The Rochefort 8 I mentioned for example is about 9% alcohol. I've drank beers upto 15% in Belgium.
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 20335783
> I've drank beers upto 15% in Belgium.

That's enough to make you go purple.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 20335788
lol
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20337801
> I've drank beers upto 15% in Belgium.
I've drunk (bock) beer up to 21% ... of course ... no sugar

>>>> That's enough to make you go purple
When lying under the table the colors don't matter ;-)

BTW, I am at home today but I've to wait until noon (f...ing principles) before I get my first beer ...
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 20337826
>> I've drunk (bock) beer up to 21%

Wow ... never heard of a Bock with that much alcohol ... must have been some special brew ...
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 20337874
> I've to wait until noon

"I like a good beer buzz early in the morning..." (S. Crow)
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 20337914
I think shankarraj has given up on us in despair.
0
 
LVL 40

Accepted Solution

by:
evilrix earned 100 total points
ID: 20345750
Fully working example.
//  Required for std::stringstream
#include <sstream>
 
// Required for for_each()
#include <algorithm>
 
// Required for std::istream
#include <iostream>
 
// Required for std::vector
#include <vector>
 
// Data -- POD type (this could also be a proper class!)
struct Data
{
	int field1;
	int field2;
	int field3;
	char field4;
	std::string field5;
	int field6;
};
 
// Overloaded input stream operator
std::istream & operator >> (std::istream & is, Data & data)
{
	std::string line;
	getline(is, line);
 
	if(is.good())
	{
		std::string::size_type pos = 0;
		std::string::size_type lpos = 0;
 
		int const LAST_FIELD = 6;
 
		for(int field = 0 ; field < LAST_FIELD ; ++ field)
		{
 
			// Find end of field
			if(std::string::npos == (pos = line.find('|', lpos)))
			{
				// If not found and last field use size
				if((LAST_FIELD - 1) == field)
				{
					pos = line.size();
				}
				else // If not last field we have an error condition
				{
					throw std::runtime_error("Invalid record structure");
				}
			}
 
			// Use to convert to the required data type
			std::stringstream ssField(line.substr(lpos, (pos - lpos)));
 
			// Start of next field
			lpos = pos + 1;
 
			// Extract field
			switch(field)
			{
			case 0:
				ssField >> data.field1;
				break;
			case 1:
				ssField >> data.field2;
				break;
			case 2:
				ssField >> data.field3;
				break;
			case 3:
				ssField >> data.field4;
				break;
			case 4:
				ssField >> data.field5;
				break;
			case 5:
				ssField >> data.field6;
				break;
			default:
				// We should never get here!
				throw std::runtime_error("Invalid record size");
				break;
			}
		}
	}
 
	return is;
}
 
// Typedef to make code more readable
typedef std::vector<Data> DataVector;
 
// Processes stream and builds a vector of records
void ProcessStream(std::istream & is, DataVector & dv)
{
	for(;;)
	{
		// Create new data structure
		Data data = {0};
 
		// Stream out next record
		is >> data ;
 
		// Process file until EOF or error
		if(is.eof()) { break; }
		if(is.bad()) { throw std::runtime_error("Error. Bad file stream."); }
 
		// Store record in vector
		dv.push_back(data);
	}
}
 
// Output functor (just for demo purposes)
class OutputResult
{
public:
	OutputResult(): m_nRecCnt(0){}
	void operator()(Data const & data)
	{
		++ m_nRecCnt;
		std::cout
			<< "Record: " << m_nRecCnt << std::endl
			<< "- Field1: " << data.field1 << std::endl
			<< "- Field2: " << data.field2 << std::endl
			<< "- Field3: " << data.field3 << std::endl
			<< "- Field4: " << data.field4 << std::endl
			<< "- Field5: " << data.field5 << std::endl
			<< "- Field6: " << data.field6 << std::endl
			<< std::endl;
	}
private:
	int m_nRecCnt;
};
 
int main()
{
	// Test data (this can be from an ifstream -- e.g. ifstream testdata("testdata.txt"))
	std::stringstream testdata (
		"1|50000|1000|S|Abc|0\n"
		"2|50001|1001|T|Def|1\n"
		"3|50002|1002|U|Ghi|2\n"
		"4|50003|1003|V|Jkl|3\n"
		"5|50003|1004|W|Mno|4\n"
		"6|50003|1005|X|Pqr|5\n"
		"7|50003|1006|Y|Stu|6\n"
	);
 
	// Data will be read into this vector
	DataVector dv;
 
	// Process data from stream
	ProcessStream(testdata, dv);
 
	// Output records in vector
	std::for_each(dv.begin(), dv.end(), OutputResult());
 
	return 0;
}

Open in new window

0
 
LVL 40

Expert Comment

by:evilrix
ID: 20345755
If you want to catch and explicitly report the thrown exceptions change main to be like this...
int main()
{
	int nRetval = 0;
 
	try
	{
		// Test data (this can be from an ifstream -- e.g. ifstream testdata("testdata.txt"))
		std::stringstream testdata (
			"1|50000|1000|S|Abc|0\n"
			"2|50001|1001|T|Def|1\n"
			"3|50002|1002|U|Ghi|2\n"
			"4|50003|1003|V|Jkl|3\n"
			"5|50003|1004|W|Mno|4\n"
			"6|50003|1005|X|Pqr|5\n"
			"7|50003|1006|Y|Stu|6\n"
		);
 
		// Data will be read into this vector
		DataVector dv;
 
		// Process data from stream
		ProcessStream(testdata, dv);
 
		// Output records in vector
		std::for_each(dv.begin(), dv.end(), OutputResult());
	}
	catch(std::exception const & ex)
	{
		std::cerr << ex.what();
		nRetval = -1;
	}
 
	return nRetval;
}

Open in new window

0
 
LVL 6

Expert Comment

by:SJT2003A
ID: 20367690
OK, check the following code. It is a simple example of reading a text file which contains of fields of any type (ie, string, non-string) with | (pipe) delimited.  
The sField is a string stores any type where as nField stores only numberic fields. Just uncomment the commented lines to read from a file.

Check it out. Good luck :)

#include "stdafx.h"
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>

using namespace std;

int main()
{
      string line("123|Samson|262|345 Blvd|North York|L9T 5Y3");
      //ifstream ifstr("mydata.dat");
      istringstream istr;
      string alphabetic("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
      string numeric("1234567890");
      string sField;
      long nField;
      string str;
      int pos, lpos;
      //if (!ifstr) {
      //      cout << "file open error " << endl;
      //      exit(1);
      //}

      //while (getline(ifstr,line)) {  //add this line if it is for a file read
            lpos = 0;
            do {
                  pos = line.find_first_of("|",lpos);
                  str = line.substr(lpos, (pos-lpos));
                  if ( (int(str.find_first_of(alphabetic)) >= 0 && int(str.find_first_of(numeric)) >= 0) || //alphanumeric
                        (int(str.find_first_of(alphabetic)) >= 0) ) { //alphabetic
                        sField = str;
                        cout << sField << endl;
                  }
                  else if (int(str.find_first_of(numeric)) >= 0) { //numeric
                        istr.str(str);
                        istr >> nField;
                        cout << nField << endl;
                        istr.clear();
                  }
                  else { //special chars
                        sField = str;
                        cout << sField << endl;
                  }
                  lpos = pos+1;
            } while (pos >= 0);

      //} //while

      return 0;
}

The output is as follows:

123
Samson
262
345 Blvd
North York
L9T 5Y3
Press any key to continue

 
0
 
LVL 6

Expert Comment

by:SeanDurkin
ID: 21535259
No comment has been added to this question in more than 21 days, so it is now classified as abandoned.

I will leave the following recommendation for this question in the Cleanup Zone:
      Split: rstaveley {http:#20334000} & Infinity08 {http:#20333741} & DeepuAbrahamK {http:#20333794} & itsmeandnobodyelse {http:#20334030} & evilrix {http:#20345750}

Any objections should be posted here in the next 4 days. After that time, the question will be closed.

Sean
EE Cleanup Volunteer
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

610 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question