1

What I want to do:

Store records in a file. These records have two things.

time_t rt; //which stores the time the record was entered by the user

and along with this I want to store one string. But I don't know the length of the string.

It will be decided on run time and will depend on how many characters the user enters.

What needs to be done(According to me):

I have no clue. I know about dynamic memory allocation but did not know how to apply this to such a problem.

What I have tried:

I have tried to take one charachter at a time from the user and store it in a text file(Temporarily).

ofstream fileObject;

fileObject.open("temp.txt");

for(int j=0;;j++)
{
  ch = _getche();

if( ch == 13)  break; //user has pressed the return key

  fileObject<<ch;
}

Then I found out the size of the file using the following code:

fileObject.seekp(0,ios::end);

long pos = fileObject.tellg(); //this is the size of the file

Then I declared a dynamic array of the size of the file.

char * entry;

entry = new char[pos]

Closed the file in the "out" mode and opened it again in the "in" mode.

fileObject.close();

ifstream fout;

fout.open("temp.txt"); //this is the name of the text file that i had given

Then character wise I copied the content of the text file into the character array:

for(int i=0;i<pos;i++)

  fout>>info[i];

info[i] = '\0';

fout.close();

But now i dont know what to do further.

What I need you to help me with:

Help me to write this record as a class object into a binary ".dat" file.

My specs:

Windows XP SP 3

IDE: Visual C++ 2010 Express

Peter Wood
  • 23,859
  • 5
  • 60
  • 99
IcyFlame
  • 5,059
  • 21
  • 50
  • 74

4 Answers4

1

use std::string and std::getline, both from the <string> header

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
1

I want to store one string. But I don't know the length of the string.

Then you need to use std::string and not a preallocated array of chars.

struct user_record
{
    time_t rt; //which stores the time the record was entered by the user
    std::string one_string;
};

Help me to write this record as a class object into a binary ".dat" file.

There are a number of serialisation options available to you. Perhaps the simplest is to write this as plain text using the standard stream operations:

std::ostream& operator <<(std::ostream& os, user_record const& ur)
{
    return os << ur.rt << ' ' << ur.one_string;
}

std::istream& operator >>(std::istream& is, user_record& ur)
{
    return is >> ur.rt >> ur.one_string;
}

For anything more involved than a single-line string, then perhaps you should investigate Boost's serialisation library.

johnsyweb
  • 136,902
  • 23
  • 188
  • 247
  • oh! I did not know about that. I will google it and find out. Thank you for mentioning it to me. But how will i declare a class which will have various sized instances? – IcyFlame Feb 25 '13 at 09:22
  • thank you so much sir. you have indeed solved my problem! @Johnsyweb – IcyFlame Feb 25 '13 at 09:26
  • 2
    you shouldn't just google it. Better pick up a good C++ book for beginners (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) – Philipp Feb 25 '13 at 09:27
  • That doesn't address the issue of how to write the values. – James Kanze Feb 25 '13 at 09:43
  • @Johnsyweb That's one solution. The real problem is that he doesn't define his problem well enough. Does the file he's creating have to be human readable? Easily? Your solution doesn't really support human readability of the date, but who knows if that's an issue or not. – James Kanze Feb 25 '13 at 12:28
  • @JamesKanze: Thanks for the feedback. By 'write this record as a class object into a binary ".dat" file', I understood it didn't have to be human-readable. – johnsyweb Feb 25 '13 at 21:50
  • @johnsyweb: you are right! I am writing a menu driven program. To read records and display them. And thanks for introducing me to the string concept(or I think it is a class but don't know am still reading up on it). It provides almost all the features there in the string library of python. Adding strings finding sub strings et al! – IcyFlame Feb 26 '13 at 07:29
  • Can we write these records using the file stream object fout and the fout.write(char *, int) function? – IcyFlame Feb 26 '13 at 07:38
  • @Johnsyweb If it doesn't have to be human readable, just outputting `time_t` as an integral type is a good solution. (It's still "sort of" human readable, for debugging purposes, but of course, just looking at the file won't tell you the time.) – James Kanze Feb 26 '13 at 09:11
  • @IcyFlame: `std::string` is missing some of Python's handiness, but you can use Boost for the stuff that's missing: http://www.boost.org/doc/libs/release/doc/html/string_algo.html – johnsyweb Feb 26 '13 at 09:39
  • @IcyFlame: If you write the `operator`s as I have demonstrated, `fout << my_user_data << std::endl` will work. – johnsyweb Feb 26 '13 at 09:40
1

If you are using c++ then std::string is best.

std::string abc="";
Arpit
  • 12,767
  • 3
  • 27
  • 40
1

What are the restrictions on the string? And how do you recognize that the user has entered all of the data he wants in the string?

If the string has to be a single line, and we can assume "reasonable" length (i.e. it will easily fit into memory), then you can use std::getline to get the string into an std::string (for input), and then define the output format, say "%Y-%m-%d %H:%M:%S: user string\n" for the file. If the user string can be several lines, you'll have to define a protocol to input them (so you can know when a single record is finished), and a more complex format for the file: one suggestion would be to separate records by an empty line (which means that the input cannot contain an empty line), or to use a record header along the lines of: "%Y-%m-%d %H:%M:%S line_count\n". (Subversion uses a variant of this for it's commit messages. With a bit more information, however, but the timestamp and the number of lines are there.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • Well will the get line function stop the input when it encounters a return key? By default? – IcyFlame Feb 26 '13 at 07:34
  • That's how it is for character arrays. – IcyFlame Feb 26 '13 at 07:35
  • And there is also an option in character arrays to give the delimiter by choice. cin.getline(arr,25,'.') would take the period '.' As the delimiter. Is the same thing allowed here? – IcyFlame Feb 26 '13 at 07:36
  • @IcyFlame The semantics of `std::getline` are to read until the terminator (by default `'\n'`); it extracts the terminator, but does not put it in the buffer. – James Kanze Feb 26 '13 at 09:13
  • Yes sir. I found that out. I would like you to look at the summary that i have written as an answer and please tell me if there are any mistakes or edits that need to be made. – IcyFlame Feb 26 '13 at 09:28