【问题标题】:Convert a sequence of chars into their respective int将一系列字符转换为它们各自的 int
【发布时间】:2023-03-08 15:10:01
【问题描述】:

我正在尝试用 C 语言编写一个程序,用户输入如下:“一百九十九”,对于三位数字(直到一百),输出将是 199。
但我只有这个可以从 1 到 9 转换,我不知道如何实现更大的数字。

#include <stdio.h>
#include <string.h>
 int main() {
     char numbers[10][10] = {"zero", "one" , "two", "three","four",  "five", "six", "seven","eight", "nine"};
        char input[100], word[10], *ptr, *tmp;
        int i, len, value;
        int values[9];
        /* get the number in words from user */
        printf("Enter number in word:\n");
        fgets(input, 100, stdin);
        input[strlen(input) - 1] = '\0';
        tmp = input;
        while (1) {
        /* move pointer to the space to extract word by word */
        ptr = strchr(tmp, ' ');
        if (ptr != NULL) {
            len = ptr - tmp;
            strncpy(word, tmp, len);
            word[len] = '\0';
            tmp = ptr + 1;
            } else {
                    /* last word in the given string */
                    len = strlen(tmp);
                    strncpy(word, tmp, len);
                    word[len] = '\0';
                        }
                     for (i = 0; i < 10; i++) {
                     /* word to number conversion */
                    if (strcasecmp(word, numbers[i]) == 0) {
                        value = (value * 10) + i;
                        break;
                        }
                    }

                    if (!ptr)
                        break;
                     }
        /* print the number */
        printf("Value in number is %d\n", value);
        int iN = 9;
        int arr[iN];
        while (iN--) {
         arr[iN]=value%10;
         value/=10;
        }
        printf("Value: %i", arr[0]);
        return 0;

}

【问题讨论】:

  • 我猜你必须编写一个编译器来解决这个问题,我想你可以用一个 c 程序来做这个,但这需要你一些时间。
  • 您的输入总是三位数还是您也需要支持两位数?您需要支持的最小和最大数字是多少?
  • @JVMATL Off-by-1。你的评论是关于input[strlen(input) - 0] = '\0';。 OP 正在使用input[strlen(input) - 1] = '\0'; 删除'\n',它是黑客可利用的,因为input[0] 可能为0。
  • len = ptr - tmp; strncpy(word, tmp, len); word[len] = '\0'; 是 UB,输入类似于 "abcdefghij"。希望您的用户只输入预期的输入。

标签: c string


【解决方案1】:

以下函数分析下一个标记,将其转换为 int 并跳过它。通过重复调用该函数,您可以解析任何数字。它是荷兰语,但意思应该很清楚:

static int lookupnum(const char *s, const char **s2, long *num)
{
    long t;

    if (strncmp(s, "nul", 3)==0)
    {
        *num= 0; *s2= s+3; return(TRUE);
    }
    else if (t=(strncmp(s, "en",      2)==0?s+=2,0:     // "and"
                strncmp(s, "één",     3)==0?s+=3,1:     // numbers
                strncmp(s, "eén",     3)==0?s+=3,1:
                strncmp(s, "een",     3)==0?s+=3,1:
                strncmp(s, "twee",    4)==0?s+=4,2:
                strncmp(s, "drie",    4)==0?s+=4,3:
                strncmp(s, "vier",    4)==0?s+=4,4:
                strncmp(s, "vijf",    4)==0?s+=4,5:
                strncmp(s, "zes",     3)==0?s+=3,6:
                strncmp(s, "zeven",   5)==0?s+=5,7:
                strncmp(s, "acht",    4)==0?s+=4,8:
                strncmp(s, "negen",   5)==0?s+=5,9:
                strncmp(s, "tien",    4)==0?s+=4,10:
                strncmp(s, "elf",     3)==0?s+=3,11:
                strncmp(s, "twaalf",  6)==0?s+=6,12:
                strncmp(s, "dertien", 7)==0?s+=7,13:
                strncmp(s, "veertien",8)==0?s+=8,14:
                strncmp(s, "twintig", 7)==0?s+=7,20:
                strncmp(s, "dertig",  6)==0?s+=6,30:
                strncmp(s, "veertig", 7)==0?s+=7,40:
                strncmp(s, "vijftig", 7)==0?s+=7,50:
                strncmp(s, "zestig",  6)==0?s+=6,60:
                strncmp(s, "zeventig",8)==0?s+=8,70:
                strncmp(s, "tachtig", 7)==0?s+=7,80:
                strncmp(s, "negentig",8)==0?s+=8,90:
                strncmp(s, "honderd", 7)==0?s+=7,100:
                strncmp(s, "duizend", 7)==0?s+=7,1000:
                strncmp(s, "miljoen", 7)==0?s+=7,1000000:
                strncmp(s, "miljard", 7)==0?s+=7,1000000000:0))
    {
        *num= t;
        *s2 = s;
        return(TRUE);    // return success
    }
    else
        return(FALSE);   // return error
}

