Thread: It works but, there's confusion, please help with this solution.

  1. #1
    Registered User
    Join Date
    Aug 2022
    Posts
    40

    It works but, there's confusion, please help with this solution.

    Hey Guys,

    My code works as it is supposed to according to the problem in the book. I wish I could say that I learned a lot as it took me several hours to complete. The truth is, I hacked my way through it by trying this and that until it worked. Terrible I know.

    Code:
    //http://knking.com/books/c2/answers/c13.html
    #include <stdio.h>
    
    int main(){
        char *digOne[]={"twenty", "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety"};
        char *digTwo[]={"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", \
    "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
        char num[9];
        int x;
        printf("Enter a two-digit number: ");
        scanf("%s", num);                     // I enter 23 - it is saved as a string in num
    
    
        if(num[0]=='0'){                        //'0' could be changed 48
            sscanf(num, "%d", &x);              // saves num as an int inside x
            printf("%s", digTwo[x]);            // works marvelously
        }
        else if(num[0]=='1'){                   //'1' could also be 49
            sscanf(num, "%d", &x);              // same as above
            printf("%s", digTwo[x]);            // works marvelously
        }
        else{
            char both[5];
            char ones, tens;
            sscanf(num, "%s", both);            // this time saves num as a string placed in both
            tens = both[0];
            printf("tens as int: %d\n", tens);  // 2 prints as 50
            printf("tens as char: %c\n", tens); // 2 prints as 2 but, I think it is '2' 
            ones = both[1];
            printf("%s", digOne[tens-'2']);     //'2' could also be 50
            if(digTwo[ones-48]!="zero"){
                printf(" %s", digTwo[ones-'0']); //'0' could also be 48
            }
        }
    
    
        return 0;
    }
    I understand why it all works but, I'm sure there was a much cleaner way to solve this problem and the answer to the problem is not provided in the book. I think it is inefficient how I converted things from integer to string, etc. I'm sure there is a better way.

    Is anyone willing to show me a simpler way to make it work? This is an area of c programming that I really struggle with (I.e. converting strings to integers and vice versa). Thank you for any comments.

  2. #2
    Registered User
    Join Date
    Sep 2020
    Posts
    425
    I would get the input as an integer,

    Then if less then zero, error out
    If more than 99, error out.

    If less than 20 print digTwo(number)

    Otherwise print digOne (number divided by 10 subtract 2) followed by digTwo (number mod 10)

  3. #3
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Here's one thing that is doing unnecessary work:

    Quote Originally Posted by mpatters View Post
    Code:
            char both[5];
            char ones, tens;
            sscanf(num, "%s", both);            // this time saves num as a string placed in both
    num is already a string read in by scanf, so this sscanf does nothing but copy num to both. You don't modify num or both in the following code, so why not just use num where you use both?
    Code:
        else{
            char ones, tens;
            tens = num[0];
            printf("tens as int: %d\n", tens);  // 2 prints as 50
            printf("tens as char: %c\n", tens); // 2 prints as 2 but, I think it is '2' 
            ones = num[1];
            printf("%s", digOne[tens-'2']);     //'2' could also be 50
            if(digTwo[ones-48]!="zero"){
                printf(" %s", digTwo[ones-'0']); //'0' could also be 48
            }
        }
    But I wouldn't even bother with that change; I'd start with getting a number as an int directly:
    Code:
    int num;
    scanf("%d", &num);
    And then do arithmetic/tests on the integer rather than mess around with looking at the digits:
    Code:
    if (num < 20) {
      printf("%s\n", digTwo[num]);
    } else if (num < 100) {
      int tens = num / 10;
      int ones = num % 10;
      if (ones != 0) {
        printf("%s %s\n", digOne[tens], digTwo[ones]);
      } else {
        printf("%s\n", digOne[tens]);
      }
    }
    Untested.

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Also note that
    Code:
    if(digTwo[ones-48]!="zero")
    produces Undefined Behavior, you can't compare two strings like that, you would need to use strcmp().

  5. #5
    Registered User
    Join Date
    Aug 2022
    Posts
    40
    Thanks hamster_nz and christop, that code you gave me is so much easier to follow than the maze that I coded. Using \10 and %10 is something that should have come into my mind but, didn't.... Great job guys. Awesome. Onto the next exercise...

  6. #6
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by jimblumberg View Post
    Also note that
    Code:
    if(digTwo[ones-48]!="zero")
    produces Undefined Behavior, you can't compare two strings like that, you would need to use strcmp().
    Is it undefined behavior or only implementation defined? AFAIK it's perfectly legal to compare two pointers, but the result won't necessarily be what you want or expect because some implementations merge identical string literals (the pointers will be equal) while some don't (the pointers won't be equal).

  7. #7
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    Quote Originally Posted by christop View Post
    Is it undefined behavior or only implementation defined? AFAIK it's perfectly legal to compare two pointers, but the result won't necessarily be what you want or expect because some implementations merge identical string literals (the pointers will be equal) while some don't (the pointers won't be equal).
    Technically it is "unspecified behavior", so the implementation does not even need to document how it is handled.
    [lex.string]
    ... Whether all string-literals are distinct (that is, are stored in nonoverlapping objects) and whether successive evaluations of a string-literal yield the same or a different object is unspecified. ...
    EDIT: I just realized I've given a link/quote to the C++ standard, not C! I'll try to find the C link/quote.

    I guess this is (maybe) saying the same thing in the C standard:
    Draft standard n1570 (C11) 6.4.5 #11
    It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.
    Last edited by john.c; 12-14-2022 at 01:02 PM.
    A little inaccuracy saves tons of explanation. - H.H. Munro

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Confusion how fgets() works
    By Tripswitch in forum C Programming
    Replies: 3
    Last Post: 07-23-2014, 10:12 AM
  2. need a solution
    By igalka in forum C Programming
    Replies: 4
    Last Post: 11-20-2013, 09:22 AM
  3. Need solution....
    By enggabhinandan in forum C Programming
    Replies: 3
    Last Post: 10-22-2006, 03:08 AM
  4. anyone know the solution?
    By heeroyung in forum C Programming
    Replies: 15
    Last Post: 09-30-2005, 06:46 AM

Tags for this Thread