reading from .dat file

Pages: 12
So if I output one contract object to each line, I should be able to extract it correctly using getline()?
Yeah you should be able to.
1
2
3
4
5
6
7
8
9
        ifstream dataIn; //input stream for data file
        //see if there's anything in it and import the data
	vector<Contract> contracts; //initialize a vector to hold all the contracts
	Contract temp; //initialize a temporary var to store the read data into

	while(!dataIn.eof()){ //read until end of file
		getline(dataIn,temp,'\n');
		contracts.push_back(temp);
	}


for some reason it says that the arguments don't match... I think it's the delimiter... I've read up on delimiters and they're supposed to be chars. I thought \n was the LF character... It could also be the stream. I don't know... Could I bug you for another insight?

EDIT:
I found out that the delimiter is optional and defaulted to '\n'. When I leave the delimiter off, it tells me there are too few arguments! I'm so confused!
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const string FILE = "contracts.txt"; //filename
	filebuf fb;
	fb.open(FILE,ios::in);
	istream dataIn(&fb); //input stream for data file
	//if it can't be opened, there's a problem and the program won't work. It will most likely be a permission issue.
	if(!dataIn) {
		cout << "File could not be opened/created. Make sure you have the correct permissions. This program will now close \n";
		system("pause");
		exit(1);
	}

	//see if there's anything in it and import the data
	vector<Contract> contracts; //initialize a vector to hold all the contracts
	Contract temp; //initialize a temporary var to store the read data into

	while(!dataIn.eof()){ //read until end of file
		dataIn.getline(temp, 10000);
		contracts.push_back(temp);
	}


OKAY. This is what I have after reading the istream getline (that would probably help, right?). Apparently I'm really bad at reading these things... Anyway, temp is a contract object and not a pointer to an array of characters as required... I have NO idea how to fix this...

I'm also assuming that there will be one contract per line and I don't know how many characters or whatever that object will take up so I chose an arbitrarily high number... Not sure if that's okay or not.
Last edited on
Well \n is the same as endl the both are end of line or new line and makes the cursor go to the next line when encountered. If that is your exact code, the first thing I see is that you don't open the file in order to read in from it. You declare the variable to hold the file but don't have the file.

1
2
3
4
5
6
7
8
9
10
ifstream dataIn;
dataIn.open("file.dat"); // didn't have this, are you loading your datafile?

vector<Contract> contracts;
Contract temp;

while (!dataIn.eof()){
     getline(dataIn, temp);
     contracts.push_back(temp);
}


Outside of that, I don't know as I would have to have the full code and datafile to test on my end to help more.

Here I did a quick section of code to test it in a simple manner.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main()
{
     ifstream dataIn;
     dataIn.open("test.dat");
     string temp; 
     
     while(!dataIn.eof())
     {
          getline(dataIn, temp);
          cout << temp << '\n'; 
      }
      
      dataIn.close();
      return 0;
}

Test.dat

This is just a test.
This is another test.
Parse this.
Last test.

output

This is just a test.
This is another test.
Parse this.
Last test.


Try changing Contract temp; to string temp; and remember to include the string header. Just to see if it fixes the problem or causes more.
Last edited on by closed account z6A9GNh0
no, it's supposed to be a string, not a contract, but I want it to be a contract and I don't know how to overload the function to handle it...
Well doing Contract is making it a class object. Not sure if there is a way to overload string to make it Contract. Though, don't quote me on that as I don't do much overloading right now. Honestly though, trying to overload data types when simple types will do is making the project harder than it needs to be.
Last edited on by closed account z6A9GNh0
getline works with std::strings, temp is not a std::string. The answer has been given to you, you should overload operator>> and no one can really help you write it unless you show an example of the contents of the file.
I find it's easier to work on retrieving after you've worked out the best way to store it.

http://www.parashift.com/c++-faq-lite/serialization.html is some reading you should probably do.

Here's a small working example for you to pick apart:

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <memory>

struct ContactInfo
{
	std::string name ;
	std::vector<std::string> email ;

	ContactInfo() {}

	ContactInfo( std::string name_, const std::vector<std::string>& email_ ):name(name_), email(email_) {}
};

