Behaviour of fstream in C++










-2















I have made the following script, that is supposed to read from a file:



 char match = "match";

int a;
int b;

inp >> lin;
while(!inp.eof())
if(!strcmp(lin, match))
inp >> a >> b;
cout << a << " " << b <<endl;

inp >> lin;


inp.close();
return num_atm;
}


It is supposed to read all words, and if a line starts with match, it should then also print the rest of the line.



My input file is this:



match 1 2 //1
match 5 2 //2
nope 3 6 //3
match 5 //4
match 1 4 //5
match 5 9 //6


It will correctly print 1 2, 5 2, and skip 3 6. But then, it will get stuck and keep printing 5 0 and continue printing 5 0 for ever. I get that match is put into b, which is an integer, but I don't get why this is looped. Shouldn't the input read match 4 once, try to read/write 5 and match, and then be done with line 4 and the match from line 5? Then it should next read the number 1 and 4 and then match from number 6.



I would also understand that due to the word not fitting into the integer, it would read match in the fifth line again, but that's not what it does.



It goes back to the match in the fourth line which it already read, and reads it again. Why is this?










share|improve this question






















  • eof within loop: Have a look at here (more important aspect: you do not catch fail in given case).

    – Aconcagua
    Nov 13 '18 at 19:11












  • Stepping through the code with a debugger should solve this for you in short order.

    – user4581301
    Nov 13 '18 at 19:11












  • Simplify your life and use std::string and std::getline.

    – Thomas Matthews
    Nov 13 '18 at 19:15











  • @Aconcagua I see! I know how to fix it, but I don't understand why data gets re-read when fail is set to true.

    – PenguinHook
    Nov 13 '18 at 19:19











  • lin is not defined

    – M.M
    Nov 14 '18 at 0:16















-2















I have made the following script, that is supposed to read from a file:



 char match = "match";

int a;
int b;

inp >> lin;
while(!inp.eof())
if(!strcmp(lin, match))
inp >> a >> b;
cout << a << " " << b <<endl;

inp >> lin;


inp.close();
return num_atm;
}


It is supposed to read all words, and if a line starts with match, it should then also print the rest of the line.



My input file is this:



match 1 2 //1
match 5 2 //2
nope 3 6 //3
match 5 //4
match 1 4 //5
match 5 9 //6


It will correctly print 1 2, 5 2, and skip 3 6. But then, it will get stuck and keep printing 5 0 and continue printing 5 0 for ever. I get that match is put into b, which is an integer, but I don't get why this is looped. Shouldn't the input read match 4 once, try to read/write 5 and match, and then be done with line 4 and the match from line 5? Then it should next read the number 1 and 4 and then match from number 6.



I would also understand that due to the word not fitting into the integer, it would read match in the fifth line again, but that's not what it does.



It goes back to the match in the fourth line which it already read, and reads it again. Why is this?










share|improve this question






















  • eof within loop: Have a look at here (more important aspect: you do not catch fail in given case).

    – Aconcagua
    Nov 13 '18 at 19:11












  • Stepping through the code with a debugger should solve this for you in short order.

    – user4581301
    Nov 13 '18 at 19:11












  • Simplify your life and use std::string and std::getline.

    – Thomas Matthews
    Nov 13 '18 at 19:15











  • @Aconcagua I see! I know how to fix it, but I don't understand why data gets re-read when fail is set to true.

    – PenguinHook
    Nov 13 '18 at 19:19











  • lin is not defined

    – M.M
    Nov 14 '18 at 0:16













-2












-2








-2








I have made the following script, that is supposed to read from a file:



 char match = "match";

int a;
int b;

inp >> lin;
while(!inp.eof())
if(!strcmp(lin, match))
inp >> a >> b;
cout << a << " " << b <<endl;

inp >> lin;


inp.close();
return num_atm;
}


It is supposed to read all words, and if a line starts with match, it should then also print the rest of the line.



My input file is this:



match 1 2 //1
match 5 2 //2
nope 3 6 //3
match 5 //4
match 1 4 //5
match 5 9 //6


