Multi data types in a line and read to struct

Hello. How can I read this file in to my struct?

1
2
3
4
      12345		Joe Lim KH		879.00
      12233		Kay Suet Yee		35.98
      23781		Leong Jing Yang	        10.00
      67543		Woon Tian Yi		500.50


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

struct master {
	
	unsigned short int IDnum;
	char name[30];
	float salesCustomer; 
	
	};
void setRecord(char masterFile[15], master masterRecord[]){
	int i=0;
	ifstream read;
	read.open(masterFile, ios::in);
	if(!read)
		cout<<"Open Fail";
	else{
		while(!read.eof()){
			
			read>>masterRecord[i].IDnum;
			read>>masterRecord[i].name;
			read>>masterRecord[i].salesCustomer;
			i++
		}
	}	
	
	read.close();
	
	}


not working
Last edited on
1. What characters does the input have between fields?
2. Do all names have three words?
in file there are spaces...what do you mean by three word?
Last edited on
"Joe" is a word. "Lim" is a word. "KH" is a word.
no it could me more than or less than 3 words
What about question 1 then?
I am trying to do this this way

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int setRecord(char masterFile[15], master masterRecord[]){
	int i=0;
	ifstream read;
	read.open(masterFile);
	if(!read)
		cout<<"Open Fail";
	else{
		while(!read.eof()){
			
					read.get(masterRecord[i].IDnum,' ');
					read.get(masterRecord[i].name, 17);
					read.get(masterRecord[i].salesCustomer, '\n');
						
		
		
		
	}	}
	
	read.close();
	return i;
	
	}
The place to start is to understand the format of the data in the file.
The sample posted uses either two tab characters "\t\t" or a single tab followed by some spaces, to separate the fields within the line.

However, I suspect that has been done simply for convenience in posting in this forum. Ideally, the file would stick to a simple, consistent format, such as
12345\tJoe Lim KH\t879.00\n
12233\tKay Suet Yee\t35.98\n
23781\tLeong Jing Yang\t10.00\n
67543\tWoon Tian Yi\t500.50\n
where the '\t' represents the tab character and '\n' represents a newline.

Then separating the three items can be done by using getline() with a specified delimiter (tab, tab and newline), and converting the string to numeric format as necessary.

Otherwise, if there are just unspecified amounts of whitespace, it may be a case of first parsing the line into 'words', then using the first and last words for the numbers, and the middle words to make up the name. Messy, but not impossible.
Last edited on
thanks, I try now :)
Consider writing
1
2
3
4
5
6
std::istream & operator>> ( std::istream & is, master & record )
{
  // code that reads one line from is into record

  return is;
}


Furthermore, use std::string instead of char array for master::name.
@chervil How do you separate the values from getline?
@kesik We are only supposed to use cstring, text file read/write in class...and normal data types
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int setRecord(char masterFile[15], master masterRecord[]){
	int i=0;
	char fileValue[50];
	ifstream read;
	
	read.open(masterFile);
	if(!read)
		cout<<"Open Fail";
	else{
		read>>noskipws;
		while(!read.eof()){			
			read.getline(fileValue, '\n');
			cout<<fileValue;
			/*read.get(masterRecord[i].IDnum, '\t');
			read.get(masterRecord[i].name, '\t');
			read.get(masterRecord[i].salesCustomer, '\n');
			*/}
		
		
	}	


Its not working even getline dont get first line of file!!! :(
Your getline appears to have a logical syntax error. The '\n' is probably used as streamsize.

Nevertheless, you still have not described the exact syntax of the data file.

This code is just a partial guess, because we don't know the format yet:
1
2
3
4
5
6
7
8
9
std::istream & operator>> ( std::istream & is, master & record )
{
  is >> record.IDnum;
  is.width(30);
  is >> record.name;
  // black magic
  is >> record.salesCustomer;
  return is;
}
Its working for only one line..I am close!!!help!! using !read.eof() dont work

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int setRecord(char masterFile[15], master masterRecord[]){
	int i=0;
	char id[10], name[17], sale[8];
	ifstream read;
	
	read.open(masterFile);
	if(!read)
		cout<<"Open Fail";
	else{
		
		while(read.good()){	
			read.get(id, '\t');
			cout<<id;
			read.get(name, '\t');
			cout<<name;
			
			read.get(sale,'\n');
			cout<<sale<<endl;
			
			}
			
	}	
	
	read.close();
	return i;
	
	}


12345	Joe Lim KH	879.00
Last edited on
i couldn't get that code to work.

Try changing
 
    read.get(id, '\t');
to
 
    read.getline(id, sizeof(id), '\t');

and the same for the other two fields.

Also, the status of the read fstream should be checked after the input has been attempted not before. Maybe like this:
1
2
3
4
5
6
7
8
9
10
11
    while (read)
    {
        read.getline(id,    sizeof(id),   '\t');
        read.getline(name,  sizeof(name), '\t');
        read.getline(sale,  sizeof(sale), '\n');
        
        if (read)
        {
            cout << id << " " << name << " " << sale << endl;
        }
    }
Last edited on
Assuming that the name is followed by a tabulator, here is putative // black magic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
std::istream & operator>> ( std::istream & is, master & record )
{
  // skip ws left of number and store number as typeof(IDnum)
  is >> record.IDnum;

  const size_t Len = sizeof( record.name );
  // skip ws left of name and store first word (at most Len-1 characters) into array 'name'
  is.width( Len );
  is >> record.name;

  // append characters to name, until a tabulator is found (or array is full)
  const size_t Pos = strlen( record.name );
  if ( Pos < Len )
  {
    is.getline( record.name + Pos,  Len - Pos, '\t');
    // check for errors that getline may set and solve them
  }
  else
  {
    // solve potential error.
  }

  // skip ws left of number and store number as typeof(salesCustomer)
  is >> record.salesCustomer;
  return is;
}

The idea is to use formatted input in order discard surplus whitespace, but read in additional words of the name unformatted to keep spaces between them. The file has to have a tabulator after the name for this to work.

Now we can do:
1
2
3
4
i = 0;
while ( i < masterRecordSize && read >> masterRecord[i] ) {
  ++i;
}

C-strings: check
Text input: check
"normal" types: check
Thanks I solved it :)
Topic archived. No new replies allowed.