将字符串转换为数字

时间:2014-01-15 04:22:57

标签: c string numbers atoi strtol

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

  • 数字并因此将其转换为有符号的int(不长)
  • 是先前在运行时定义的符号表示,并将其转换为signed 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,但将它转换回非long int似乎很乏味。我发现的简单(读取:最短)方式是使用sscanf

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

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

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

最后,是否存在模拟关联数组和/或允许我在运行时将元素推送到数组的短代码?

2 个答案:

答案 0 :(得分:1)

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

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

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

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

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

答案 1 :(得分: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应该不是上面提到的问题。