Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

How to read multi-word strings from a file

Posted on 2003-03-28
13
Medium Priority
?
319 Views
Last Modified: 2008-01-16

Plz examin the following code.

struct employee
{
     int code;
     char name[100];
     float salary;
};

void main()
{
     employee e1;
     ofstream f1("Employee.txt");
     for(int i=1;i<=10;i++)
     {
          cout<<"Enter Code, Name and Salary : ";
          cin>>e1.code>>e1.name>>e1.sal;
          f1<<e1.code"\t"<<e1.name<<"\t"<<e1.salary;
     }
}
     
   This will write 10 employee records on to a file "Employee.txt".
Assume that the employee name is a multi-word string. Then,
how to read it back from that file ?

void main()
{
     struct employee e1;
     ifstream f1("Employee.txt");
     while(!f1.eof())
     {
          f1>>e1.code>>e1.name>>e1.salary;
          cout<<"\n\n\t"<<e1.code<<"\t"<<e1.name<<"\t"<<e1.salary;
     }
}

   This won't work. The overloaded extraction operator is not
capable of reading multi-word strings from a file.

   Plz suggest a solution for this problem.
0
Comment
Question by:balakiran_bs
  • 4
  • 3
  • 3
  • +2
12 Comments
 
LVL 8

Expert Comment

by:Exceter
ID: 8225560
You need to use getline to accomplish this. For example,

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    char name[100];
    ifstream in( "test.txt", ios::in );
    in.getline( name, 100, '\n' );
    cout << name << endl;
    return 0;
}

-- Test.txt --

My name is Exceter

-- output --

My name is Exceter

Exceter
0
 
LVL 8

Accepted Solution

by:
Exceter earned 100 total points
ID: 8225594
Oops, I forgot to leave space on the end of name to account for the null byte. This would not bother unless getline actually read in 100 charcters from disk. In which case it would attempt to assign the bull byte to position 100 which does not exist as name's highest index is 99. So the following,

>> in.getline( name, 100, '\n' );

should be,

in.getline( name, 99, '\n' );

Exceter
0
 
LVL 12

Assisted Solution

by:Salte
Salte earned 100 total points
ID: 8225618
I will suggest you use some form of field separator which isn't space between each field. The reason why it shouldn't be space is that space is a legal character in the name (which is why it is multi word).

so, assuming you use ':' or ',' or whatever to separate the code, name and salary you can simple read it like this:

f1 >> e1.code;
f1.ignore(1024,':'); // read and ignore until ':'
f1.getline(e1.name,':'); // read name
f1.ignore(1,':'); // read and ignore the ':'
f1 >> e1.salary
f1.ignore(1024,'\n');

I would believe you also have to do something similar in the input from user, except you typically don't use a separator character in that case but rather have separate questions, if you want you can use a separator character in that case too, if so the code is similar to the above.

Also, I notice you have some 'nuisance' in your original code and my code above assume you have fixed that. You do not terminate the record with a newline character, so the whole file becomes one huge line with code, name, salary, code, name, salary etc... such a file will be very difficult to read if you want to read it in an editor and so I suggest you rather insert a end of line after each salary so that each employee's record comes on a line of its own.

So add a << endl after the salary when you make the file.

Alf
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 8

Expert Comment

by:Exceter
ID: 8225628
The problem you are experiencing is simply that all in streams break when they encounter a space character because they are derived from the same base class. You will notice the same phenomenon when you use cin. For example,

char name[100];
cin >> name;

Type multiple words. You will notice that only the first word is stored in name.

Exceter
0
 
LVL 12

Expert Comment

by:Salte
ID: 8225786
One thing,

my getline() is a bit fast, you need an argument specifying the size of the array also:

f1.getline(e.name,sizoef(e.name),':');

is correct usage.

f1.getline(...,...,':');

will not break at space but will break at ':' (or whatever character you choose for your field separator character).

Alf
0
 
LVL 41

Expert Comment

by:Kyle Abrahams
ID: 8229445
You could also use string.append(source, stuff to append); if you wanted to keep each thing separate.
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 8236605
I would suggest that you write an entire object to the file and read an entire object from the file instead of reading/ writing strings and numbers at the same time.

Mayank.
0
 
LVL 8

Expert Comment

by:Exceter
ID: 8243245
>> I would suggest that you write an entire object to the file and read an entire object from the file instead of reading/ writing strings
>> and numbers at the same time.

How would you go about doing that? As I understand things, object serialization is not nearly as simple in C++ as it is in other languages, such as Java for example.

Exceter
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 8243294
Why can't you use the read (), write () functions:

class Employee
{    
  int code ;
  char name[100] ;
  double salary ;
public:
  ..
  .. // memner functions

} ;
 
..
.. // in some member function
ofstream fout ;
four.write ( ( char * ) this, sizeof ( * this ) ) ;

..
..
ifstream fin ;
fin.read ( ( char * ) this, sizeof ( * this ) ) ;

Mayank.
0
 
LVL 12

Expert Comment

by:Salte
ID: 8244476
Mayank,

that gives a binary file (should be opened with ios::binary) and might be difficult if he wants to inspect the file using a regular editor.

The specification he originally gave is such that a file using some specific character (not space) to separate the fields should be perfect. I would use either ':' or ';' but virtually any character that doesn't occur in his data can be used.

getline() will then read the file correctly up to but not including the stop character. Using the separator character as stop character for getline() will then get him the current field.

Alf
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 8244521
Actually, the questioner simply asked that how should he read the name if it contains multiple words. Personally, whenever I have to write a structure or an entire object into a file, I always prefer the read () and write () functions, simply because I find them very easy to use and yet very effective. I agree that we get a binary file, but as long as we're not editing the file directly but accessing it only through the program, it gives a very handy way to read data directly into your structure variable (or object).

As per his specifications, if a delimiting character has to be specified for every element in the record (and assuming that he also wants to use an editor to read the file, not just the program), I think it’ll be better to simply write every element in a new-line, e.g.,

Code
Name
Salary

Code
Name
Salary

And individual records can be identified after every 3 or 4 new-lines.

I wonder what he is doing.... he's already got enough comments here to solve his problem in many different ways!

Cheers,

Mayank.
0
 
LVL 9

Expert Comment

by:tinchos
ID: 9566463
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Split points between Exceter & Salte

Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

Tinchos
EE Cleanup Volunteer
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

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

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.
Suggested Courses

581 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