【问题标题】:In plain C, how to do you make the equivalent of a "map"?在纯 C 中,如何制作相当于“地图”的内容?
【发布时间】:2015-04-27 01:58:36
【问题描述】:

所以我试图完全从头开始制作一个程序(不包括库),我有一个非常丑陋的函数:

int parseUnsignedInt ( char * ch, unsigned int * ui )
{
/* Starting at character ch, reads the unsigned int into the
       variable ui, returns the number of characters read.
*/
    ui = 0; // unsigned integer into which the string representation is read 
    int m = 1; // multiplier
    int ncp = 0; // # of characters parsed
    while (*ch)
    {
        bool chid = false; // ch is a decimal
        for (int k = 0; k < decmapLength; ++k)
        {
            if (decmap[k].cval == *ch)
            {
                ui += decmap[k].ival * m;
                m *= 10;
                chid = true;
                break;
            }
        }
        if (!chid) break;
        ++ncp;
        ++ch;
    }
    return ncp;
}

它的丑陋部分源于我需要一种方法将characters 与integers ('0'->0, '1'->1, ..., '9'- >9) 并创建一个数组或结构体

typedef struct icpair
{
    char cval;
    int ival;
} icpair;

icpair decmap [10] = {{'0',0}, {'1',1}, {'2',2}, {'3',3}, {'4',4}, {'5',5}, {'6',6}, {'7',7}, {'8',8}, {'9',9}};
int decmapLength = sizeof(decmap)/sizeof(icpair);

为此目的。但是,如果在纯 C 中有更好的方法来执行此操作,则查找一个值(如果它甚至存在)会导致难看的行数可以被压缩。我也希望这是可靠的,所以没有 ASCII 值减法之类的'9'-'ch'。这在纯 C 中是否可行,如果可以,它是如何实现的?

【问题讨论】:

  • ui = 0 替换为*ui = 0,将ui += decmap[k].ival * m 替换为*ui += decmap[k].ival * m。否则不返回任何内容
  • 为什么没有 ASCII 减法? *ch - '0' 正是您要找的。​​span>
  • @JuanLopes 这是否适用于可以编译该程序的所有可能系统?
  • C 规范保证ch - '0' 工作,无论使用哪个字符集,只要ch 包含一个从0 到9 的数字。
  • 在内部循环中,它可能是:*ui *= 10;,后跟*ui += decmap[k].ival;,否则“1000”将计算为1。我认为m 没有用。

标签: c dictionary data-structures


【解决方案1】:

C 中的简单地图 API 可能如下所示:

Map * map_create(void);
void map_insert(Map * map, char key, int value);
int map_find(Map * map, char key);
void map_destroy(Map * map);

然后您就可以通过map_find(map, '0') 来获取整数值,如果找不到则返回-1 的语义。

根据您的需要,可以使用多种不同的数据结构来实现这一点。如果您不关心维护订单,则哈希表可能是最合适的。例如,如果您确实需要根据键维护顺序,二叉树可能是一个更好的主意(可能是红黑树)。

您可以修改 API 以将 void * 用作键和值以稍微概括它(在没有泛型的情况下,C 缺乏)。会增加复杂性,例如为哈希表提供哈希函数或为二叉树提供比较函数。

也就是说,执行*ch - '0' 是安全的,并且会正常工作。

【讨论】:

    【解决方案2】:

    如果您想将任何 10 个随机字符映射到0..9,则不需要单独的结构元素ival——“自然顺序”已经立即索引正确的数字.因此,您可以使用长度为 10 个随机字符的单个 char 数组作为查找。

    如果此数组中的字符连续递增 1,则根本不需要该数组。在这种情况下,您可以减去 first 代码,测试结果是否在 0 和 9 之间,表示成功,否则拒绝该字符。

    这适用于 C 中的数字集,因为 C 的规范需要它

    在源和执行基本字符集中,上述列表中0之后的每个字符的值都应比前一个字符的值大一个。 (5.2.1 字符集ISO/IEC 9899:201x Normative Draft 2011 (PDF))

    因此,要获得任何数字的数值,character - '0'总是为真。

    附带说明,这不是为A..Za..z 范围定义的。这意味着如果您将'A' 视为0,则不能保证'J'-'A' == 9。为此,您需要再次使用简单的查找字符数组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-03
      • 1970-01-01
      • 2016-02-11
      • 1970-01-01
      相关资源
      最近更新 更多