Problem: writing to a file with C and reading with C++

Discussion in 'C++' started by Keith Dewell, Sep 24, 2003.

  1. Keith Dewell

    Keith Dewell Guest

    Greetings!

    My current job has brought me back to working in C++ which I haven't
    used since school days. The solution to my problem may be trivial but
    I have struggled with it for the last two days and would appreciate
    this group's helpful expertise.

    My problem may be related to mixing the C and C++ languages together.
    Namely, I have a struct which I cannot change (as legacy code)
    similiar to this (I will change the names throughout as I am working
    on a government project):

    typedef struct {
    char firstMember[16];
    char secondMember[16];
    char thirdMember[96];
    unsigned long count;
    } my_Struct_T;

    Instances of this struct are written to a file using fprintf like
    this:

    if (file_p) fprintf(file_p, MY_MACRO_FORMAT);

    where MY_MACRO_FORMAT is defined like this:

    #define MY_MACRO_FORMAT \
    "%-12.12s\t%-8.8s\t%6d\t%-56.56s\t", \
    aStruct.firstMember,aStruct.secondMember,aStruct.count,Struct.thirdMember

    (aStruct being an instance of my_Struct_T)

    The user selects the written file using a dialog box from the GUI in
    order to read-in this data. To do this I use C++ code as follows:

    std::vector<std::string> dataFromFile;
    std::string aString;

    //actually passed-in from another method
    std::ifstream inputFileStream(&filename[0], std::ios::in);

    while(std::getline(inputFileStream[0], aString, '\t'))
    dataFromFile.push_back(aString);

    Now the problem ...

    Stepping through the code in the debugger as values are written to the
    vector, I see that the values for aStruct.thirdMember are always
    garbage unless it contains 15 or less characters.

    BTW, the values always look good in the file to which I have written,
    regardless of the number of characters for thirdMember. (I confirm
    this with a text editor.)

    Please offer a solution where I can still take a C++ approach (instead
    of C) as that is my preference, while not changing the legacy code
    (namely, the struct above).

    Much Thanks,
    Keith
     
    Keith Dewell, Sep 24, 2003
    #1
    1. Advertising

  2. Keith Dewell wrote:

    > Greetings!
    >
    > My current job has brought me back to working in C++ which I haven't
    > used since school days. The solution to my problem may be trivial but
    > I have struggled with it for the last two days and would appreciate
    > this group's helpful expertise.
    >
    > My problem may be related to mixing the C and C++ languages together.
    > Namely, I have a struct which I cannot change (as legacy code)
    > similiar to this (I will change the names throughout as I am working
    > on a government project):
    >
    > typedef struct {
    > char firstMember[16];
    > char secondMember[16];
    > char thirdMember[96];
    > unsigned long count;
    > } my_Struct_T;
    >
    > Instances of this struct are written to a file using fprintf like
    > this:
    >
    > if (file_p) fprintf(file_p, MY_MACRO_FORMAT);
    >
    > where MY_MACRO_FORMAT is defined like this:
    >
    > #define MY_MACRO_FORMAT \
    > "%-12.12s\t%-8.8s\t%6d\t%-56.56s\t", \
    > aStruct.firstMember,aStruct.secondMember,aStruct.count,Struct.thirdMember
    >
    > (aStruct being an instance of my_Struct_T)
    >
    > The user selects the written file using a dialog box from the GUI in
    > order to read-in this data. To do this I use C++ code as follows:
    >
    > std::vector<std::string> dataFromFile;
    > std::string aString;
    >
    > //actually passed-in from another method
    > std::ifstream inputFileStream(&filename[0], std::ios::in);


    What is 'filename'? If it's a std::string, this is very bad (use
    filename.c_str() instead). If it's a char* or char[] this is
    unnecessary. The only case I can think of where you'd want to do this is
    if filename just happened to be a null-terminated vector<char>, which is
    unusual.

    >
    > while(std::getline(inputFileStream[0], aString, '\t'))
    > dataFromFile.push_back(aString);


    It's hard to say what this will do without knowing something about the
    format of the file. Those char[] members you wrote to the file, might
    they have tab characters in them?

    >
    > Now the problem ...
    >
    > Stepping through the code in the debugger as values are written to the
    > vector, I see that the values for aStruct.thirdMember are always
    > garbage unless it contains 15 or less characters.
    >
    > BTW, the values always look good in the file to which I have written,
    > regardless of the number of characters for thirdMember. (I confirm
    > this with a text editor.)
    >
    > Please offer a solution where I can still take a C++ approach (instead
    > of C) as that is my preference, while not changing the legacy code
    > (namely, the struct above).


    Your problem does not appear to have anything to do with "mixing C and
    C++." There is nothing obviously wrong here (other than the
    '&filename[0]' thing). Try posting a complete, minimal program that
    demonstrates the problem, as well as some input to test it with.

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
     
    Kevin Goodsell, Sep 24, 2003
    #2
    1. Advertising

  3. Keith Dewell escribió:

    > Stepping through the code in the debugger as values are written to the
    > vector, I see that the values for aStruct.thirdMember are always
    > garbage unless it contains 15 or less characters.
    > BTW, the values always look good in the file to which I have written,
    > regardless of the number of characters for thirdMember. (I confirm
    > this with a text editor.)


    If I understand you correctly the program works fine, the problem is how
    to see correctly a non zero terminated array of char in the debugger. To
    get help about that, post in a group about your development tools.

    Regards.
     
    =?iso-8859-1?Q?Juli=E1n?= Albo, Sep 24, 2003
    #3
  4. Keith Dewell

    Keith Dewell Guest

    Julián Albo <> wrote in message news:<>...
    > Keith Dewell escribi? :




    >
    > > Stepping through the code in the debugger as values are written to the
    > > vector, I see that the values for aStruct.thirdMember are always
    > > garbage unless it contains 15 or less characters.
    > > BTW, the values always look good in the file to which I have written,
    > > regardless of the number of characters for thirdMember. (I confirm
    > > this with a text editor.)

    >
    > If I understand you correctly the program works fine, the problem is how
    > to see correctly a non zero terminated array of char in the debugger. To
    > get help about that, post in a group about your development tools.
    >
    > Regards.


    Thanks for responding. I am using MS Visual Studio 7.0 (a.k.a. MS
    Visual C++ .NET) and watch the vector become populated by using:

    dataFromFile._Myfirst, 10

    in the watch window of the debugger.

    The other members of the struct show good data in the debugger, only
    thirdMember shows garbage. This is why I believe this is an I/O
    problem since the data looks good in the file I am reading and this is
    the only variable where I see garbage; all the other members of the
    struct show good data in the debugger as they come into the vector.

    Regards,
    Keith
     
    Keith Dewell, Sep 25, 2003
    #4
  5. Keith Dewell escribió:

    > The other members of the struct show good data in the debugger, only
    > thirdMember shows garbage. This is why I believe this is an I/O
    > problem since the data looks good in the file I am reading and this is
    > the only variable where I see garbage; all the other members of the
    > struct show good data in the debugger as they come into the vector.


    Forget the debugger for one moment, and check the chars indvidually in
    the program, then you will know if it is a problem with the debugger or
    not.

    If it is a program with the debugger ask in a windows programming group,
    debuggers and compiler specific things are off-topic here.

    Regards.
     
    =?iso-8859-1?Q?Juli=E1n?= Albo, Sep 25, 2003
    #5
  6. Keith Dewell

    Keith Dewell Guest

    Kevin Goodsell <> wrote in message news:<C2lcb.1843$>...
    > Keith Dewell wrote:
    >
    > > Greetings!
    > >
    > > My current job has brought me back to working in C++ which I haven't
    > > used since school days. The solution to my problem may be trivial but
    > > I have struggled with it for the last two days and would appreciate
    > > this group's helpful expertise.
    > >
    > > My problem may be related to mixing the C and C++ languages together.
    > > Namely, I have a struct which I cannot change (as legacy code)
    > > similiar to this (I will change the names throughout as I am working
    > > on a government project):
    > >
    > > typedef struct {
    > > char firstMember[16];
    > > char secondMember[16];
    > > char thirdMember[96];
    > > unsigned long count;
    > > } my_Struct_T;
    > >
    > > Instances of this struct are written to a file using fprintf like
    > > this:
    > >
    > > if (file_p) fprintf(file_p, MY_MACRO_FORMAT);
    > >
    > > where MY_MACRO_FORMAT is defined like this:
    > >
    > > #define MY_MACRO_FORMAT \
    > > "%-12.12s\t%-8.8s\t%6d\t%-56.56s\t", \
    > > aStruct.firstMember,aStruct.secondMember,aStruct.count,Struct.thirdMember
    > >
    > > (aStruct being an instance of my_Struct_T)
    > >
    > > The user selects the written file using a dialog box from the GUI in
    > > order to read-in this data. To do this I use C++ code as follows:
    > >
    > > std::vector<std::string> dataFromFile;
    > > std::string aString;
    > >
    > > //actually passed-in from another method
    > > std::ifstream inputFileStream(&filename[0], std::ios::in);

    >
    > What is 'filename'? If it's a std::string, this is very bad (use
    > filename.c_str() instead). If it's a char* or char[] this is
    > unnecessary. The only case I can think of where you'd want to do this is
    > if filename just happened to be a null-terminated vector<char>, which is
    > unusual.
    >

    'filename' is an instance of FXString from the FOX Toolkit
    (http://www.fox-toolkit.org/); in our shop we use FOX instead of MFC
    or whatever for GUI development. We use a dialog box for the user to
    give the filename and this code uses FOX. I agree that '&filename[0]'
    is ugly, but it is the only way I have found, so far, that works.
    FXString does not understand c_str(). Anyway, this doesn't pertain to
    my problem since this code successfully attaches the stream to the
    file. But thanks for your input!
    > >
    > > while(std::getline(inputFileStream[0], aString, '\t'))
    > > dataFromFile.push_back(aString);

    >
    > It's hard to say what this will do without knowing something about the
    > format of the file. Those char[] members you wrote to the file, might
    > they have tab characters in them?
    >

    The values which the char[] members hold onto are just words like,
    "The quick brown fox jumped over the lazy dog" -- or whatever words
    may be found in a government project. :) The only whitespace
    permissable is a blank. Between the struct members I insert a tab
    delimiter for later parsing (see MY_MACRO_FORMAT above).
    > >
    > > Now the problem ...
    > >
    > > Stepping through the code in the debugger as values are written to the
    > > vector, I see that the values for aStruct.thirdMember are always
    > > garbage unless it contains 15 or less characters.
    > >
    > > BTW, the values always look good in the file to which I have written,
    > > regardless of the number of characters for thirdMember. (I confirm
    > > this with a text editor.)
    > >
    > > Please offer a solution where I can still take a C++ approach (instead
    > > of C) as that is my preference, while not changing the legacy code
    > > (namely, the struct above).

    >
    > Your problem does not appear to have anything to do with "mixing C and
    > C++."
    >

    The reason I thought it may have to do with the mixing of languages is
    that I write to the file with C and read the file with C++ where:

    1)The only problem-child is the thirdMember, the first and second
    members never take in garbage values and the only difference is the
    size of the arrays in their definition, i.e., char firstMember[16] and
    char secondMember[16] versus char thirdMember[96]. AND ...

    2)The problem seems to have something to do with the "magical"
    number 16, because if the thirdMember has < 16 characters then it
    takes no garbage from the stream and the values look good.

    > There is nothing obviously wrong here (other than the
    > '&filename[0]' thing). Try posting a complete, minimal program that
    > demonstrates the problem, as well as some input to test it with.
    >
    > -Kevin


    I started rewriting a minimal program but found it more involved than
    expected; partly because of the presence of FOX, partly because I need
    to change names and data for security reasons, and partly because of
    the overarching functionality which crosses over a few different
    classes. I haven't given-up on this yet and it may be a good approach
    for troubleshooting anyway. But I thought I should go ahead and
    respond to your post with the hope of presenting my problem more
    clearly.

    Thanks for all of your help,
    Keith
     
    Keith Dewell, Sep 26, 2003
    #6
  7. Keith Dewell wrote:

    > I started rewriting a minimal program but found it more involved than
    > expected;


    Well, I did write a minimal program based on what you posted:

    #include <stdio.h>
    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <string>

    using namespace std;

    typedef struct {
    char firstMember[16];
    char secondMember[16];
    char thirdMember[96];
    unsigned long count;
    } my_Struct_T;


    #define MY_MACRO_FORMAT \
    "%-12.12s\t%-8.8s\t%6d\t%-56.56s\t", \
    aStruct.firstMember,aStruct.secondMember,aStruct.count,aStruct.thirdMember


    int main()
    {
    FILE *fp = fopen("test.txt", "w");
    if (fp == 0)
    {
    cerr << "could not open test.txt" << endl;
    return 0;
    }

    my_Struct_T aStruct = {"first", "second",
    "third is very very very very loooooonnnnnng", 24};
    if (fp) fprintf(fp, MY_MACRO_FORMAT);

    fclose(fp);

    ifstream inputFileStream("test.txt");

    std::vector<std::string> dataFromFile;
    std::string aString;

    while(std::getline(inputFileStream, aString, '\t'))
    dataFromFile.push_back(aString);

    return 0;
    }


    This works exactly as expected. I also noticed a few more errors in your
    code while making this:

    #define MY_MACRO_FORMAT \
    "%-12.12s\t%-8.8s\t%6d\t%-56.56s\t", \
    aStruct.firstMember,aStruct.secondMember,aStruct.count,Struct.thirdMember
    ^^^^^^

    'Struct.thirdMember' should presumably be 'aStruct.thirdMember'.

    And here:

    std::ifstream inputFileStream(&filename[0], std::ios::in);

    while(std::getline(inputFileStream[0], aString, '\t'))
    dataFromFile.push_back(aString);

    'inputFileStream[0]' should presumably NOT have the '[0]'.

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
     
    Kevin Goodsell, Sep 26, 2003
    #7
  8. Keith Dewell

    Keith Dewell Guest

    Julián Albo <> wrote in message news:<>...
    > Keith Dewell escribi :
    >
    > > The other members of the struct show good data in the debugger, only
    > > thirdMember shows garbage. This is why I believe this is an I/O
    > > problem since the data looks good in the file I am reading and this is
    > > the only variable where I see garbage; all the other members of the
    > > struct show good data in the debugger as they come into the vector.

    >
    > Forget the debugger for one moment, and check the chars indvidually in
    > the program, then you will know if it is a problem with the debugger or
    > not.
    >
    > If it is a program with the debugger ask in a windows programming group,
    > debuggers and compiler specific things are off-topic here.
    >
    > Regards.


    Julián,

    You were right(!), the problem was related to the debugger and also to
    std::string. Here is a quote from Thore B. Karlsen on another thread
    dated 2003-01-03 07:24:05 PST:

    "The string class in VC++ 7.0 has a short string optimization for
    strings of 16 characters or less. Anything with this length is stored
    in a small buffer in the string object. For longer strings, memory is
    allocated. What you're seeing is probably just the internal buffer."

    Hence the "magic" number 16 I was encountering. BTW, Mr. Karlsen has
    provided this solution for at least 3 different posters. And though
    debuggers are off-topic I thought I should post this here just so
    everyone can see the resolution to my problem.

    Thanks Julián (and Kevin) for your help!

    Regards,
    Keith
     
    Keith Dewell, Oct 1, 2003
    #8
    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. David Hearn
    Replies:
    1
    Views:
    320
    avnrao
    Jun 30, 2004
  2. HNguyen
    Replies:
    4
    Views:
    2,408
    HNguyen
    Dec 21, 2004
  3. Giulio
    Replies:
    0
    Views:
    378
    Giulio
    Sep 22, 2003
  4. Replies:
    7
    Views:
    525
  5. utab
    Replies:
    7
    Views:
    3,379
    Dietmar Kuehl
    Mar 14, 2006
Loading...

Share This Page