It will correctly print 1 2, 5 2, and skip 3 6. But then, it will get stuck and keep printing 5 0 and continue printing 5 0 for ever. I get that match is put into b, which is an integer, but I don't get why this is looped. Shouldn't the input read match 4 once, try to read/write 5 and match, and then be done with line 4 and the match from line 5? Then it should next read the number 1 and 4 and then match from number 6.



I would also understand that due to the word not fitting into the integer, it would read match in the fifth line again, but that's not what it does.



It goes back to the match in the fourth line which it already read, and reads it again. Why is this?










share|improve this question














I have made the following script, that is supposed to read from a file:



 char match = "match";

int a;
int b;

inp >> lin;
while(!inp.eof())
if(!strcmp(lin, match))
inp >> a >> b;
cout << a << " " << b <<endl;

inp >> lin;


inp.close();
return num_atm;
}


It is supposed to read all words, and if a line starts with match, it should then also print the rest of the line.



My input file is this:



match 1 2 //1
match 5 2 //2
nope 3 6 //3
match 5 //4
match 1 4 //5
match 5 9 //6


It will correctly print 1 2, 5 2, and skip 3 6. But then, it will get stuck and keep printing 5 0 and continue printing 5 0 for ever. I get that match is put into b, which is an integer, but I don't get why this is looped. Shouldn't the input read match 4 once, try to read/write 5 and match, and then be done with line 4 and the match from line 5? Then it should next read the number 1 and 4 and then match from number 6.



I would also understand that due to the word not fitting into the integer, it would read match in the fifth line again, but that's not what it does.



It goes back to the match in the fourth line which it already read, and reads it again. Why is this?







c++ fstream






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 13 '18 at 19:08









PenguinHookPenguinHook

1




1












  • eof within loop: Have a look at here (more important aspect: you do not catch fail in given case).

    – Aconcagua
    Nov 13 '18 at 19:11












  • Stepping through the code with a debugger should solve this for you in short order.

    – user4581301
    Nov 13 '18 at 19:11












  • Simplify your life and use std::string and std::getline.

    – Thomas Matthews
    Nov 13 '18 at 19:15











  • @Aconcagua I see! I know how to fix it, but I don't understand why data gets re-read when fail is set to true.

    – PenguinHook
    Nov 13 '18 at 19:19











  • lin is not defined

    – M.M
    Nov 14 '18 at 0:16

















  • eof within loop: Have a look at here (more important aspect: you do not catch fail in given case).

    – Aconcagua
    Nov 13 '18 at 19:11












  • Stepping through the code with a debugger should solve this for you in short order.

    – user4581301
    Nov 13 '18 at 19:11












  • Simplify your life and use std::string and std::getline.

    – Thomas Matthews
    Nov 13 '18 at 19:15











  • @Aconcagua I see! I know how to fix it, but I don't understand why data gets re-read when fail is set to true.

    – PenguinHook
    Nov 13 '18 at 19:19











  • lin is not defined

    – M.M
    Nov 14 '18 at 0:16
















eof within loop: Have a look at here (more important aspect: you do not catch fail in given case).

– Aconcagua
Nov 13 '18 at 19:11






eof within loop: Have a look at here (more important aspect: you do not catch fail in given case).

– Aconcagua
Nov 13 '18 at 19:11














Stepping through the code with a debugger should solve this for you in short order.

– user4581301
Nov 13 '18 at 19:11






Stepping through the code with a debugger should solve this for you in short order.

– user4581301
Nov 13 '18 at 19:11














Simplify your life and use std::string and std::getline.

– Thomas Matthews
Nov 13 '18 at 19:15





Simplify your life and use std::string and std::getline.

– Thomas Matthews
Nov 13 '18 at 19:15













@Aconcagua I see! I know how to fix it, but I don't understand why data gets re-read when fail is set to true.

– PenguinHook
Nov 13 '18 at 19:19





@Aconcagua I see! I know how to fix it, but I don't understand why data gets re-read when fail is set to true.

– PenguinHook
Nov 13 '18 at 19:19













lin is not defined

– M.M
Nov 14 '18 at 0:16





lin is not defined

– M.M
Nov 14 '18 at 0:16












1 Answer
1






active

oldest

votes


















0














When you are reading with >> line enndings are handled the same as spaces: They are just more whitespace that is skipped. That means you see



