close

Privacy guaranteed - Your email is not shared with anyone.

Bit of help with C++ file I/O?

Discussion in 'Tech Talk' started by devildog2067, Dec 21, 2006.

  1. devildog2067

    devildog2067

    Joined:
    Apr 20, 2005
    Messages:
    16,466
    Likes Received:
    1,548
    Location:
    Chicago
    Hey all,

    I'm trying to figure out what is wrong with this code. They're two separate programs, one works fine and the other gives me an error.

    Notice that the parts highlighted in red are almost identical; the line in bold in the first block is the line that gives an error.

    void plotcorrection{
    <p> gROOT->Reset();
    TFile *hfile = new TFile("corrections.root","RECREATE");
    ifstream coll;
    coll.open("HB_wire_coll_corr.dat");
    double a,b,c,d,e,f;
    double corr_coll[4][17][16];
    if(!coll.is_open()){
    <p>cout << "ERROR: cannot open file" << endl;
    return;
    }

    for( int eta = 1; eta <17; eta++){
    <p> for( int layer = 0; layer < 17; layer++){
    <p> for( int phi = 1; phi < 5; phi++){
    <p> if(!coll.eof()){
    coll >> a >> b >> c >> d >> e >> f;
    corr_coll[phi-1][layer][eta-1] = d;
    }
    }
    }

    }


    while this code does not:

    void genfile(){
    <p> ifstream coll;
    coll.open("HB_wire_coll_corr.dat");
    double a,b,c,d,e,f,sum,error;
    double corr_coll[17][16];
    if(!coll.is_open()){
    <p> cout << "ERROR: cannot open file" << endl;
    return;
    }

    ofstream out;
    out.open("HB_wire_mean_RMS.dat");
    //for( int ndex = 1; ndex < 1088; ndex++){
    for( int eta = 1; eta <17; eta++){

    for( int layer = 0; layer < 17; layer++){
    sum = 0;
    error = 0;
    <p> for( int phi = 1; phi < 5; phi++){
    if(!coll.eof()){
    <p> coll >> a >> b >> c >> d >> e >> f;
    sum += d;
    error += e;
    }}

    corr_coll[layer][eta-1] = sum*.25;
    out << setw(2) << setfill('0') << eta << "\t";
    out << setw(2) << setfill('0') << layer << "\t";
    out << setw(9) << setfill('0') << corr_coll[layer][eta-1] << "\t";
    out << setw(9) << setfill('0') << e*.25 << "\n";
    }} }


    The error is "Error: improper lvalue FILE:genplots.C Line:17"

    Why does the part which reads the values into the array work fine in the second program but not in the almost identical first one? The error sounds like some sort of type mismatch thing but I don't understand it.

    I guess I don't really understand the >> operator and how it works with ifstream. I read all six values from each line of the file even though I only need 1, b/c that's the way that someone told me to do it once. If I only read the first four, will it skip to the next line the next time I loop over phi?

    The input file has about a thousand lines which are all structured like this:

    1 1 0 0.19033 0.00245 36

    I only need the fourth value to be stored in corr_coll.

    BTW, this is code for ROOT, which uses CINT.
     
  2. devildog2067

    devildog2067

    Joined:
    Apr 20, 2005
    Messages:
    16,466
    Likes Received:
    1,548
    Location:
    Chicago
    What the heck is the freaking tab tag? I tried [tab], [p],
    ...

    (I really do indent my code!)​
     

  3. JBlitzen

    JBlitzen .22 Hater

    Joined:
    Dec 18, 2005
    Messages:
    203
    Likes Received:
    0
    Location:
    Dallas, TX
    1. Try breaking it out into:

    coll >> a;
    coll >> b;
    coll >> c;
    coll >> d;
    coll >> e;
    coll >> f;

    to see if that slaps the parser back into normalcy.

    2. State your compiler/version/library/OS.

    3. Consider asking this in a programming forum, or in an IRC chatroom like Undernet's #C++. You can download mIRC as unlimited use shareware.
     
  4. tous

    tous GET A ROPE!

    Joined:
    Jan 7, 2001
    Messages:
    34,793
    Likes Received:
    38,615
    Location:
    Plano, Texas, Republic of
  5. ShawnG

    ShawnG

    Joined:
    Jun 7, 2000
    Messages:
    14
    Likes Received:
    0
    Location:
    Indiana
    Looks to me like what you have should work. I copied your code and modified it slightly, then created a data file for it to read in. I printed out the first read line so I would know I was properly reading the data. I compiled the code with gcc 3.1 and ran it, seemed to work fine. Here is the code I used and the output (of course, you have to #include iostream, fstream, and string):

    int main()
    {

    std::string filename("HB_wire_coll_corr.dat");
    std::ifstream coll(filename.c_str());
    double a,b,c,d,e,f;
    double corr_coll[4][17][16];
    bool dataPrinted = false;

    if (!coll.is_open())
    {
    std::cout << "ERROR: cannot open file\n";
    return -1;
    }

    for( int eta = 1; eta < 17; eta++)
    {

    for( int layer = 0; layer < 17; layer++)
    {

    for( int phi = 1; phi < 5; phi++)
    {

    if (!coll.eof())
    {

    coll >> a >> b >> c >> d >> e >> f;

    if (!dataPrinted)
    {
    std::cout << "A: " << a << "\n";
    std::cout << "B: " << b << "\n";
    std::cout << "C: " << c << "\n";
    std::cout << "D: " << d << "\n";
    std::cout << "E: " << e << "\n";
    std::cout << "F: " << f << "\n";
    dataPrinted = true;
    }

    corr_coll[phi-1][layer][eta-1] = d;

    }
    }
    }
    }

    std::cout << "Done\n";
    return 0;
    }

    output (this is a UNIX machine of course):

    $ /software/fsf/gcc-3.1/bin/g++ testRead.cpp -o testRead
    $ ./testRead
    A: 1
    B: 1
    C: 0
    D: 0.19033
    E: 0.00245
    F: 36
    Done

    Not sure what your problem is, what compiler are you using? Also, the code is more readable if you are consistent with your array indices in your loops. Since arrays all start at index 0, your loops should start at 0 as well, then you don't need to subtract one in your array assignments (like [phi - 1]). Also, you can skip ahead to the end of the line when you are reading in data, so you don't have to read all of the data if you don't need it.
     
  6. tous

    tous GET A ROPE!

    Joined:
    Jan 7, 2001
    Messages:
    34,793
    Likes Received:
    38,615
    Location:
    Plano, Texas, Republic of
    I ran the code in both GCC 4.1 and Visual C++ v7 and it works fine.

    I know of ROOT and CINT, but haven't had much to do with them. I suggest it may be a CINT interpreter 'feature.':upeyes:

    the lvalue (corr) would be invalid if it wasn't open.

    istreams don't really care about type, i.e., there is no numeric istream or character istream. The >> operator is overloaded to account for all possible types.

    Without a real compiler and an adult debugger it's hard to know where the error is.

    NB: lvalue is the object on the left side of an operator.

    Good luck, mi amigo. :wavey:
     
  7. freepatriot

    freepatriot Retired GT Mod Moderator

    Joined:
    Aug 8, 2002
    Messages:
    3,857
    Likes Received:
    29
    Location:
    South FL
  8. devildog2067

    devildog2067

    Joined:
    Apr 20, 2005
    Messages:
    16,466
    Likes Received:
    1,548
    Location:
    Chicago
    ROOT v4.02.00, which uses CINT, it's a C++ "style" command-line interpreter. It's what we use at CERN for data analysis.

    http://root.cern.ch

    Usually it's pretty close to ISO C++ but sometimes it kicks some strangeness in.

    The indices corespond to the physical way that the channels are laid out. Etas are numbered starting from 1 but layers are numbered starting from zero.

    I guess I don't understand. How do I skip ahead? If I can do:

    coll >> a;
    coll >> b;
    coll >> c;
    coll >> d;
    coll >> e;
    coll >> f;

    as another poster suggested, how do I tell the interpreter to skip to the next line?

    I posted for help on the ROOT user forums as well but there's quite a bit less traffic there than over here at this time of year (it's a lot of Swiss and French people, and they pretty much take all of December off). Thanks for the suggestion on IRC though, I'm heading there now.
     
  9. David_G17

    David_G17 /\/\/\/\/\/\/\/

    Joined:
    Oct 7, 2002
    Messages:
    2,046
    Likes Received:
    0
    for your viewing pleasure ;)

     
  10. David_G17

    David_G17 /\/\/\/\/\/\/\/

    Joined:
    Oct 7, 2002
    Messages:
    2,046
    Likes Received:
    0
    just to see his code. oh, and Shawn makes some good points - start your for loops with zero instead of 1; it's really common (esp. when indexing arrays).

     
  11. ShawnG

    ShawnG

    Joined:
    Jun 7, 2000
    Messages:
    14
    Likes Received:
    0
    Location:
    Indiana
    My best guess is that it is an issue with ROOT, not a problem with your actual C++ code. Unfortunately, I know nothing about ROOT so I can't be of much help there, sorry.
     
  12. David_G17

    David_G17 /\/\/\/\/\/\/\/

    Joined:
    Oct 7, 2002
    Messages:
    2,046
    Likes Received:
    0
    is there some way you can make your compiler produce more verbose output?

    maybe it could give you some more specific details of the problem it's seeing.
     
  13. JBlitzen

    JBlitzen .22 Hater

    Joined:
    Dec 18, 2005
    Messages:
    203
    Likes Received:
    0
    Location:
    Dallas, TX
    Google verified that this is the solution. ROOT gets mixed up by complex statements. It will behave the same as intended by the original line.