Reading text from file into a user-defined object

(Working on windows 7 with Visual Studio 2010.)

Hello! Beginner here and I am working on random file I/O and I have a text file of tool records that is in the format

3 Electric sander 7 57.98
17 Hammer 76 11.99
24 Jig saw 21 11.00
.........

My problem is trying to use the overloaded >> operator to read each tool record into my Tool object

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Tool                      
{
	friend istream &operator>>(istream&, Tool&);
protected:
	int recordNum;
	char toolName[30];              
        int quantity;   
	double cost;
public:
	Tool(int = 0, string = "", int = 0, double = 0.0);
	int getRecordNum() const;
	void setRecordNum(int);
	string getToolName() const;
	void setToolName(string);
	int getQuantity() const;
	void setQuantity(int);
	double getCost() const;
	void setCost(double);
};

Tool::Tool(int x, string tName, int y, double d)
{
	recordNum = x;
	setToolName( tName );
	quantity = y;
	cost = d;
}

string Tool::getToolName() const
{
	return toolName;
}

void Tool::setToolName(string s)
{
   int length = s.size();
   length = ( length < 30 ? length : 29 );
   s.copy( toolName, length );
   toolName[ length ] = '\0';
}
................


The toolName is where I am having an issue, Originally I was using user input to capture the information and I had it working just fine using
1
2
3
4
5
6
7
8
9
10
11
12
13
14
istream &operator>>(istream &input, Tool &t)
{
	cout << "Enter new tool name: ";
	cin.ignore();
	cin.get(t.toolName, 30);
	cin.clear();
	cin.ignore(INT_MAX,'\n');

	cout << "Enter new quantity: ";
	input >> t.quantity;
	cout << "Enter new cost: ";
	input >> t.cost;
	return input;
}


I could capture the tool name regardless of how many spaces were inputted and it stopped at 30 characters. But then my requirements changed and now I am trying to capture the data off of the text file I showed above.

To read in from the file I am using the function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void loadData(fstream &inOutFile)
{
	
	ifstream starter("test.txt", ios::in);
	Tool tt;

	while (!starter.eof())
	{
		starter >> tt;

		inOutFile.seekp((tt.getRecordNum() - 1) * sizeof(Tool));
		inOutFile.write((char*)(&tt), sizeof(Tool));
	}
}


I can't figure out how to correctly read in the tool name when it is 2 or more separate words.

I tried researching get and getline and adapting my earlier code for the user input collection like so:
1
2
3
4
5
6
7
8
9
10
istream &operator>>(istream &input, Tool &t)
{
	input >> t.recordNum;
	input.get(t.toolName, 30);
	input.clear();
	input.ignore();

	input >> t.quantity >> t.cost;
        return input;
}


but that resulted in black tool names and skipping over records

I also messed around with things like this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
istream &operator>>(istream &input, Tool &t)
{
	input >> t.recordNum;

	int x = 0;
	while(x < 30)
	{
		 input.get(t.toolName[x]);
		 if(isdigit(t.toolName[x]))
		 {
			 input.clear();
			input.ignore();
			break;
		 }
		 x+=1;
	}

	input >> t.quantity >> t.cost;
	return input;
}


which resulted in gibberish such as

3 Electric sander 7ÌÌÌÌÌÌÌÌÌÌÌÌÌÌ957 0.98


If someone could point me in the right direction how to read in this information correctly that would be fantastic, thank you!
Last edited on
Any advice?
I would change char toolName[30]; to a string string toolName;. Then I would change the input file to look like this.

1
2
3
3 7 57.98 Electric sander
17 76 11.99 Hammer
24 21 11.00 Jig saw


then you can just input the first three numbers
input >> num1 >> num2 >> num3
then use getline to get the rest of the line, spaces wont be a problem.

You could also change the input file like this.
1
2
3
3 Electric sander  :  7 57.98
17 Hammer  :   76 11.99
24 Jig saw  :   21 11.00


input the first number then use getline like this getline(input, str, ':') this form of getline will input up to the : instead of the '\n'. Then just input the other numbers.
Last edited on
Thanks! That worked, I didn't even think about changing the input file I was focused all on the code

changed input file to use ":" after tool name

and then used

1
2
3
4
5
6
7
8
9
10
11
istream &operator>>(istream &input, Tool &t)
{
	input >> t.recordNum;

	input.get(t.toolName, 30, ':');
	input.ignore();
	
	input >> t.quantity >> t.cost;

	return input;
}


everything is good
Topic archived. No new replies allowed.