match 1 2 
match 5 2
nope 3 6
match 5
match 1 4
match 5 9


But the program sees



match 1 2 match 5 2 nope 3 6 match 5 match 1 4 match 5 9 


Let's fast forward to where things go south



Contents of stream:



nope 3 6 match 5 match 1 4 match 5 9 


Processing



inp >> lin; // reads nope stream: 3 6 match 5 match 1 4 match 5 9 
if(!strcmp(lin, match)) // nope != match skip body

inp >> lin; // reads 3 stream: 6 match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // 3 != match skip body

inp >> lin; // reads 6 stream: match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // 6 != match skip body

inp >> lin; // reads match stream: 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // match != match Enter body
inp >> a >> b; // reads 5 and fails to parse match into an integer.
// stream: match 1 4 match 5 9
// stream now in failure state
cout << a << " " << b <<endl; // prints 5 and garbage because b was not read


inp >> lin; // reads nothing. Stream failed
if(!strcmp(lin, match)) // match != match Enter body
inp >> a >> b; // reads nothing. Stream failed
// stream: match 1 4 match 5 9
// stream now in failure state
cout << a << " " << b <<endl; // prints g and garbage because b was not read




Because nothing is ever read, while(!inp.eof()) is utterly worthless. The end of the file can never be reached. The program will loop forever, probably printing whatever it last read. Successfully read.



Fixing this depends entirely on what you want to do if you have a match line without 2 numbers on it, but a typical framework looks something like



