0

我正在寻找一种获取字符串并检查 3 种可能性的方法。

  • 数字,从而将其转换为有符号整数(不是长整数)
  • 是先前在运行时定义的符号表示,并将其转换为带符号的 int
  • 两者都不

“符号表示”基本上就像一个关联数组,从 0 个元素开始并随着更多符号的添加而扩展。例如,让我们说 C 有关联数组(我希望)这个 peusdocode:

symbol_array['q'] = 3;
symbol_array['five'] = 5;
symbol_array['negfive'] = -5;
symbol_array['random294'] = 28;

signed int i;
string = get_from_input();
if(!(i = convert_to_int(string))) {
    if(!(i = translate_from_symbol(string))) {
        printf("Invalid symbol or integer\n");
        exit(1);
    }
}

printf("Your number: %d\n, i);

这个想法是,如果他们输入“5”,它将通过 convert_to_int 将其转换为 5,如果他们输入“5”,它将通过 translate_from_symbol 将其转换为 5。我觉得可能最难的是,如果他们输入“random294”,它不会将其转换为 294,而是转换为 28。如果他们输入“foo”,那么它将退出(1)。

我的一般问题是:(而不是发表多个帖子)

convert_to_int我知道我不应该使用atoi时,因为它不会正确失败。有人说要使用strtol,但将其转换回非长整数似乎很乏味。我发现的最简单(阅读:最短)的方法是使用sscanf

int i;
if ((sscanf(string, "%d", &i)) == 1){
    return i;
}

然而,有些人甚至看不起这一点。如果不是 sscanf 或转换 strtol,有什么更好的方法?

其次,我怎样才能不仅返回一个整数,而且知道它是否找到了一个。例如,如果用户输入“0”,那么它将返回 0,从而在我的 if 语句中设置我的 FALSE。如果没有找到,我曾考虑使用-1,但由于我返回有符号整数,所以这也遇到了同样的问题。在 PHP 中,我知道例如strpos他们使用=== FALSE

最后,是否有任何短代码可以模拟关联数组和/或让我在运行时将元素推送到数组?

4

2 回答 2

1

首先,您可能想要修改语法并将关键字与操作数分开,即"neg five"代替"negfive". 否则,您对关键字的符号查找必须考虑每个前缀。("random294"如果您的关键字中不允许包含数字,则可能没问题。)

当然,sscanf告诉您是否在返回值中找到了小数点并将该小数点写入单独的int,这很好,但是您必须通过检查读取的字符数是否等于字符串的长度来注意尾随字符与%n格式。否则,sscanf将被5x视为合法的十进制数。strtol还返回一个指向解析十进制数后位置的指针,但它过于依赖于检查err我的口味。

使用长整数的事实strtol不应该是一个问题。如果输入不适合 int,则返回INT_MAXINT_MIN发出错误。

您还可以轻松地编写一个包装函数sscanfstrtol更好地满足您的需求。(我知道我想要一个函数,它在成功时返回 true 并通过指针参数sscanf样式存储整数,其中成功意味着:没有尾随的非数字字符。)

最后,关于关联数组:没有短代码,至少在 C 中没有。您必须实现自己的哈希映射或使用库。作为初稿,我将使用字符串的线性列表并逐个检查它们。这是一种非常幼稚的方法,但很容易实现。我假设你一开始不会有很多符号,也没有做很多检查,所以速度应该不是问题。(您可以对数组进行排序并使用二进制搜索来加快速度,但每次插入后都必须重新排序。)一旦您的程序逻辑正常工作,您就可以开始考虑哈希映射。

于 2014-01-15T07:14:24.890 回答
0

这样的事情应该做你的工作:

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

struct StringToLongLookUp {
    char *str;
    char *num;
};

struct StringToLongLookUp table[] =
{
    { "q"        ,  "3" },
    { "five"     ,  "5" },
    { "negfive"  , "-5" },
    { "random294", "28" }
};


int translate_from_symbol(char **str)
{
    int i;
    for(i = 0; i < (sizeof(table) / sizeof(struct StringToLongLookUp)); i++)
    {
        if(strcmp(*str, table[i].str) == 0)
        {                
            *str = table[i].num;
            return 1; // TRUE
        }
    }
    return 0; // FALSE
}

int main()
{

    char buf[100];
    char *in = buf;
    char *out;
    int val;

    scanf("%s", in);

    translate_from_symbol(&in);

    val = strtol(in, &out, 10);

    if (in != out)
    {            
        printf("\nValue = %d\n", val);
    }
    else
    {
        printf("\nValue Invalid\n");
    }
}

当然,您会得到很长的时间,但是如上所述将其转换为 int 应该不是问题。

于 2014-01-21T06:36:46.493 回答