0

In this code, I am getting an input from the user to enter a number(s). After giving some number(s), the desired message will be printed according to that particular number.

My question is that if the numbers are not exactly sure as in this case then how can I put if-statement/switch in a short way. Because for example, if I entered 10,000 then I have to write if-statements/switch 10,000 times and this is not a good way.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
  int i;
  printf("Enter a number: ");
  // fgets(i, sizeof(i), stdin);
  scanf("%d", &i);

  if(i == 1){
    printf("one");
  }
  else if(i == 2){
    printf("two");
  }
  else{
    printf("%d\n", i);
  }

  return 0;
}
Sky wifibrand
  • 109
  • 1
  • 6
  • What about a `switch`? You can have multiple `case:` labels for each 'block' or, if appropriate, you can switch on a 'function' of `i` (like `i / 10` or `i % 10`). Can you provide a more illustrative example? – Adrian Mole Feb 23 '21 at 16:21
  • 2
    One thing you could try is to add all your messages to an array, and then print messages[i]. Note that this only works if you have i from 0 - 10000 – Chrysophylaxs Feb 23 '21 at 16:22
  • Surely array or some other data structure mapping numbers to strings is the right way for the usecase described. – Eugene Sh. Feb 23 '21 at 16:24
  • 2
    Is this a ["print a number as words"](https://stackoverflow.com/questions/1720049/print-number-in-words) assignment? – Fred Larson Feb 23 '21 at 16:25
  • I would guess the purpose of this exercise is *not* to build a 10,000 entry lookup table, but instead to have a 10 entry lookup table and some logic. eg, given `983`, use the lookup table to get the string "nine", then another table to get "hundred". Probably a different lut for "eighty" (although you good print "eight tens" or similar), and then lookup the "three". – William Pursell Feb 23 '21 at 16:29

4 Answers4

1

You need to decompose the number in powers of ten and print it. So, for example, for 3452 you will need to know is "3000" "400" "50" and "2".

You need to be careful with special cases from 11 to 19, because it is not "one and ten" but "eleven" all the way to 19, "nineteen", then it is regular.

#include <stdio.h>
#include <stdint.h>
#include <string.h>


int main(int argc, char**argv)
{
  uint16_t input_num=0;
  uint8_t units,tens,hundreds,thousands;
  char* unitsStr[]={"","one","two","three","four","five","six","seven","eight","nine","ten"};
  char* tensStr[]={"","ten","twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"};
  char* specialCaseStr[]={"","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eightteen","nineteen"};
  char finalString[128]={0};
  char tempStr[64]={0};

  printf("Please enter the number: ");
  scanf("%hd",&input_num);
  printf("\r\nEntered %d\r\n",input_num);

  units =      input_num % 10;
  tens =      (input_num / 10) % 10;
  hundreds =  (input_num / 100) % 10;
  thousands = (input_num / 1000) % 10;

  if(thousands > 0)
  {
    sprintf(tempStr,"%s thousand ",unitsStr[thousands]);
    strcat(finalString,tempStr);
  }

  if(hundreds > 0)
  {
    sprintf(tempStr,"%s hundred ",unitsStr[hundreds]);
    strcat(finalString,tempStr);
  }

  if((units+(tens*10)) >= 11 &&  (units+(tens*10)) <= 19)
  {
    sprintf(tempStr,"%s",specialCaseStr[units]);
    strcat(finalString,tempStr);
  }
  else
  {
    if(tens > 0)
    {
      sprintf(tempStr,"%s ",tensStr[hundreds]);
      strcat(finalString,tempStr);
    }
    if(units > 0)
    {
      sprintf(tempStr,"%s ",unitsStr[units]);
      strcat(finalString,tempStr);
    }
  }

  printf("%s\r\n",finalString);

  return 0;

}

It could be further optimized for memory usage, that is left as an exercise.

Pedro Perez
  • 330
  • 1
  • 2
  • 11
0

You could use an array to store your strings, but you have to make sure the chosen value does not go beyond the numbers of elements in your array :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(){
  const char *numbers[] = {"zero", "one", "two"};

  int i;
  printf("Enter a number: ");
  // fgets(i, sizeof(i), stdin);
  scanf("%d", &i);

  if(i >= 0 && i < sizeof numbers / sizeof *numbers){
    printf("%s\n", numbers[i]);
  }
  else{
    printf("%d\n", i);
  }

  return 0;
}
ShellCode
  • 1,072
  • 8
  • 17
  • But I am not sure about the limit of numbers. I just said that if I entered 10,000. It could be more or less than that. Then how can I set the if-statement according to that? – Sky wifibrand Feb 23 '21 at 16:45
  • Oh ! Then you have to decompose the number into digits and build a string based on the value and the position of each digit. But the array idea remains the same. You create an array going from 1 to 9 and an other one containing "hundred" "thousand". It will be easier to do this using fgets. – ShellCode Feb 23 '21 at 16:51
0

Couple of things you could do, first is an array of strings, arranged the right way, like so:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i;
    char *numbers[] = {"one", "two", "three"}; /* fill more numbers */

    printf("Enter a number: ");

    if (scanf("%d", &i) != 1)
    {
        exit(EXIT_FAILURE);
    }

    if (i - 1 >= 0)
    {
        puts(numbers[i - 1]);
    }
    else
    {
        fprintf(stderr, "Invalid input\n");
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}

I guess you could also have one conditional expression as well :

#include <stdio.h>
#include <stdlib.h>

#define MAX_LEN 1000

int main()
{
    int i;

    printf("Enter a number: ");

    if (scanf("%d", &i) != 1)
    {
        exit(EXIT_FAILURE);
    }

    char buffer[MAX_LEN];

    snprintf(buffer,MAX_LEN,"%d",i); /* converting the int read into a string */

    printf("%s",(i == 1 ? "one" : i == 2 ? "two" : buffer));

    exit(EXIT_SUCCESS);
}
alex01011
  • 1,670
  • 2
  • 5
  • 17
  • But I am not sure about the limit of numbers. I just said that if I entered **10,000**. It could be more or less than that. Then how can I set the `if-statement` according to that? – Sky wifibrand Feb 23 '21 at 16:39
0

Here's a version that can take 64 bit numbers:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int opt_d;
int opt_f;

typedef long long val_t;

#define ARRAY_SIZE(_arr) \
    sizeof(_arr) / sizeof(_arr[0])

char *ones[] = {
    NULL,
    "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"
};

char *tens[] = {
    NULL,
    "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty",
    "ninety"
};

char *teens[] = {
    NULL,
#if 0
    "ten",
#endif
    "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen",
    "seventeen", "eighteen", "nineteen"
};

const char *places[] = {
    //NULL,
    //NULL,
#if 0
    "hundred",
#else
    NULL,
#endif
    "thousand",
    "million",
    "trillion",
    "quadrillion",
#if 0
    "quintillion",
#endif
#if 0
    "sextillion", "septillion", "octillion", "nonillion", "decillion",
    "undecillion", "duodecillion", "tredecillion", "quatttuor-decillion",
    "quindecillion", "sexdecillion", "septen-decillion", "octodecillion"
#endif
};

#define BUFWID  1000

char *odst;
char obuf[BUFWID];
const char *curplace;

#if defined(DEBUG) || defined(_USE_ZPRT_)
#define dbgprt(_fmt...) \
    do { \
        if (opt_d) \
            printf(_fmt); \
    } while (0)
#else
#define dbgprt(_fmt...) \
    do { } while (0)
#endif

val_t
ipow(int pow)
{
    val_t acc = 1;

    for (;  pow > 0;  --pow)
        acc *= 1000;

    return acc;
}

#define BUFMAX  20
char *
strbuf(void)
{
    static int bufidx = 0;
    static char bufpool[BUFMAX][BUFWID];

    char *buf = bufpool[bufidx];
    bufidx += 1;
    bufidx %= BUFMAX;

    *buf = 0;

    return buf;
}

const char *
show(val_t val)
{
    char *buf = strbuf();
    char tmp[100];

    int len = sprintf(tmp,"%lld",val);
    int off = len % 3;

    char *bp = buf;
    for (char *src = tmp;  *src != 0;  ++src, --off) {
        if (off == 0) {
            if (src > tmp)
                *bp++ = ',';
            off = 3;
        }
        *bp++ = *src;
    }
    *bp = 0;

    return buf;
}

void
append(const char *str)
{

    if (str != NULL) {
        if (odst > obuf)
            *odst++ = ' ';
        odst += sprintf(odst,"%s",str);
    }
}

val_t
digout(val_t bigval,int div,char **str,char *midplace)
{
    val_t cur = bigval / div;

    dbgprt("digout: ENTER bigval=%s div=%d cur=%s str='%s' midplace='%s'\n",
        show(bigval),div,show(cur),str[cur],midplace);

    if (cur != 0) {
        append(str[cur]);
        append(midplace);
    }

    bigval %= div;

    dbgprt("digout: EXIT bigval=%s\n",show(bigval));

    return bigval;
}

void
group(val_t bigval,int plidx)
{
    val_t cur;

    dbgprt("group: ENTER bigval=%s plidx=%d curplace='%s'\n",
        show(bigval),plidx,curplace);

    bigval = digout(bigval,100,ones,"hundred");
    if ((bigval > 10) && (bigval < 20))
        bigval = digout(bigval - 10,1,teens,NULL);
    else {
        bigval = digout(bigval,10,tens,NULL);
        bigval = digout(bigval,1,ones,NULL);
    }
    append(curplace);

    dbgprt("group: EXIT\n");
}

void
pretty(val_t origval)
{
    char tokbuf[BUFWID];
    char *cp;
    char *bp;
    int totlen = 0;

    sprintf(tokbuf,"%s -- %s",show(origval),obuf);

    bp = tokbuf;
    while (1) {
        cp = strtok(bp," ");
        if (cp == NULL)
            break;

        int toklen = strlen(cp);

        if ((totlen + 1 + toklen) >= 72) {
            printf("\n");
            totlen = 0;
            printf("+");
            totlen += 1;
        }

        if (bp == NULL) {
            printf(" ");
            totlen += 1;
        }

        printf("%s",cp);
        totlen += toklen;

        bp = NULL;
    }

    if (totlen > 0)
        printf("\n");
}

const char *
convert(val_t origval)
{
    val_t bigval = origval;

    odst = obuf;
    *odst = 0;

    int plidx = ARRAY_SIZE(places) - 1;
    dbgprt("convert: ENTER bigval=%s plidx=%d\n",show(bigval),plidx);

    while (bigval != 0) {
        val_t div = ipow(plidx);

        val_t cur = bigval / div;
        val_t dig = cur / 1000;

        curplace = places[plidx];
        dbgprt("convert: LOOP bigval=%s plidx=%d div=%s cur=%s dig=%s curplace='%s'\n",
            show(bigval),plidx,show(div),show(cur),show(dig),curplace);

        if (cur != 0) {
            group(cur,plidx);
            dbgprt("convert: OBUF obuf='%s'\n",obuf);
        }

        bigval %= div;
        plidx -= 1;
    }

    pretty(origval);

    dbgprt("convert: EXIT obuf='%s'\n",obuf);

    return obuf;
}

int
main(int argc,char **argv)
{
    char *cp;

    --argc;
    ++argv;

    for (;  argc > 0;  --argc, ++argv) {
        cp = *argv;
        if (*cp != '-')
            break;

        cp += 2;
        switch (cp[-1]) {
        case 'd':
            opt_d = ! opt_d;
            break;

        case 'f':
            opt_f = ! opt_f;
            break;
        }
    }

    int dodiag = 1;
    for (;  argc > 0;  --argc, ++argv) {
        dodiag = 0;
        val_t val = strtoll(*argv,&cp,10);
        convert(val);
    }

    if (dodiag) {
        convert(1234);
        convert(117);
        convert(311);
        convert(412);
        convert(1234567);
        convert(12319678);
        convert(123456789);
        convert(12345678927594);
    }

    return 0;
}

Here's the program's default output:

1,234 -- one thousand two hundred thirty four
117 -- one hundred seventeen
311 -- three hundred eleven
412 -- four hundred twelve
1,234,567 -- one million two hundred thirty four thousand five hundred
+ sixty seven
12,319,678 -- twelve million three hundred nineteen thousand six
+ hundred seventy eight
123,456,789 -- one hundred twenty three million four hundred fifty six
+ thousand seven hundred eighty nine
12,345,678,927,594 -- twelve quadrillion three hundred forty five
+ trillion six hundred seventy eight million nine hundred twenty seven
+ thousand five hundred ninety four
Craig Estey
  • 30,627
  • 4
  • 24
  • 48