std::string line;
while(std::getline(inp, line) // get a whole line. Exit if line can't be read for any reason.

std::istringstream strm(line);
std::string lin;
if(strm >> lin && lin == match) // enters if lin was read and lin == match
// if lin can't be read, it doesn't matter.
// strm is disposable

int a;
int b;

if (strm >> a >> b) // enters if both a and b were read

cout << a << " " << b <<"n"; // endl flushes. Very expensive. just use a newline.





Output from this should be something like



1 2 
5 2
1 4
5 9


If you want to make some use of match 5... Well it's up to you what you want to put in b if there is no b in the file.






share|improve this answer






















    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53287933%2fbehaviour-of-fstream-in-c%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    When you are reading with >> line enndings are handled the same as spaces: They are just more whitespace that is skipped. That means you see



    match 1 2 
    match 5 2
    nope 3 6
    match 5
    match 1 4
    match 5 9


    But the program sees



    match 1 2 match 5 2 nope 3 6 match 5 match 1 4 match 5 9 


    Let's fast forward to where things go south



    Contents of stream:



    nope 3 6 match 5 match 1 4 match 5 9 


    Processing



    inp >> lin; // reads nope stream: 3 6 match 5 match 1 4 match 5 9 
    if(!strcmp(lin, match)) // nope != match skip body

    inp >> lin; // reads 3 stream: 6 match 5 match 1 4 match 5 9
    if(!strcmp(lin, match)) // 3 != match skip body

    inp >> lin; // reads 6 stream: match 5 match 1 4 match 5 9
    if(!strcmp(lin, match)) // 6 != match skip body

    inp >> lin; // reads match stream: 5 match 1 4 match 5 9
    if(!strcmp(lin, match)) // match != match Enter body
    inp >> a >> b; // reads 5 and fails to parse match into an integer.
    // stream: match 1 4 match 5 9
    // stream now in failure state
    cout << a << " " << b <<endl; // prints 5 and garbage because b was not read


    inp >> lin; // reads nothing. Stream failed
    if(!strcmp(lin, match)) // match != match Enter body
    inp >> a >> b; // reads nothing. Stream failed
    // stream: match 1 4 match 5 9
    // stream now in failure state
    cout << a << " " << b <<endl; // prints g and garbage because b was not read




    Because nothing is ever read, while(!inp.eof()) is utterly worthless. The end of the file can never be reached. The program will loop forever, probably printing whatever it last read. Successfully read.



    Fixing this depends entirely on what you want to do if you have a match line without 2 numbers on it, but a typical framework looks something like



    std::string line;
    while(std::getline(inp, line) // get a whole line. Exit if line can't be read for any reason.

    std::istringstream strm(line);
    std::string lin;
    if(strm >> lin && lin == match) // enters if lin was read and lin == match
    // if lin can't be read, it doesn't matter.
    // strm is disposable

    int a;
    int b;

    if (strm >> a >> b) // enters if both a and b were read

    cout << a << " " << b <<"n"; // endl flushes. Very expensive. just use a newline.





    Output from this should be something like



    1 2 
    5 2
    1 4
    5 9


    If you want to make some use of match 5... Well it's up to you what you want to put in b if there is no b in the file.






    share|improve this answer



























      0














      When you are reading with >> line enndings are handled the same as spaces: They are just more whitespace that is skipped. That means you see



      match 1 2 
      match 5 2
      nope 3 6
      match 5
      match 1 4
      match 5 9


      But the program sees



      match 1 2 match 5 2 nope 3 6 match 5 match 1 4 match 5 9 


      Let's fast forward to where things go south



      Contents of stream:



      nope 3 6 match 5 match 1 4 match 5 9 


      Processing



      inp >> lin; // reads nope stream: 3 6 match 5 match 1 4 match 5 9 
      if(!strcmp(lin, match)) // nope != match skip body

      inp >> lin; // reads 3 stream: 6 match 5 match 1 4 match 5 9
      if(!strcmp(lin, match)) // 3 != match skip body

      inp >> lin; // reads 6 stream: match 5 match 1 4 match 5 9
      if(!strcmp(lin, match)) // 6 != match skip body

      inp >> lin; // reads match stream: 5 match 1 4 match 5 9
      if(!strcmp(lin, match)) // match != match Enter body
      inp >> a >> b; // reads 5 and fails to parse match into an integer.
      // stream: match 1 4 match 5 9
      // stream now in failure state
      cout << a << " " << b <<endl; // prints 5 and garbage because b was not read


      inp >> lin; // reads nothing. Stream failed
      if(!strcmp(lin, match)) // match != match Enter body
      inp >> a >> b; // reads nothing. Stream failed
      // stream: match 1 4 match 5 9
      // stream now in failure state
      cout << a << " " << b <<endl; // prints g and garbage because b was not read




      Because nothing is ever read, while(!inp.eof()) is utterly worthless. The end of the file can never be reached. The program will loop forever, probably printing whatever it last read. Successfully read.



      Fixing this depends entirely on what you want to do if you have a match line without 2 numbers on it, but a typical framework looks something like



      std::string line;
      while(std::getline(inp, line) // get a whole line. Exit if line can't be read for any reason.

      std::istringstream strm(line);
      std::string lin;
      if(strm >> lin && lin == match) // enters if lin was read and lin == match
      // if lin can't be read, it doesn't matter.
      // strm is disposable

      int a;
      int b;

      if (strm >> a >> b) // enters if both a and b were read

      cout << a << " " << b <<"n"; // endl flushes. Very expensive. just use a newline.





      Output from this should be something like



      1 2 
      5 2
      1 4
      5 9


      If you want to make some use of match 5... Well it's up to you what you want to put in b if there is no b in the file.






      share|improve this answer

























        0












        0








        0







        When you are reading with >> line enndings are handled the same as spaces: They are just more whitespace that is skipped. That means you see



        match 1 2 
        match 5 2
        nope 3 6
        match 5
        match 1 4
        match 5 9


        But the program sees



        match 1 2 match 5 2 nope 3 6 match 5 match 1 4 match 5 9 


        Let's fast forward to where things go south



        Contents of stream:



        nope 3 6 match 5 match 1 4 match 5 9 


        Processing



        inp >> lin; // reads nope stream: 3 6 match 5 match 1 4 match 5 9 
        if(!strcmp(lin, match)) // nope != match skip body

        inp >> lin; // reads 3 stream: 6 match 5 match 1 4 match 5 9
        if(!strcmp(lin, match)) // 3 != match skip body

        inp >> lin; // reads 6 stream: match 5 match 1 4 match 5 9
        if(!strcmp(lin, match)) // 6 != match skip body

        inp >> lin; // reads match stream: 5 match 1 4 match 5 9
        if(!strcmp(lin, match)) // match != match Enter body
        inp >> a >> b; // reads 5 and fails to parse match into an integer.
        // stream: match 1 4 match 5 9
        // stream now in failure state
        cout << a << " " << b <<endl; // prints 5 and garbage because b was not read


        inp >> lin; // reads nothing. Stream failed
        if(!strcmp(lin, match)) // match != match Enter body
        inp >> a >> b; // reads nothing. Stream failed
        // stream: match 1 4 match 5 9
        // stream now in failure state
        cout << a << " " << b <<endl; // prints g and garbage because b was not read




        Because nothing is ever read, while(!inp.eof()) is utterly worthless. The end of the file can never be reached. The program will loop forever, probably printing whatever it last read. Successfully read.



        Fixing this depends entirely on what you want to do if you have a match line without 2 numbers on it, but a typical framework looks something like



        std::string line;
        while(std::getline(inp, line) // get a whole line. Exit if line can't be read for any reason.

        std::istringstream strm(line);
        std::string lin;
        if(strm >> lin && lin == match) // enters if lin was read and lin == match
        // if lin can't be read, it doesn't matter.
        // strm is disposable

        int a;
        int b;

        if (strm >> a >> b) // enters if both a and b were read

        cout << a << " " << b <<"n"; // endl flushes. Very expensive. just use a newline.





        Output from this should be something like



        1 2 
        5 2
        1 4
        5 9


        If you want to make some use of match 5... Well it's up to you what you want to put in b if there is no b in the file.






        share|improve this answer













        When you are reading with >> line enndings are handled the same as spaces: They are just more whitespace that is skipped. That means you see



        match 1 2 
        match 5 2
        nope 3 6
        match 5
        match 1 4
        match 5 9


        But the program sees



        match 1 2 match 5 2 nope 3 6 match 5 match 1 4 match 5 9 


        Let's fast forward to where things go south



        Contents of stream:



        nope 3 6 match 5 match 1 4 match 5 9 


        Processing



        inp >> lin; // reads nope stream: 3 6 match 5 match 1 4 match 5 9 
        if(!strcmp(lin, match)) // nope != match skip body

        inp >> lin; // reads 3 stream: 6 match 5 match 1 4 match 5 9
        if(!strcmp(lin, match)) // 3 != match skip body

        inp >> lin; // reads 6 stream: match 5 match 1 4 match 5 9
        if(!strcmp(lin, match)) // 6 != match skip body

        inp >> lin; // reads match stream: 5 match 1 4 match 5 9
        if(!strcmp(lin, match)) // match != match Enter body
        inp >> a >> b; // reads 5 and fails to parse match into an integer.
        // stream: match 1 4 match 5 9
        // stream now in failure state
        cout << a << " " << b <<endl; // prints 5 and garbage because b was not read


        inp >> lin; // reads nothing. Stream failed
        if(!strcmp(lin, match)) // match != match Enter body
        inp >> a >> b; // reads nothing. Stream failed
        // stream: match 1 4 match 5 9
        // stream now in failure state
        cout << a << " " << b <<endl; // prints g and garbage because b was not read




        Because nothing is ever read, while(!inp.eof()) is utterly worthless. The end of the file can never be reached. The program will loop forever, probably printing whatever it last read. Successfully read.



        Fixing this depends entirely on what you want to do if you have a match line without 2 numbers on it, but a typical framework looks something like



        std::string line;
        while(std::getline(inp, line) // get a whole line. Exit if line can't be read for any reason.

        std::istringstream strm(line);
        std::string lin;
        if(strm >> lin && lin == match) // enters if lin was read and lin == match
        // if lin can't be read, it doesn't matter.
        // strm is disposable

        int a;
        int b;

        if (strm >> a >> b) // enters if both a and b were read

        cout << a << " " << b <<"n"; // endl flushes. Very expensive. just use a newline.





        Output from this should be something like



        1 2 
        5 2
        1 4
        5 9


        If you want to make some use of match 5... Well it's up to you what you want to put in b if there is no b in the file.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 13 '18 at 23:49









        user4581301user4581301

        19.8k51831




        19.8k51831



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53287933%2fbehaviour-of-fstream-in-c%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            這個網誌中的熱門文章

            What does pagestruct do in Eviews?

            Dutch intervention in Lombok and Karangasem

            Channel Islands