"Programming In Objective-C" (Book) Excersie

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

1. Darkroom Guest

Joined:
Dec 15, 2006
Location:
#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. robbieduncan Moderator emeritus

Joined:
Jul 24, 2002
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...

Joined:
Dec 15, 2006
Location:
#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. robbieduncan Moderator emeritus

Joined:
Jul 24, 2002
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

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. mysterytramp macrumors 65816

Joined:
Jul 17, 2008
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. garethlewis2 macrumors 6502

Joined:
Dec 6, 2006
#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 Guy macrumors member

Joined:
Sep 17, 2008
#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. bbarnhart macrumors 6502a

Joined:
Jan 16, 2002
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;
}

```

Joined:
Dec 15, 2006
Location:
#9
wow... yeah, i never would have gotten that... it's nice to see it and learn from example... thanks

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. garethlewis2 macrumors 6502

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

11. robbieduncan Moderator emeritus

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

12. bbarnhart macrumors 6502a

Joined:
Jan 16, 2002
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. mysterytramp macrumors 65816

Joined:
Jul 17, 2008
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. lee1210 macrumors 68040

Joined:
Jan 10, 2005
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. mysterytramp macrumors 65816

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

mt

16. deprecated macrumors newbie

Joined:
Oct 1, 2008
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. theotherbeck macrumors newbie

Joined:
Nov 15, 2008
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;

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. beebauman macrumors newbie

Joined:
Feb 13, 2009
#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. mdeh macrumors 6502

Joined:
Jan 3, 2009
#19

There is an entire thread on this exercise here:

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

20. Apr 10, 2011
Last edited by a moderator: Apr 11, 2011

srbrian5 macrumors newbie

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

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

Code:
```int number,divider,divcounter,left_Num, count, cKeeper;

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:

• code-.txt
File size:
10.3 KB
Views:
24
21. Apr 11, 2011
Last edited by a moderator: Apr 11, 2011

srbrian5 macrumors newbie

Joined:
Apr 10, 2011
#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;

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. tyche macrumors 6502

Joined:
Jul 30, 2010
#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");
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;
}
```

Joined:
Jun 12, 2014
#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. ArtOfWarfare macrumors 604

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