"Programming In Objective-C" (Book) Excersie

Discussion in 'Mac Programming' started by Darkroom, Sep 23, 2008.

  1. macrumors 68020

    Darkroom

    Joined:
    Dec 15, 2006
    Messages:
    2,448
    Location:
    Montréal, Canada
    #1
    Exercise (from page 126): Write a program that takes an interger keyed in from the terminal and extracts and displays each digit of the interger in English. So, if the user types 932, the program should display "Nine Three Two". (Remember to display "Zero" if the user types in just a 0.) Note: This exercise is a hard one!.

    right... so i can't figure out how i could use a for loop in this situation... for loops are not my strong point... i feel that a for loop would reduce the redundent coding i have here so far. also, this code only works for 5 digit numbers. if the user types in 45, it will display "Zero Zero Zero Four Five"... not exactly ideal... i could copy this code 4 more times in different If statements [IE: If (Number < 10)] to go all the way down to one digit input, but again it would have even more redundent code.

    thoughts? suggestions?

    Code:
    #include <stdio.h>
    
    int main (int argc, const char * argv[])
    	{
    	int number, digit1, digit2, digit3, digit4, digit5;
    	
    	printf("Enter a number (max 5 digits): ");
    	scanf("%i", &number);
    	
    	if (number < 100000)
    		{
    		digit1 = number % 100000 / 10000;
    
    			switch (digit1)
    				{
    				case 0 : printf("Zero "); break;
    				case 1 : printf("One "); break;
    				case 2 : printf("Two "); break;
    				case 3 : printf("Three "); break;
    				case 4 : printf("Four "); break;
    				case 5 : printf("Five "); break;
    				case 6 : printf("Six "); break;
    				case 7 : printf("Seven "); break;
    				case 8 : printf("Eight "); break;
    				case 9 : printf("Nine "); break;
    				default : printf("Unknown Interger ");  break;
    				}
    
    		digit2 = number % 10000 / 1000;
    		
    			switch (digit2)
    				{
    				case 0 : printf("Zero "); break;
    				case 1 : printf("One "); break;
    				case 2 : printf("Two "); break;
    				case 3 : printf("Three "); break;
    				case 4 : printf("Four "); break;
    				case 5 : printf("Five "); break;
    				case 6 : printf("Six "); break;
    				case 7 : printf("Seven "); break;
    				case 8 : printf("Eight "); break;
    				case 9 : printf("Nine "); break;
    				default : printf("Unknown Interger ");  break;
    				}
    				
    		digit3 = number % 1000 / 100;
    		
    			switch (digit3)
    				{
    				case 0 : printf("Zero "); break;
    				case 1 : printf("One "); break;
    				case 2 : printf("Two "); break;
    				case 3 : printf("Three "); break;
    				case 4 : printf("Four "); break;
    				case 5 : printf("Five "); break;
    				case 6 : printf("Six "); break;
    				case 7 : printf("Seven "); break;
    				case 8 : printf("Eight "); break;
    				case 9 : printf("Nine "); break;
    				default : printf("Unknown Interger ");  break;
    				}
    
    		digit4 = number % 100 / 10;
    		
    			switch (digit4)
    				{
    				case 0 : printf("Zero "); break;
    				case 1 : printf("One "); break;
    				case 2 : printf("Two "); break;
    				case 3 : printf("Three "); break;
    				case 4 : printf("Four "); break;
    				case 5 : printf("Five "); break;
    				case 6 : printf("Six "); break;
    				case 7 : printf("Seven "); break;
    				case 8 : printf("Eight "); break;
    				case 9 : printf("Nine "); break;
    				default : printf("Unknown Interger ");  break;
    				}		
    		
    		digit5 = number % 10;
    
    			switch (digit5)
    				{
    				case 0 : printf("Zero "); break;
    				case 1 : printf("One "); break;
    				case 2 : printf("Two "); break;
    				case 3 : printf("Three "); break;
    				case 4 : printf("Four "); break;
    				case 5 : printf("Five "); break;
    				case 6 : printf("Six "); break;
    				case 7 : printf("Seven "); break;
    				case 8 : printf("Eight "); break;
    				case 9 : printf("Nine "); break;
    				default : printf("Unknown Interger ");  break;
    				}
    		}
    		else
    		{
    		printf("Entered Number is too long.");
    		}
    	return 0;
    	}
    
     
  2. Moderator

    robbieduncan

    Staff Member

    Joined:
    Jul 24, 2002
    Messages:
    24,480
    Location:
    London
    #2
    If I were you I'd turn the number into a NSString the peal each character off in turn in a loop...
     
  3. macrumors 68020

    Darkroom

    Joined:
    Dec 15, 2006
    Messages:
    2,448
    Location:
    Montréal, Canada
    #3
    yeah, i kinda figured that's possible. but it wasn't yet discussed in the book... the only things concretely discussed so far are data types, operators, IF/Else, Switch, For, While... ya know, basic C stuff... i think the only thing really Objective-C that was mentioned so far was BOOL... so essentially i'm trying to use a For loop since it's the only thing mentioned so far that i *think* could reduce the redundant code.
     
  4. Moderator

    robbieduncan

    Staff Member

    Joined:
    Jul 24, 2002
    Messages:
    24,480
    Location:
    London
    #4
    Hmm, OK. A recursive function wound be my next choice. The function would be something like this:

    Divide input by 10 and store in newVar.
    If newVar>10 call the function with newVar
    Get remainder (% operator) for dividing input by 10.
    Use remainder to lookup what the number is in english and print it.

    This will handily print the number furthest to the left first :D

    Another handy hint:
    The case statement is no necessary. Store the strings in an array indexed correctly and you can just look them up directly :)
     
  5. macrumors 65816

    mysterytramp

    Joined:
    Jul 17, 2008
    Messages:
    1,333
    Location:
    Maryland
    #5
    Part of the issue might be to think of the number from right to left rather than from left to right.

    Peel off the digits arithmetically, convert to strings and then PREPEND the string instead of appending the string to your output.

    You could use a while loop instead of a for loop, and then user could have an integer of virtually unlimited size.
     
  6. macrumors 6502

    Joined:
    Dec 6, 2006
    Messages:
    277
    #6
    There are two solutions to this that don't use any cheating, e.g. using NSString, etc.

    The first has already been mentioned and that is to use recursion. You will not run out of stack space, but you will unnecessarily allocate a large amount of memory.

    e.g. imagine you had the value
    1234
    You would first push 4 onto the stack then divide 1234 by 10 to get 123, then call the getdigit function again, which will push 3 onto the stack before dividing by 10, but this time, your stack page contains 4 followed by 3, and then another stack page containing 4.

    The other solution is far more elegant and does not involve any recursion. This is to use linked lists. You just use the push operation to keep 'push'ing elements onto the front of the queue. So you first get 4, push this onto the list, then get 3 and push that onto the list, then get 2 and push that , then 1 and push that, and you have a list which looks like

    head -> 1 -> 2 -> 3 -> 4 -> nil.

    Easy. You still have to code it, and no I will not send you the code, you need to solve these on your own.
     
  7. macrumors member

    Joined:
    Sep 17, 2008
    Messages:
    82
    #7
    You can also count the digits and start dividing from the end.

    Code:
    void print_digits(int number) {
        char* digits[10] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eigth", "nine"};
    
        int number_len = 1;
        int number_copy = number;
        while(number_copy /= 10 ) number_len++; 
        
        int power = pow(10, number_len - 1);
        while(number_len--) {
            printf("%s ", digits[number/power]);
            number %= power;
            power /= 10;
        }
    }
    
     
  8. macrumors 6502a

    bbarnhart

    Joined:
    Jan 16, 2002
    Messages:
    823
    Location:
    Stilwell, Kansas
    #8
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main (int argc, char * const argv[])
    {
    	 
    	char numbers[10][10] = {{"Zero"}, {"One"}, {"Two"}, {"Three"}, {"Four"}, {"Five"}, {"Six"}, {"Seven"}, {"Eight"}, {"Nine"} };
    	
    	char input[100];
    	printf("Enter number: ");
    	scanf("%s", &input);
    	
    	for (int i=0 ; i < strlen(input); i++)
    	{
                printf("%s ", numbers[input[i] - 48]);
    	}
    	
    	return 0;
    }
    
    
     
  9. macrumors 68020

    Darkroom

    Joined:
    Dec 15, 2006
    Messages:
    2,448
    Location:
    Montréal, Canada
    #9
    wow... yeah, i never would have gotten that... it's nice to see it and learn from example... thanks :)

    i'm curious about this:

    Code:
    char numbers[10][10] = {{"Zero"}, {"One"}, {"Two"}, {"Three"}, {"Four"}, {"Five"}, {"Six"}, {"Seven"}, {"Eight"}, {"Nine"} };
    
    your numbers variable has 2 max 10 characters arguments? and then your assigned are wrapped in braces individually... can you explain this to me?
     
  10. macrumors 6502

    Joined:
    Dec 6, 2006
    Messages:
    277
    #10
    Urgghhh. Buffer overflow errors with that solution. Vomit
     
  11. Moderator

    robbieduncan

    Staff Member

    Joined:
    Jul 24, 2002
    Messages:
    24,480
    Location:
    London
    #11
    It creates a 2D array 10 across and 10 down and pre-fills it with the correct values.
     
  12. macrumors 6502a

    bbarnhart

    Joined:
    Jan 16, 2002
    Messages:
    823
    Location:
    Stilwell, Kansas
    #12
    More better?

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main (int argc, char * const argv[])
    {
    	char* numbers[] = {"Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"};
    	const int len = 100;
    	char input[len];
    	printf("Enter number: ");
           fgets(input, len, stdin);
    	
    	for (int i=0; i < strlen(input); i++)
    	{
                if (input[i] >= '0' && input[i] <= '9')
                {
                    printf("%s ", numbers[input[i] - '0']);
                }    
    	}
    	
    	return 0;
    }
    
     
  13. macrumors 65816

    mysterytramp

    Joined:
    Jul 17, 2008
    Messages:
    1,333
    Location:
    Maryland
    #13
    Not terribly elegant -- I think bbarnhart wins that one -- but I muscled through this and here's what I got. I find while loops easier to read than for loops and the switch block easier to follow than an array. Limitations of human processor.

    mt

    Code:
    #import <Foundation/Foundation.h>
    
    int main (int argc, const char * argv[]) {
    	 
    	int input, i, digits[100];
    	printf("Enter number: ");
    	scanf("%d", &input);
    	i=1;
    	while(input > 0) {
    		digits[i] = input % 10;
    		input = (input/10);
    		i=i+1;
    	}
    	i=i-1;
    	while(i > 0) {
    		switch (digits[i])
    			{
    			case 0 : printf("Zero "); break;
    			case 1 : printf("One "); break;
    			case 2 : printf("Two "); break;
    			case 3 : printf("Three "); break;
    			case 4 : printf("Four "); break;
    			case 5 : printf("Five "); break;
    			case 6 : printf("Six "); break;
    			case 7 : printf("Seven "); break;
    			case 8 : printf("Eight "); break;
    			case 9 : printf("Nine "); break;
    			default : printf("Unknown Integer ");  break;
    			}
    		i = i-1;
    	}
    	printf("\n");
    
    	return 0;
    }
    
     
  14. macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Messages:
    3,172
    Location:
    Dallas, TX
    #14
    There's certainly something to be said for readability and ease of understanding, but understand that using a switch is equivalent to a very large, nested if-else structure. In something like this example, branching 5-6 times for each of 5 digits is not a big deal vs. constant time access to an array. However, be sure in actual intensive situations you are careful with switch, because it can slow things down.

    -Lee
     
  15. macrumors 65816

    mysterytramp

    Joined:
    Jul 17, 2008
    Messages:
    1,333
    Location:
    Maryland
    #15
    Thanks for the observation, Lee. This kind of guidance is very, very helpful.

    mt
     
  16. macrumors newbie

    Joined:
    Oct 1, 2008
    Messages:
    1
    Location:
    north pole
    #16
    My solution:

    Code:
    #import <stdio.h>
    #import <objc/Object.h>
    
    int main()
    {
    	int num, num_ = 0;
    	
    	printf("enter integer number:");
    	scanf("%i", &num);
    	
    	// revert typed number into variable num_
    	do
    	{
    		num_ *= 10;
    		num_ += num % 10;
    		num /= 10;
    	}while (num > 0);
    
    	// print each sign of reverted variable 
    	do
    	{
    		switch (num_ % 10)
    		{
    			case 1:
    				printf("one");
    				break;
    			case 2:
    				printf("two");
    				break;
    			case 3:
    				printf("three");
    				break;
    			case 4:
    				printf("four");
    				break;
    			case 5:
    				printf("five");
    				break;
    			case 6:
    				printf("six");
    				break;
    			case 7:
    				printf("seven");
    				break;
    			case 8:
    				printf("eight");
    				break;
    			case 9:
    				printf("nine");
    				break;
    			case 0:
    				printf("zero");
    				break;
    		}
    		// print space between each sign
    		printf(" ");
    		num_ /= 10;
    	}while (num_ > 0);
    	
    	printf("\n");
    	
    	return 0;
    }
     
  17. macrumors newbie

    Joined:
    Nov 15, 2008
    Messages:
    10
    Location:
    New York, NY
    #17
    printing numbers in order - not backwards?

    Hi guys,

    I just posted another thread trying to figure this out, and then was directed here... Below is what I figure out, but it, like all the other solutions in this thread seem to print the numbers backwards... I believe the exercise was to print them forward in order. Anyone know how to do that? It seems to me there has to be a simple way to turn the number around before running the loop, but I can't figure out what that way would be. Thanks!

    Code:
    
    // Program to print the numbers entered in english
    
    #import <stdio.h>
    #import <objc/Object.h>
    
    int main (int argc, char *argv[])
    {
    	int		number, right_digit;
    
    	printf ("Enter your number.\n");
     	scanf ("%i", &number);
    	
    	//seems like I should reverse the entered number here, but I can't figure out how.
    	
    	do {		//gets the last number
    		right_digit = number % 10;
    				
    				//prints the last number as a word
    				if (right_digit == 0) {
    					printf("zero");
    				}
    				else if (right_digit == 1){
    					printf("one ");
    					}
    				else if (right_digit == 2){
    					printf("two ");
    					}
    				else if (right_digit == 3){
    					printf("three ");
    					}
    				else if (right_digit == 4){
    					printf("four ");
    					}
    				else if (right_digit == 5){
    					printf("five ");
    					}
    				else if (right_digit == 6){
    					printf("six ");
    					}
    				else if (right_digit == 7){
    					printf("seven ");
    					}
    				else if (right_digit == 8){
    					printf("eight ");
    					}
    				else if (right_digit == 9){
    					printf("nine ");
    					}
    				
    		// loses last number from number entered		
    		number /= 10;
    	} while (number != 0);
    	
    		
    
    	
    	return 0;
    }
    
    
     
  18. macrumors newbie

    Joined:
    Feb 13, 2009
    Messages:
    6
    #18
    I like deprecated's solution best

    deprecated, I think your solution was the one that the author intended. All others (with the exception of the first one by Darkroom) incorporate concepts not yet taught by the book.
     
  19. macrumors 6502

    Joined:
    Jan 3, 2009
    Messages:
    344
    #19

    There is an entire thread on this exercise here:


    HTML:
    http://classroomm.com/objective-c/index.php?topic=36.0
     
  20. srbrian5, Apr 10, 2011
    Last edited by a moderator: Apr 11, 2011

    macrumors newbie

    Joined:
    Apr 10, 2011
    Messages:
    2
    #20
    Beautifully done!!!

    This is the way I did it.. by my self..

    Code:
    int number,divider,divcounter,left_Num, count, cKeeper;
    	 
    	NSLog(@"Enter your number.");
    	scanf("%i", &number);
        
    	left_Num = number; //Set User number
    	
    	do //No how many digits
    	{
    		left_Num /= 10;
    		++cKeeper;// How many time loop have 2 run
    		
    	}
    	while (left_Num != 0);
    	
    	left_Num = number; //reload user number
    	
    while (cKeeper != 0)
    {
    	
    	divider = 10;
    	count = 0;
    	
    	do  //No how many digits
    	{
    		left_Num /= 10;
    		++count; //how many time run loop to look for correct number
    		
    	}
    	while (left_Num != 0);
    	
    	
    	count -= 1; //Take one out so we get fisrt digit
    	
    	left_Num = number; //need to keep 'number' intact
    	divcounter = cKeeper; //Set counter to increase divider
    
    	do  //Get the digits to diplay number in a word.
    	{
    		if (count !=0) //Avoid division of last digits.
    		left_Num /= 10;
    		--count;
    		
    		for(divcounter; divcounter > 2; --divcounter) 
    		{
    			divider *= 10; //set divider to set correct residual to number
    		}
    	} 
    	while (count > 0);
        
    	number %= divider;  //Get new number value
    	
    		
    	switch (left_Num) //Display Correct Msg
    	{
    		case 0:NSLog(@"Zero");break;
    		case 1:NSLog(@"One");break;
    		case 2:NSLog(@"Two");break;
    		case 3:NSLog(@"Three");break;
    		case 4:NSLog(@"Four");break;
    		case 5:NSLog(@"Five");break;
    		case 6:NSLog(@"Six");break;
    		case 7:NSLog(@"Seven");break;
    		case 8:NSLog(@"Eight");break;
    		case 9:NSLog(@"Nine");break;	
    		default:NSLog(@"Not a digits");break;
    	}
    	left_Num = number; //reload user number
    	--cKeeper; //One time less
    }
    Dint know that you can accumulate and integer like that. Learn something new every day...
     

    Attached Files:

  21. srbrian5, Apr 11, 2011
    Last edited by a moderator: Apr 11, 2011

    macrumors newbie

    Joined:
    Apr 10, 2011
    Messages:
    2
    #21
    After sleep an take another look on what I did, find to many unnessesary thing so I rewrote it
    this my new solution:

    Code:
    int number, left_Num, count, divider;
    	 
    	NSLog(@"Enter your number.");
    	scanf("%i", &number);
      
    	divider = 1; //Set divider
    	left_Num = number;//Set User number
            count = 0; //set counter to zero
    	
    	while (left_Num > 9)//stop in last digits user enter
    	{
    		divider *= 10; //Set the divider to get left num.
    		left_Num /= 10; // reduce value to end loop
    		++count; //create count for next loop
    	} 
    	
        ++count; //since above loop was set to finish 1 digits early we add it here to the count
    	
    while (count != 0) 
    {
    	left_Num = number / divider; //get the left num
    	number %= divider; //Get the rest of number digits (ex. if 932, result is 32)
    	divider /= 10; // decrease divider for update number (ex. update number is 32, divider is 100, result is divider = 10
    	--count; // decrease counter to finish loop
    	
    	switch (left_Num)//Display Correct Msg
    	{
    		case 0:NSLog(@"Zero");break;
    		case 1:NSLog(@"One");break;
    		case 2:NSLog(@"Two");break;
    		case 3:NSLog(@"Three");break;
    		case 4:NSLog(@"Four");break;
    		case 5:NSLog(@"Five");break;
    		case 6:NSLog(@"Six");break;
    		case 7:NSLog(@"Seven");break;
    		case 8:NSLog(@"Eight");break;
    		case 9:NSLog(@"Nine");break;	
    		default:NSLog(@"Not a digits");break;
    	}
    	
    }	
        [pool drain];
        return 0;
    }
     
  22. macrumors 6502

    Joined:
    Jul 30, 2010
    Messages:
    269
    #22
    progrmaming in C by Kochan exercise 6-6

    Ok, this was hard. I am reading the Programming in C version but it looks like it has similar problems with the objective-C version.

    Anyway, I'm new to C so I tried to solve this by only using what I have been taught in the book so far and didn't cheat by using arrays and stuff.

    My solution also covers 0's to the right. eg 100 results in one zero zero. Hope this helps others understand.

    Code:
    int main(void)
    {
    	int count = 0, val = 0, flipval = 0, tval = 0, loop = 0;
    	
    	printf("Programming in C by Kochan\n");
    	printf("Chapter 6, example 6\n");
    	printf("Write a program that takes an integer\nkeyed in from the terminal and extracts and displays\neach digit of the integer in English\n");
    	printf("-----------------------------------\n");
    	printf("Enter your number :");
    	scanf("%i", &val);
    	
    // find out how many digits were typed to be used later
    	tval = val;
    	do
    	{
    		tval = tval / 10;
    		count++;
    	}
    	while (tval !=0);
    
    // now flip the digits once
    	do
    	{
    		flipval = flipval * 10;
    		flipval = flipval + val % 10;
    		val = val / 10;
    	}
    	while (val > 0);
    
    	// now strip each digit and change to a word. 
    	// we use a loop to catch trailing 0's by keeping track of how many digits we started with
    	// ex. 400 flips to 4 so we need to loop 3 times and add two zero's.
    	for ( loop =1; loop <= count; loop++)
    	{
    		switch (flipval % 10)
    		{
    			case 1:
    				printf("one ");
    				break;
    			case 2:
    				printf("two ");
    				break;
    			case 3:
    				printf("three ");
    				break;
    			case 4:
    				printf("four ");
    				break;
    			case 5:
    				printf("five ");
    				break;
    			case 6:
    				printf("six ");
    				break;
    			case 7:
    				printf("seven ");
    				break;
    			case 8:
    				printf("eight ");
    				break;
    			case 9:
    				printf("nine ");
    				break;
    			case 0:
    				printf("zero ");
    				break;
    			default :
    				printf("zero ");
    		}
    		flipval = flipval / 10;
    	}
    	return 0;
    }
    
     
  23. macrumors newbie

    Joined:
    Jun 12, 2014
    Messages:
    2
    #23
    Code:
    @autoreleasepool {
            char temp;
            char * s = "[lazyness placeHolder]";
            NSLog(@"Enter the number mayne");
            while ((temp = getchar()) != '\n') {
                s = (temp == '0') ? "zero " :
                (temp == '1') ? "one " :
                (temp == '2') ? "two " :
                (temp == '3') ? "three " :
                (temp == '4') ? "four " :
                (temp == '5') ? "five " :
                (temp == '6') ? "six " :
                (temp == '7') ? "seven " :
                (temp == '8') ? "eight " :
                (temp == '9') ? "nine " : "NaN " ;
                if (s[1] != 'a') {
                    printf("%s",s);
                }
            }
        }
    
     
  24. macrumors 603

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    Messages:
    6,245
    #24
    If someone puts in string that doesn't end in \n, this would crash... Right?
     
  25. macrumors newbie

    Joined:
    Jun 12, 2014
    Messages:
    2
    #25
    It shouldn't as when typing in the terminal you have to press "Enter" or "Return". It has a spectacular chance of crashing if reading from a file as I have no EOF checks
     

Share This Page