reading / writing a string

Discussion in 'C++' started by Per, Dec 3, 2008.

  1. Per

    Per Guest

    On 2008-12-03, hamishd <> wrote:
    > Hi, I have a structure like this:
    >
    > #define MAX_LENGTH 20
    >
    > struct InformationClass
    > {
    > char StringA[MAX_LENGTH];
    > char StringB[MAX_LENGTH];
    > };
    >
    > I want to be able to write it to a file, and also read it back in
    > again? I am using fprintf, and fscanf.
    >
    > Write like this:
    > fprintf(stream, "%s%s", IC.StringA, IC.StringB);
    >
    > Read like this:
    > fscanf(stream, "%s%s", &IC.StringA, &IC.StringB);
    >
    > It doesn't seem to work. Is there an easy way to do this?
    >


    To me this looks like C-code. In C++ I would have overloaded the <<
    and >> operators for istream and ostream respectively. If its just
    serialization you are after there is also the boost serialization library.

    Further in C++ use std::string instead of char[].

    /Per
    Per, Dec 3, 2008
    #1
    1. Advertising

  2. Per

    hamishd Guest

    Hi, I have a structure like this:

    #define MAX_LENGTH 20

    struct InformationClass
    {
    char StringA[MAX_LENGTH];
    char StringB[MAX_LENGTH];
    };

    I want to be able to write it to a file, and also read it back in
    again? I am using fprintf, and fscanf.

    Write like this:
    fprintf(stream, "%s%s", IC.StringA, IC.StringB);

    Read like this:
    fscanf(stream, "%s%s", &IC.StringA, &IC.StringB);

    It doesn't seem to work. Is there an easy way to do this?
    hamishd, Dec 3, 2008
    #2
    1. Advertising

  3. Per

    Fred Guest

    On Dec 3, 7:54 am, Jeff Schwab <> wrote:
    > hamishd wrote:
    > > Hi, I have a structure like this:

    >
    > > #define MAX_LENGTH 20

    >
    > > struct InformationClass
    > > {
    > >    char StringA[MAX_LENGTH];
    > >    char StringB[MAX_LENGTH];
    > > };

    >
    > > I want to be able to write it to a file, and also read it back in
    > > again? I am using fprintf, and fscanf.

    >
    > > Write like this:
    > > fprintf(stream, "%s%s", IC.StringA, IC.StringB);

    >
    > Here, you write the strings back-to-back, without any intervening
    > whitespace.  When you try to read the strings back into your program,
    > the whole sequence will be mistaken for one string.  You could try
    > inserting a space, so that the format string is "%s %s".
    >
    > > Read like this:
    > > fscanf(stream, "%s%s", &IC.StringA, &IC.StringB);

    >
    > > It doesn't seem to work. Is there an easy way to do this?

    >
    > The "easy" way is to use the C++ standard library's stream and string
    > types, and to follow some basic conventions with regard to operator
    > overloading.  This may seem cryptic to you at first, but it is worth
    > taking the time to understand; the effort pays off quickly.
    >
    > #include <fstream>
    > #include <iostream>
    > #include <string>
    >
    > struct information {
    >      std::string string_a;
    >      std::string string_b;
    >
    > };
    >
    > std::eek:stream& operator<<(
    >          std::eek:stream& stream,
    >          information const& info) {
    >      return stream << info.string_a << ' ' << info.string_b;
    >
    > }
    >
    > std::istream& operator>>(
    >          std::istream& stream,
    >          information& info) {
    >      return stream >> info.string_a >> info.string_b;
    >
    > }
    >
    > void write_file(char const* name, information const& info) {
    >      std::eek:fstream stream( name );
    >      stream << info;
    >
    > }
    >
    > information read_file(char const* name) {
    >      std::ifstream stream( name );
    >      information info;
    >      stream >> info;
    >      return info;
    >
    > }
    >
    > int main() {
    >      information const info = { "hello", "world" };
    >      char const file_name[] = "some_file";
    >      write_file(file_name, info);
    >      std::cout << read_file(file_name) << '\n';
    >      return 0;
    >
    >
    >
    > }- Hide quoted text -
    >
    > - Show quoted text -- Hide quoted text -
    >
    > - Show quoted text -


    This still will not work if either of the strings contains embedded
    whitespace.
    --
    Fred K
    Fred, Dec 3, 2008
    #3
  4. Per

    KK Guest

    On Dec 3, 11:14 am, Fred <> wrote:
    > On Dec 3, 7:54 am, Jeff Schwab <> wrote:
    >
    >
    >
    > > hamishd wrote:
    > > > Hi, I have a structure like this:

    >
    > > > #define MAX_LENGTH 20

    >
    > > > struct InformationClass
    > > > {
    > > >    char StringA[MAX_LENGTH];
    > > >    char StringB[MAX_LENGTH];
    > > > };

    >
    > > > I want to be able to write it to a file, and also read it back in
    > > > again? I am using fprintf, and fscanf.

    >
    > > > Write like this:
    > > > fprintf(stream, "%s%s", IC.StringA, IC.StringB);

    >
    > > Here, you write the strings back-to-back, without any intervening
    > > whitespace.  When you try to read the strings back into your program,
    > > the whole sequence will be mistaken for one string.  You could try
    > > inserting a space, so that the format string is "%s %s".

    >
    > > > Read like this:
    > > > fscanf(stream, "%s%s", &IC.StringA, &IC.StringB);

    >
    > > > It doesn't seem to work. Is there an easy way to do this?

    >
    > > The "easy" way is to use the C++ standard library's stream and string
    > > types, and to follow some basic conventions with regard to operator
    > > overloading.  This may seem cryptic to you at first, but it is worth
    > > taking the time to understand; the effort pays off quickly.

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

    >
    > > struct information {
    > >      std::string string_a;
    > >      std::string string_b;

    >
    > > };

    >
    > > std::eek:stream& operator<<(
    > >          std::eek:stream& stream,
    > >          information const& info) {
    > >      return stream << info.string_a << ' ' << info.string_b;

    >
    > > }

    >
    > > std::istream& operator>>(
    > >          std::istream& stream,
    > >          information& info) {
    > >      return stream >> info.string_a >> info.string_b;

    >
    > > }

    >
    > > void write_file(char const* name, information const& info) {
    > >      std::eek:fstream stream( name );
    > >      stream << info;

    >
    > > }

    >
    > > information read_file(char const* name) {
    > >      std::ifstream stream( name );
    > >      information info;
    > >      stream >> info;
    > >      return info;

    >
    > > }

    >
    > > int main() {
    > >      information const info = { "hello", "world" };
    > >      char const file_name[] = "some_file";
    > >      write_file(file_name, info);
    > >      std::cout << read_file(file_name) << '\n';
    > >      return 0;

    >
    > > }- Hide quoted text -

    >
    > > - Show quoted text -- Hide quoted text -

    >
    > > - Show quoted text -

    >
    > This still will not work if either of the strings contains embedded
    > whitespace.
    > --
    > Fred K


    check getline() where you can specify a delimiter. You could use '\n'
    as delimiter while writing a strings in different lines
    KK, Dec 3, 2008
    #4
  5. Per

    James Kanze Guest

    On Dec 3, 8:44 pm, Jeff Schwab <> wrote:
    > Fred wrote:
    > > On Dec 3, 7:54 am, Jeff Schwab <> wrote:
    > >>> fprintf(stream, "%s%s", IC.StringA, IC.StringB);
    > >> Here, you write the strings back-to-back, without any
    > >> intervening whitespace.  When you try to read the strings
    > >> back into your program, the whole sequence will be mistaken
    > >> for one string.  You could try inserting a space, so that
    > >> the format string is "%s %s".

    > > This still will not work if either of the strings contains
    > > embedded whitespace.


    > Good point.  That did not occur to me.


    It's a general problem when serializing in text format.
    Choosing a separator for most types is fairly trivial, however;
    there are lots of characters which can't show up in the string
    representation an int or a double. (But it still requires some
    thought---the C++ standard for formatting a complex regretfully
    uses a separator which can occur in a double, which means that a
    standard conforming implementation is totally useless.) For
    strings in general, it's a bit more complicated. Most strings,
    however, have a semantic, e.g. family name, or something like
    that, which will forbid some characters, and thus allow a
    separator; if not, I've written a ParsableString class which
    ensures round trip serialization, roughly by using the
    conventions for C++ string literals: in quotes, with quotes and
    unprintable characters escaped.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Dec 3, 2008
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. HNguyen
    Replies:
    4
    Views:
    2,386
    HNguyen
    Dec 21, 2004
  2. happy

    read a string..writing a string

    happy, Feb 11, 2005, in forum: C Programming
    Replies:
    3
    Views:
    339
    Thomas Matthews
    Feb 12, 2005
  3. Replies:
    5
    Views:
    298
    Nick Keighley
    Dec 7, 2007
  4. Leslaw Bieniasz
    Replies:
    2
    Views:
    1,019
    Thomas J. Gritzan
    Jan 15, 2010
  5. Greg Hurrell
    Replies:
    1
    Views:
    221
    Greg Hurrell
    Feb 26, 2007
Loading...

Share This Page