示例:“driehonderdeenendertigduizendzeshondertweeentwintig”

或者:“六百二万四百二十”(英语中需要管理空格:任何较大的数字跟在较小的数字后面似乎都意味着乘?)

【讨论】:

    【解决方案2】:

    解决此问题的一种方法是将您的输入拆分为标记,并以相反的顺序解析每个标记并累积结果。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define MAX_NUM_WORDS   10
    #define MAX_INPUT_LEN   128
    #define ARRAY_SIZE(a)   (sizeof(a) / sizeof(a[0]))
    
    enum digit_state {
        UNITS,
        TENS,
        HUNDREDS,
        MAX_STATE
    };
    
    int get_numerical_value(const char **array, unsigned int length, char *token)
    {
        int i;
        int val = -1;
    
        for (i = 0; i < length; ++i) {
            if (!strcmp(array[i], token)) {
                val = i;
                break;
            }
        }
        return val;
    }
    
    unsigned int string2num(char *str)
    {
        int i;
        int n;
        int num_words;
        unsigned int result;
        unsigned int state;
        char *token;
        char *words[MAX_NUM_WORDS];
        char input[MAX_INPUT_LEN];
        const char *units[] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
        const char *tens[] = {"zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
    
        // save input
        memset(input, 0, MAX_INPUT_LEN);
        strncpy(input, str, strlen(str));
    
        // get each token, allocate memory and save them in an array
        num_words = 0;
        token = strtok(input, " ");
        while (token) {
            int len = strlen(token) + 1;
    
            words[num_words] = malloc(len);
            memset(words[num_words], 0, len);
    
            strncpy(words[num_words], token, len);
            token = strtok(NULL, " ");
            num_words++;
        }
    
        result = 0;
        state = UNITS;
        n = num_words;
    
        // process each token in the reverse order
        while (n--) {
            int val;
    
            if (state == UNITS) {
                val = get_numerical_value(units, ARRAY_SIZE(units), words[n]);
                if (val > 0)
                    result += val;
                else
                    // units digit missing so ignore this word
                    ++n;
    
                state++;
            } else if (state == TENS) {
                val = get_numerical_value(tens, ARRAY_SIZE(tens), words[n]);
                if (val > 0)
                    result += val*10;
                else
                    ++n;    // tens digit missing so ignore this word
    
                state++;
            } else if (state == HUNDREDS) {
                val = 0;
    
                if (!strcmp(words[n], "hundred"))
                    val = get_numerical_value(units, ARRAY_SIZE(units), words[--n]);
    
                result += val*100;
                state++;
            } else if (state == MAX_STATE) {
                break;
            }
        }
    
        while (num_words--)
            free(words[num_words]);
    
        return result;
    }
    
    
    int main(void)
    {
        int i;
        char *input[] = {
            "one hundred fifty four",
            "two hundred thirty",
            "eighty one",
            "five",
            "zero",
            "forty",
        };
    
        for (i = 0; i < ARRAY_SIZE(input); ++i) {
            unsigned int val = string2num(input[i]);
            printf("%s: %u\n", input[i], val);
        }
    }
    

    这是一般的想法,您可以进一步改进它,并根据您需要处理所有极端情况的输入。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-04
      • 1970-01-01
      • 1970-01-01
      • 2012-10-13
      • 2016-04-14
      • 2014-11-15
      • 2014-06-05
      相关资源
      最近更新 更多