Stays in loop, but it's not an infinite loop...

Started by
10 comments, last by Zahlman 18 years, 9 months ago
I learned C two or so years ago, and I recently (last year) decided to teach myself cxx. I never got around to doing it until now. So I have this book called C++ Primer 2nd Edition by Stanley B. Lippman. Exercise 0-3 tells me to write a program that will count the amount of blanks, tabs, newlines, and characters (without white spaces) of an input. Few pages earlier it gave a similar program:
/*
*This program reads a character at a time from standard input
*until end-of file is encountered.  It keeps a count of both the number of
*characters and the number of lines it reads.  Its output is of the following form:
*	lineCount characterCount
#include <iostream.h>

int main ()
{
	char ch;
	int lineCnt=0, charCnt=0;
	
	while(cin.get(ch))
	{
		switch(ch)
		{
			case '\t':
			case ' ':
				break;
			case '\n':
				++lineCnt;
				break;
			default:
				++charCnt;
				break;
		}
	}
	cout<<lineCnt<<" "<<charCnt<<endl;
	return 0;
}
So I based my program off of that (hey, if it's given, I'll take it):
#include <iostream.h>

int main ()
{
	char ch;
	int lineCnt=0, charCnt=0, tabCnt=0, blankCnt=0;
	
	while(cin.get(ch))
		switch(ch)
		{
			case '\t':
				++tabCnt;
				break;
			case ' ':
				++blankCnt;
				break;
			case '\n':
				++lineCnt;
				break;
			default:
				++charCnt;
				break;
		}
	cout<<"\t\tTotal Characters: "<<charCnt<<"\n\n\nLines:   "<<lineCnt<<"\nChars:   "<<charCnt<<"\nTabs:    "<<tabCnt<<"\nBlanks: "<<blankCnt<<endl;
	return 0;
}
The output is as follows(I typed in "hello"):
EXECUTING:
/home/[username removed]/C++/Exercis0.3/Count
--------------------------------------------------------------
hello
And it just stays there... I asked my friend (been cxx programming for ~2.5 years now), and his initial thought was that it was in an infinite loop. I saw it as a possibility, but I didn't see why it would be stuck in an infinite loop, so I ran a test:
#include <iostream.h>

int main ()
{
	char ch;
	int lineCnt=0, charCnt=0, tabCnt=0, blankCnt=0;
	
	while(cin.get(ch))
	{
		switch(ch)
		{
			case '\t':
				++tabCnt;
				cout<<"t";
				break;
			case ' ':
				++blankCnt;
				cout<<"b";
				break;
			case '\n':
				++lineCnt;
				cout<<"n";
				break;
			default:
				++charCnt;
				cout<<"d";
				break;
		}
		cout<<" nothing\n";
	}
	cout<<"reached\n";
	cout<<"\t\tTotal Characters: "<<charCnt<<"\n\n\nLines:   "<<lineCnt<<"\nChars:   "<<charCnt<<"\nTabs:    "<<tabCnt<<"\nBlanks: "<<blankCnt<<endl;
	return 0;
}
The output is as follows (I typed in "hello"):
EXECUTING:
/home/[username removed]/C++/Exercis0.3/Count
--------------------------------------------------------------
hello
d nothing
d nothing
d nothing
d nothing
d nothing
n nothing
As you can see it never leaves the while loop, but it's not an infinite loop. What is going on? Just tell me that, and I might be able to solve the problem on my own.
Advertisement
Read the comment at the top of the Lippman program. Under what condition does the loop terminate? Has that condition been met?
Quote:Random site returned by Google
cin.get() performs a blocking read for the next character

It appears the while loop is waiting for cin.get() to return, but it never will because it's blocking until it gets more input.

EDIT: Sneftel beat me to it; I suppose EOF will cause cin.get() to fail and return false.
Ra
I'm not sure, but I think the break is only breaking from the switch...
correct; breaks within the switch statement will only break out of the switch; the while loop continues until cin.get returns false -> either EOF, or a read error has occurred. so, to end the program and get the character counts you desire, press Ctrl+D (linux; might work for windows cmd, i wouldn't be the person to ask)
Whack in a breakpoint somewhere in the while loop, then use your compiler's debugger to watch the value of ch.
If at first you don't succeed, call it version 1.0You don't stop playing because you get old; you get old when you stop playing.
ctrl+c or ctrl+z is the windows key for feeding a null (and therefore an end of file). Had to do the same sort of thing in Java a while back.

~Savagemonitor
Here is what I would do:
1) Change #include <iostream.h> to #include <iostream> and put using namespace std ; after all includes.
2) add in a done variable, so that the beginning of your loop looks like this:
while(cin.get(ch) && done == 0)

3) now, tweak it so that when the user presses a certain key (say 'q'), done will equal 1 and the loop will exit and display how many tabs, spaces, etc.


Just a question, not really related to this, why do you call C++ cxx?
First, I'll repeat myself. It's not out of the loop, but that doesn't make it an infinite loop. To my knowledge (using the checks) it's no longer in the loop. Other wise it would always repeat:
nothingnothingnothingnothing
And on and on and on (infinite loop). But it's not. In fact, you know it's not out of the the loop because it doesn't output:
d nothingd nothingd nothingd nothingd nothingn nothingreached
that "reach" would indicate it's no longer in the loop.

Oberon_Command, you are correct about using the flag, but I don't want any special characters because that could cause it to terminate "unexpectedly" (on the front-end).

I ran another test, this time on the user side. After writing "hello" and it did it's thing, I wrote "something" and found that it went through everything again. So it's in the loop, but it's not really an infinite loop. I had my mom help me out...

Thanks though
cin.get(ch) is waiting for you to enter text. That is why the while loop never terminates. In order to terminate the while loop, you have to input an end-of-file character. End-of-file causes cin.get(ch) to return false, so the loop condition will not be met and it will terminate.

End-of-file is either CTRL-D or CTRL-Z depending on what system you're on.

This topic is closed to new replies.

Advertisement