Thread: infinite loop

  1. #1
    Registered User
    Join Date
    Aug 2011
    Posts
    385

    infinite loop

    why does the following code gets stuck in an infinite loop in the second pass through the while loop?? I know its got something to do with the input buffer, cause it works when I use fflush(stdin) but I can't understand what's wrong. Also I need to know why std::cout.flush() does not seem to be working..

    Code:
    #include <iostream>
    #include <fstream>
    
    int main()
    {
    	std::ofstream file;
    	file.open("file.dat",std::ios::trunc|std::ios::binary);
    	if(!file)
    		std::cout<<"unable to open for output";
    
    	struct record
    	{
    		char code[6];
    		char name[20];
    		int i;
    	};
    
    	record r;
    	int a = 0;
    
    	while(1)
    	{
    		std::cout<<"Record " << a + 1 << std::endl;
    		std::cout<<"Enter character code, name and an int \n";
    		std::cin.getline(r.code,6);
    		std::cout.flush();
    		std::cin.getline(r.name,20);
    		std::cout.flush();
    		std::cin>>r.i;
    		std::cout.flush();
    		file.write((char *)&r,sizeof(r));
    		std::cout<<"\nAdd another (y\\n) : ";
    		char c;
    		std::cin>>c;
    		std::cout.flush();
    		if(c == 'n')
    			break;
    		a++;
    		std::cout<<'\n'<<'\n';
    	}
    	file.close();
    }
    Last edited by juice; 03-18-2012 at 01:23 PM.

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    cout::flush is working. Read what it does here:

    Synchronizes the buffer associated with the stream to its controlled output sequence. This effectively means that all unwritten characters in the buffer are written to its controlled output sequence as soon as possible ("flushed").
    So if you did a lot of output and need to make sure it appears before you do input, you call flush. When you seek in files, this is very relevant info. Otherwise you really don't have to worry unless input and output appear out of order on the screen, and it really doesn't sound like the problem.

    Instead, read about istream::getline and find the problem:

    Characters are extracted until either (n - 1) characters have been extracted or the delimiting character is found (which is delim if this parameter is specified, or '\n' otherwise). The extraction also stops if the end of file is reached in the input sequence or if an error occurs during the input operation.
    The full manual entry is here, and good to read if you don't know what it says already.

    Basically, I think you are reading data that is too long into strings that are too short. You might not want to change the record, but you will have to read into longer strings initially, to avoid the situation where the user can't type anymore.

  3. #3
    Registered User
    Join Date
    Aug 2011
    Posts
    385
    Quote Originally Posted by whiteflags View Post
    The full manual entry is here, and good to read if you don't know what it says already.

    Basically, I think you are reading data that is too long into strings that are too short. You might not want to change the record, but you will have to read into longer strings initially, to avoid the situation where the user can't type anymore.
    Yes I already read that, and the input that I am giving to getline is only one character, so there should not be any problem..

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
            std::cin>>r.i;
            std::cout.flush();
            file.write((char *)&r,sizeof(r));
            std::cout<<"\nAdd another (y\\n) : ";
            char c;
            std::cin>>c;
    This smells like a problem to me. Just consider that reading integers leaves the newline in the input buffer.
    I strongly urge you to stop using chars and start using std::string instead. Then replace std::cin.getline with std::getline.

    Those std::cout.flush() calls probably do little or nothing at all since you are flushing the output buffer and not the input buffer. Keep in mind that you can't "flush" an input buffer. It is undefined behavior. You can throw away buffered input with std::cin.ignore, however.
    fflush(stdin) is equally undefined.

    file.close() is just unnecessary.
    Last edited by Elysia; 03-18-2012 at 02:59 PM. Reason: Typo
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Taking a closer look the problem seems to be here:
    Code:
            char c;
            std::cin>>c;
            std::cout.flush();
            if(c == 'n')
                break;
    After this the loop repeats, so you should start at the top of the loop again, while running through it in your mind. Since the extraction operator will leave newlines in your input buffer after the input, those newlines will be read by cin.getline(r.code, 6); which breaks everything. You could fix it by using getline to read the continue character instead of treating it specially.

  6. #6
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Quote Originally Posted by Elysia View Post
    This smells like a problem to me.
    I didn't know you kept your eyeballs in your nose.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I don't need eyes to see bad code, it just smells bad
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User
    Join Date
    Aug 2011
    Posts
    385
    ok one last thing, why does the following statement fail to open the file..

    Code:
    std::fstream file1("file.dat",std::ios::binary);

  9. #9
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    fstream requires that you specify whether to open the file for reading, writing, or both. ifstream and ofstream do not, because they are child classes of fstream, written to handle input and output specifically.

  10. #10
    Registered User
    Join Date
    Aug 2011
    Posts
    385
    Quote Originally Posted by Elysia View Post
    replace std::cin.getline with std::getline.
    when I do that it says "error C2039: 'getline' : is not a member of 'std'"

  11. #11
    Registered User
    Join Date
    Aug 2011
    Posts
    385
    Quote Originally Posted by whiteflags View Post
    fstream requires that you specify whether to open the file for reading, writing, or both. ifstream and ofstream do not, because they are child classes of fstream, written to handle input and output specifically.
    I tried
    Code:
    std::fstream file1("file.dat",std::ios::in|std::ios::out|std::ios::binary);
    and after a while it hung up the whole program???

  12. #12
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    std::getline is a member of the std::string library and unless you use the std::string library you won't be able to call it. You can still use my advice if you want the least changes to fix the problem.

  13. #13
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Quote Originally Posted by juice View Post
    I tried
    Code:
    std::fstream file1("file.dat",std::ios::in|std::ios::out|std::ios::binary);
    and it hung up the whole program???
    OK but why did you try that? That is nothing like what you had before. If you don't need fstream, don't use it.

  14. #14
    Registered User
    Join Date
    Aug 2011
    Posts
    385
    Ok here's the complete code. It is supposed to read records from input and store them in a file called file.dat. Then it is supposed to arrange these records in ascending order, but the program hangs at line no. 66

    Code:
    #include "stdafx.h"
    #include <iostream>
    #include <fstream>
    #include <strstream>
    
    int main()
    {
    	std::ofstream file;
    	file.open("file.dat",std::ios::trunc|std::ios::binary);
    	if(!file)
    		std::cout<<"unable to open for output";
    
    	struct record
    	{
    		char code[6];
    		char name[20];
    		int i;
    	};
    
    	record r;
    	int a = 0;
    
    	while(1)
    	{
    		std::cout<<"Record " << a + 1 << std::endl;
    		std::cout<<"Enter character code, name and an int \n";
    		fflush(stdin);
    		std::cin.getline(r.code,6);
    		std::cout.flush();
    		std::cin.getline(r.name,20);
    		std::cout.flush();
    		std::cin>>r.i;
    		std::cout.flush();
    		file.write((char *)&r,sizeof(r));
    		std::cout<<"\nAdd another (y\\n) : ";
    		char c;
    		std::cin>>c;
    		std::cout.flush();
    		if(c == 'n')
    			break;
    		a++;
    		std::cout<<'\n'<<'\n';
    	}
    	file.close();
    
    	std::fstream file1("file.dat",std::ios::in|std::ios::out|std::ios::binary);
    	if(!file1)
    		std::cout<<"unable to open file1";
    
    	else
    	{
    		if(a>0)
    		{	while(a)
    			{
    				file1.seekp(0);
    				for(int i = a; i>0;i--)
    				{
    					record r1;
    					file1.read((char *)&r,sizeof(r));
    					file1.read((char *)&r1,sizeof(r1));
    					if(r1.i < r.i)
    					{
    						file1.seekp(-(sizeof(r)*2),std::ios::cur);
    						file1.write((char *)&r1,sizeof(r));
    						file1.write((char *)&r,sizeof(r));
    						file1.seekg(-(sizeof(r)),std::ios::cur);
    					}
    				}
    		
    				a--;
    			}
    		}
    		file1.close();
    	}
    
    	std::ifstream file2("file.dat",std::ios::binary);
    	if(!file2)
    		std::cout<<"unable to open file2";
          else
    	while(1)
    	{
    		std::cout<<"\n\n";
    		file2.read((char *)&r,sizeof(r));
    		if(file2.eof())
    			break;
    		std::cout<<r.code<<'\t'<<r.name<<'\t'<<r.i;
    	}
    }
    Last edited by juice; 03-18-2012 at 02:48 PM.

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    >> fflush(stdin);
    I already told you that's undefined.
    Go back and implement our suggestions before you proceed.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. infinite loop
    By juice in forum C Programming
    Replies: 9
    Last Post: 12-18-2011, 12:16 PM
  2. Replies: 3
    Last Post: 10-14-2011, 11:33 PM
  3. Infinite loop!!!
    By Bizmark in forum C Programming
    Replies: 3
    Last Post: 02-21-2009, 12:09 PM
  4. stays in loop, but it's not an infinite loop (C++)
    By Berticus in forum C++ Programming
    Replies: 8
    Last Post: 07-19-2005, 11:17 AM
  5. Infinite Loop!!!
    By Frantic- in forum C++ Programming
    Replies: 3
    Last Post: 12-13-2004, 06:39 PM