Thread: question about the loop in case conversion program

  1. #1
    Registered User Elhaz's Avatar
    Join Date
    Sep 2004
    Posts
    32

    question about the loop in case conversion program

    In Herbert Schildt's "C++ A Beginner's Guide" one of the module mastery questions is to create a program that converts lowercase letters to uppercase (and vice-versa) and displays the result without making any changes to other characters. The progam has to stop when the user enters a '.' and at the end the program has to display the number of case changes made.

    It's a simple program and I got it to work just fine... maybe too fine. What I mean by this is that I got results that I wasn't expecting... seemingly good results.

    First, the program as I wrote it:

    Code:
    // C++ A Beginer's Guide - Herbert Schildt
    // Module 3 Mastery Check Question # 11
    
    // Case Converter
    
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
    	cout << "Case Converter\n\n";
    	cout << "Please type something (enter a \'.\' to quit):\n\n";
    
    	char input;
    	int caseCounter = 0;  // records number of coversions
    
    	while (input != '.')
    	{
    		cin >> input;
    
    		if ((input >= 'a') && (input <= 'z'))
    		{
    			input = input - 32;  // converts the case
    			cout << input;
    			caseCounter++;
    		}
    		else if ((input >= 'A') && (input <= 'Z'))
    		{
    			input = input + 32;
    			cout << input;
    			caseCounter++;
    		}
    		else cout << input;
    	}
    	cout << "\n\nThe number of case changes was: " 
                    << caseCounter << "\n\n";
    
    	system ("PAUSE");
    
    	return 0;
    }
    When I first tested the progam I entered one character at a time and the results were what I expected. Then I thought I'd try to enter multiple characters before hitting the enter key. (For example instead of hitting just 'H' or 'f' I typed a word 'hELLO'). After hitting enter each letter in the string(?) was converted ('Hello'). The case counter accurately reflected the number of changes.

    Woo hoo! Cool! But then I got thinking:

    This must mean that the loop was executing for each character typed into "input" regardles of when the enter key is hit. But I don't know how this happens. Is C++ converting the string(?) into a char array for me? And if so, is this dangerous? I mean I know that there is no bounds checking on arrays in C++... I don't want to overwrite anything important accidentally.

    Or do I have it all wrong?

    Any comments would be appreciated.

    Thanks.

  2. #2
    Registered User axon's Avatar
    Join Date
    Feb 2003
    Posts
    2,572
    hello elhaz, welcome to the boards. I've modified your program a bit, to help you see what is going on in it. If you still have some questions about it, ask away.

    Code:
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
    	cout << "Case Converter\n\n";
    	cout << "Please type something (enter a \'.\' to quit):\n\n";
    
    	char input;
    	int caseCounter = 0;  // records number of coversions
            int i=0;
    	while (input != '.')
    	{
                     
    		cin >> input;
    		cout << "\n" <<  i << ": " << input << endl;
    		i++;
    		if ((input >= 'a') && (input <= 'z'))
    		{
    			input = input - 32;  // converts the case
    			cout << input;
    			caseCounter++;
    		}
    		else if ((input >= 'A') && (input <= 'Z'))
    		{
    			input = input + 32;
    			cout << input;
    			caseCounter++;
    		}
    		else cout << input;
    	}
    	cout << "\n\nThe number of case changes was: " 
                    << caseCounter << "\n\n";
    
    	system ("PAUSE");
    
    	return 0;
    }

    some entropy with that sink? entropysink.com

    there are two cardinal sins from which all others spring: Impatience and Laziness. - franz kafka

  3. #3
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    This must mean that the loop was executing for each character typed into "input" regardles of when the enter key is hit. But I don't know how this happens.
    What happens when you type characters is that they get sent to an input buffer somewhere. What cin does is extract characters from the input buffer for you. If do cin>>(some char), it extracts one character. If you do cin>>(some int), it reads in everything in the input buffer up to the first whitespace and tries converting it to an integer. So what happens with your cin >> char is that you type "hello", and hit enter. Once you hit enter, it reads the input.. one char. So far so good, then your loop says to cin >> another char, so since the enter key hasn't been extracted from the input buffer yet, it thinks you've hit enter already (This part is fuzzy, I might be wrong) so it inputs another char... and so on, until it gets to the end of the characters and find the enter.

    Is C++ converting the string(?) into a char array for me? And if so, is this dangerous? I mean I know that there is no bounds checking on arrays in C++... I don't want to overwrite anything important accidentally.
    As I mentioned above, it isn't technically a 'string', it's an input buffer - sort of like a queue, and it isn't converting it into a char array for you, and if it was, it might be dangerous but you'd probably just get an illegal operation and crash if you ever overstepped the bounds.

    Note: On a modern system, it's very hard to accidentally destroy your computer. It's hard to even tell when there's a memory leak, because there's too much RAM for it to all disappear in a noticeable amount of time And Windows restricts everything, so anything dangerous tends to be illegal, and you get a crash.
    Last edited by Hunter2; 09-19-2004 at 10:03 PM.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by Elhaz
    In Herbert Schildt's
    How many people just cringed and stopped reading there?

    *raises hand*

    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    Nov 2002
    Posts
    126
    I've got a little tip for you to make your algorithm much cleaner. In ASCII code, the only difference between a letter and the same letter of the opposite case is the fifth bit of the character. Upper case numbers have a fifth bit value of 0, lower case of 1, and the rest of the bits are the same. So to change the case of a letter, all you need to do is flip the fifth bit of the number. How do you do that? With the binary exclusive OR operator (^). If you don't know about binary operators or the exclusive or operation, look them up. At any rate, here's my revision of your code:

    Code:
    // C++ A Beginer's Guide - Herbert Schildt
    // Module 3 Mastery Check Question # 11
    
    // Case Converter
    
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
    	cout << "Case Converter\n\n";
    	cout << "Please type something (enter a \'.\' to quit):\n\n";
    
    	char input;
    	int caseCounter = 0;  // records number of coversions
    
    	while (input != '.')
    	{
    		cin >> input;
    
    		if( input >= 'A' && input <= 'z' )
    		{
    			input ^= 1 << 5; //Flip the fifth bit of the char
    			caseCounter++;
    		}
    		
    		cout <<input;
    	}
    	
    	cout << "\n\nThe number of case changes was: " 
                    << caseCounter << "\n\n";
    }
    Oooh, clean. If you didn't know, the << operator is used as the binary shift operator(google it )

  6. #6
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    [hijack]
    Good C++ programmers have no need for void, just as good C programmers have no need for goto
    Really? So every single function must return a value? What on earth for?
    [/hijack]

    Quzah.
    Hope is the first step on the road to disappointment.

  7. #7
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    [adding to hijack]
    Ya i was thinking the same thing!
    [/adding to hijack]
    Woop?

  8. #8
    Registered User Elhaz's Avatar
    Join Date
    Sep 2004
    Posts
    32
    Axon,

    Thanks for the code insert, it helped a lot in figuring out "how" it was happening. I noticed a similar thing when I was trying to get a new line between enter-key presses. I put a "\n" in the loop hoping to break up input and output lines but it inserted a new line between each character. Cool.

    And thanks for the welcome!


    Hunter2,

    Thanks for the explanation. Really helped a lot as to "why" it was happening. As for whitespace, I noticed that if I input a short sentence it outputs the whole converted sentence, minus the spaces. I guess the loop just keeps telling it to go back for more even after the white space.

    Thanks, too, for the memory tips. Glad to know it's not that easy to do serious damage.


    quzah,

    Can't say I know why Schildt's name would cause you to cringe. Is his stuff no good? But hey, it's a breath of fresh air compared to what I was working out of before. I fear to mention it because if Shildt makes you cringe then this'll probably make you faint dead away... Davis's "C++ for Dummies". Shock! Horror! Yes, THAT was a terrible book. Had to read each chapter three times just to make sense of it. Way too many holes. Had to grit my teeth through all the bad jokes too.

    Schildt's book give's good detail (so far) and has program assignments (something I really needed). That and no stupid jokes to grit my teeth through.


    PorkyChop,

    Thanks for the binary shift operator info. I will definitely look into it. I'm still a beginner but can already sorta see a difference between smooth and chunky code (at a beginner level). Elegant code is something I'll definitely strive for as I progress.


    quzah (again) and prog-bman,

    Hey, I don't mind you hijacking my thread. I'm just "da lil' fish in da big pond" and will take any chance to learn that I can get. Wanna fill me in on it a little more? What thread is this spawned from? I'll check it out.


    Thanks again to all for your input.

  9. #9
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Hey, I don't mind you hijacking my thread. I'm just "da lil' fish in da big pond" and will take any chance to learn that I can get. Wanna fill me in on it a little more? What thread is this spawned from? I'll check it out.
    It's spawned from PorkyChop's signature, which I also completely disagree with (as I detailed in a Private Message to him/her). I'd very much like to hear the response

    Anyway, always glad to help in any capacity I may. Glad you got it figured out!
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. get keyboard and mouse events
    By ratte in forum Linux Programming
    Replies: 10
    Last Post: 11-17-2007, 05:42 PM
  2. Intel syntax on MinGW ?
    By TmX in forum Tech Board
    Replies: 2
    Last Post: 01-06-2007, 09:44 AM
  3. ascii rpg help
    By aaron11193 in forum C Programming
    Replies: 18
    Last Post: 10-29-2006, 01:45 AM
  4. Replies: 27
    Last Post: 10-11-2006, 04:27 AM
  5. rand()
    By serious in forum C Programming
    Replies: 8
    Last Post: 02-15-2002, 02:07 AM