namespace{
	// utility functions
	// I know all these sizes will be < 256.  It may not be an assumption you want to make.
	unsigned writeSize(std::ofstream& out, unsigned sz)
	{
		unsigned char size = static_cast<unsigned char>(sz) ;
		out.write(reinterpret_cast<char*>(&size), sizeof(size)) ;
		return size ;
	}

	unsigned readSize(std::ifstream&in)
	{
		unsigned char sz ;
		in.read(reinterpret_cast<char*>(&sz), sizeof(sz)) ;
		return sz ;
	}
}

std::ofstream& Write(std::ofstream& out, const ContactInfo& ci)
{
	unsigned size = writeSize(out, ci.name.length()+1) ;
	out.write(ci.name.data(), size) ;

	size = writeSize(out, ci.email.size()) ;
	
	for( unsigned i=0 ; i < ci.email.size() ; ++i )
	{
		size = writeSize(out, ci.email[i].length()+1);
		out.write(ci.email[i].data(), size) ;
	}

	return out ;
}

std::ifstream& Read(std::ifstream& in, ContactInfo& ci)
{
	unsigned size = readSize(in) ;
	std::auto_ptr<char> buffer(new char[256]) ;

	in.read(buffer.get(), size) ;
	ci.name.assign(buffer.get()) ;

	unsigned v_size=readSize(in) ;

	ci.email.clear() ;
	for ( unsigned i=0; i<v_size; ++i)
	{
		size=readSize(in) ;
		in.read(buffer.get(), size) ;
		ci.email.push_back(std::string(buffer.get())) ;
	}
	return in ;
}


std::ostream& operator <<(std::ostream& out, const ContactInfo& ci )
{
	out << "Name: " << ci.name << "\nEmail: " ;
	for ( unsigned i=0; i < ci.email.size() ; ++i )
		out << ci.email[i] << ' ' ;
	return out << '\n' ;
}

std::string  email[] = 
{ "hobo320@yahoo.com","hobo320@msn.com","train.wreck@gapers.crawl"};

std::string email2[] =
{"pixiedust@hogrider.com","lookatthis@cakefarts.com"};


int main(void)
{
	std::vector<ContactInfo> contacts ;

	contacts.push_back(ContactInfo("Dwight Eisenhower", 
		std::vector<std::string>( email, email+(sizeof(email)/sizeof(email[0])) ) )) ;

	contacts.push_back(ContactInfo("Henry Hudson",
		std::vector<std::string>( email2, email2+(sizeof(email2)/sizeof(email2[0])) ) )) ;

	{
		std::ofstream out( "ContactInfo.dat", std::ios::out | std::ios::trunc | std::ios::binary ) ;

		unsigned c_size = contacts.size() ;
		writeSize(out, c_size) ;

		for ( unsigned i=0 ; i<contacts.size(); ++i)
			Write(out, contacts[i]) ;
	}
	contacts.clear() ;

	{
		std::ifstream in( "ContactInfo.dat", std::ios::in | std::ios::binary) ;
		contacts.resize(readSize(in)) ;

		for ( unsigned i=0; i<contacts.size(); ++i)
			Read(in, contacts[i]) ;
	}

	for ( unsigned i=0; i<contacts.size() ; ++i )
		std::cout << contacts[i] << '\n' ;
}
Let me see if I'm understanding what you want. You want to call Contract temp; instead of string temp; but you want Contract to act like a string? If that is the case then at the top of your program (and I hate recommending this) under all the includes and using lines put:

 
#define Contract string 


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

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

#define Contract string

int main()
{
     ifstream dataIn;
     dataIn.open("test.dat");
     Contract temp; 
     
     while(!dataIn.eof())
     {
          getline(dataIn, temp);
          cout << temp << '\n'; 
      }
      
      dataIn.close();
      return 0;
}


But you can't have anything else named Contract as it would translate it to string. So if you had, say struct Contract{};, it would be read as struct string{};. Outside of that you are making this way too difficult for a fairly simple thing.
The main thing wrong with what you have is that Contract is an object, not a string. When you getline(), you need to reference the string within Contract.
Topic archived. No new replies allowed.
Pages: 12