Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Darkroom

Guest
Original poster
Dec 15, 2006
2,445
0
Montréal, Canada
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;
	}
 
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.
 
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 :)
 
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.
 
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.
 
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;
    }
}
 
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;
}
 
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?
 
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?

It creates a 2D array 10 across and 10 down and pre-fills it with the correct values.
 
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;
}
 
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;
}
 
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

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
 
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

Thanks for the observation, Lee. This kind of guidance is very, very helpful.

mt
 
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;
}
 
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;
}
 
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.
 
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.


There is an entire thread on this exercise here:


HTML:
http://classroomm.com/objective-c/index.php?topic=36.0
 
Beautifully done!!!

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;
}

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...
 

Attachments

  • code-.txt
    10.3 KB · Views: 241
Last edited by a moderator:
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;
}
 
Last edited by a moderator:
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;
}
 
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);
            }
        }
    }
 
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);
            }
        }
    }

If someone puts in string that doesn't end in \n, this would crash... Right?
 
If someone puts in string that doesn't end in \n, this would crash... Right?
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
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.