字符串可以用作数组索引吗?

时间:2009-01-06 11:53:12

标签: c arrays associative-array

字符串可以用作C?

中的数组索引

例: 字符串对应的值 “ONE”1 “两个”2 “五”5 “十”10

当上面列表中的字符串传递给函数时,该函数必须返回上面指示的相应值。可以通过将字符串声明为索引

来声明一个常量数组来实现
int *x;
x["ONE"]  = 1;
x["TWO"]  = 2;
x["FIVE"] = 5;
x["TEN"]  = 5;

return x["string received by the function"];

上述逻辑无法按预期工作;是否有一种解决方法来实现上述逻辑,以便有一个字符串索引数组?

8 个答案:

答案 0 :(得分:17)

它可能会编译,但它不起作用。

目前还不完全清楚你要实现的目标。我想你想要associative array,在这种情况下你应该找到一个库实现。

如果您正在寻找更像enumerated type的内容,并且可以依赖C89,请查看以下内容:

enum cardsuit {
   CLUBS,
   DIAMONDS,
   HEARTS,
   SPADES
};

如果您不能依赖C89,那么您应该尝试一些typedef技巧。

答案 1 :(得分:10)

对于你应该做的事情还有其他很好的答案,所以我想我会解释你在做什么以及为什么它在编译而不起作用。

在C中,通过使用数组或指针以及某种整数来完成数组引用。 (在x [1]中,x是数组,1是整数)。只要您使用某种整体类型,它就会按预期工作。

假设你有一些不是整数的东西。在这种情况下,C实现将查看它是否可以将其转换为适当的类型,因此您最终得到数组和整数。这样的情况会让你遇到麻烦(在C ++中稍微复杂一点的版本会让经验丰富的人感到困惑)。

在C中,像“one”这样的文字字符串是const char *类型,意味着指向您无法更改的字符。实际值是字符串实际驻留在内存中的内存地址。通常情况下,你不会注意这个指针值,看看字符串值,但这里有一个问题。

在C中,任何数据指针都可以转换为某种整数,并且会自动转换。因此,你有一个像“one”这样的字符串,它的值是代表内存地址的任何数字。在C期望某种整数的情况下使用它,它将被转换为某个整数值或其他。

因此,这就是x [“ONE”]正在发生的事情。 C系统必须将字符串“ONE”放在内存中的哪个位置,并不重要。它很可能是一个内存相当大的地方,很可能是数十亿。当它看到x [“ONE”]时,它会尝试将该值转换为整数,并将其用作下标。因此,您尝试远远超出其范围访问数组x,这导致了问题。要么你正在尝试使用你不允许使用的内存,而系统只是阻止你,或者你正在捣乱你应该独自留下的一大块内存,而且它可能会以某种神秘的方式失败。 / p>

答案 2 :(得分:3)

您需要编写一个将字符串映射到整数的函数,或者使用整个枚举(然后可能是将枚举值映射到字符串的函数)。

通常,后者更好:传递整数,因此实现不依赖于可能在表示中使用的字符串的细节。例如,考虑如何管理本地化(翻译),如果你需要让那些用不同语言的人认为这些字符串是可口的。

答案 3 :(得分:3)

您可以使用bsearch()提供的函数stdlib.h轻松构建查找表。一个工作的例子就是这样:

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

#define count(ARRAY) (sizeof(ARRAY)/sizeof(*ARRAY))

struct item
{
    const char * name;
    int value;
};

static _Bool sorted;

static struct item items[] =
{
    { "one", 1 },
    { "two", 2 },
    { "three", 3 },
    { "ten", 10 }
};

static int compare(const void * p1, const void * p2)
{
    return strcmp(*((const char **)p1), *((const char **)p2));
}

int get(const char * name)
{
    if(!sorted)
    {
        qsort(items, count(items), sizeof(*items), compare);
        sorted = 1;
    }

    struct item * item = bsearch(&name, items, count(items), sizeof(*items),
        compare);

    return item ? item->value : 0;
}

int main(int argc, char ** argv)
{
    int i;
    for(i = 1; i < argc; ++i)
        printf("%i\n", get(argv[i]));

    return 0;
}

答案 4 :(得分:1)

你正在寻找的东西可能相当于一个关联数组,在C语言中不能提供相同的语法糖,但是没有一些愚蠢的结果。

但是,如果您的数据符合密钥,则可以提供的是散列图 - &gt;价值对。您需要的是适当的哈希函数。

这里有一个很好的简单哈希表示例:

http://www.cl.cam.ac.uk/~cwc22/hashtable/

答案 5 :(得分:0)

如前所述,您需要一个关联数组或哈希映射或等价物。这种代码的一个可能来源是Hanson的“C Interfaces and Implementations”(Google Code处的代码 - 在使用之前仔细检查许可条款等。)

答案 6 :(得分:0)

这是一个旧线程,但我认为这对于那些寻找实现的人来说可能仍然有用。它不需要太多代码; Hank Gay建议我没有任何额外的库,我做了大约100行。我把它称为字典,因为它与python数据类型相似(有点)。这是代码:

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

typedef struct hollow_list hollow_list;

struct hollow_list{
    unsigned int size;
    void *value;
    bool *written;
    hollow_list *children;
};

//Creates a hollow list and allocates all of the needed memory
hollow_list hollow_list_create(unsigned int size){
    hollow_list output;
    output = (hollow_list) {.size = size, .value = (void *) 0, .written = calloc(size, sizeof(bool)), .children = calloc(size, sizeof(hollow_list))};
    return output;
}

//Frees all memory of associated with a hollow list and its children
void hollow_list_free(hollow_list *l, bool free_values){
    int i;
    for(i = 0; i < l->size; i++){
        hollow_list_free(l->children + i, free_values);
    }
    if(free_values){
        free(l->value);
    }
    free(l);
}

//Reads from the hollow list and returns a pointer to the item's data
void *hollow_list_read(hollow_list *l, unsigned int index){
    if(index == 0){
        return l->value;
    }
    unsigned int bit_checker;
    bit_checker = 1<<(l->size - 1);
    int i;
    for(i = 0; i < l->size; i++){
        if(bit_checker & index){
            if(l->written[i] == true){
                return hollow_list_read(l->children + i, bit_checker ^ index);
            } else {
                return (void *) 0;
            }
        }
        bit_checker >>= 1;
    }
}

//Writes to the hollow list, allocating memory only as it needs
void hollow_list_write(hollow_list *l, unsigned int index, void *value){
    if(index == 0){
        l->value = value;
    } else {
        unsigned int bit_checker;
        bit_checker = 1<<(l->size - 1);
        int i;
        for(i = 0; i < l->size; i++){
            if(bit_checker & index){
                if(!l->written[i]){
                    l->children[i] = hollow_list_create(l->size - i - 1);
                    l->written[i] = true;
                }
                hollow_list_write(l->children + i, bit_checker ^ index, value);
                break;
            }
            bit_checker >>= 1;
        }
    }
}

typedef struct dictionary dictionary;

struct dictionary{
    void *value;
    hollow_list *child;
};

dictionary dictionary_create(){
    dictionary output;
    output.child = malloc(sizeof(hollow_list));
    *output.child = hollow_list_create(8);
    output.value = (void *) 0;
    return output;
}

void dictionary_write(dictionary *dict, char *index, unsigned int strlen, void *value){
    void *hollow_list_value;
    dictionary *new_dict;
    int i;
    for(i = 0; i < strlen; i++){
        hollow_list_value = hollow_list_read(dict->child, (int) index[i]);
        if(hollow_list_value == (void *) 0){
            new_dict = malloc(sizeof(dictionary));
            *new_dict = dictionary_create();
            hollow_list_write(dict->child, (int) index[i], new_dict);
            dict = new_dict;
        } else {
            dict = (dictionary *) hollow_list_value;
        }
    }
    dict->value = value;
}

void *dictionary_read(dictionary *dict, char *index, unsigned int strlen){
    void *hollow_list_value;
    dictionary *new_dict;
    int i;
    for(i = 0; i < strlen; i++){
        hollow_list_value = hollow_list_read(dict->child, (int) index[i]);
        if(hollow_list_value == (void *) 0){
            return hollow_list_value;
        } else {
            dict = (dictionary *) hollow_list_value;
        }
    }
    return dict->value;
}

int main(){
    char index0[] = "hello, this is a test";
    char index1[] = "hello, this is also a test";
    char index2[] = "hello world";
    char index3[] = "hi there!";
    char index4[] = "this is something";
    char index5[] = "hi there";

    int item0 = 0;
    int item1 = 1;
    int item2 = 2;
    int item3 = 3;
    int item4 = 4;

    dictionary d;
    d = dictionary_create();
    dictionary_write(&d, index0, 21, &item0);
    dictionary_write(&d, index1, 26, &item1);
    dictionary_write(&d, index2, 11, &item2);
    dictionary_write(&d, index3, 13, &item3);
    dictionary_write(&d, index4, 17, &item4);

    printf("%d\n", *((int *) dictionary_read(&d, index0, 21)));
    printf("%d\n", *((int *) dictionary_read(&d, index1, 26)));
    printf("%d\n", *((int *) dictionary_read(&d, index2, 11)));
    printf("%d\n", *((int *) dictionary_read(&d, index3, 13)));
    printf("%d\n", *((int *) dictionary_read(&d, index4, 17)));
    printf("%d\n", ((int) dictionary_read(&d, index5, 8)));
}

不幸的是你无法复制list [x]语法,但这是我提出的最佳选择。

答案 7 :(得分:-2)

在“普通C”中,您可以模仿使用字符串作为索引,但不能以您想要的方式使用QUITE。但是,这样做很少有用,而且大多数都是使代码不可读的好方法。您似乎想要的是能够将字符串键用于字典(或“散列表”,如果您愿意)并且C中没有内置数据结构。确切的设计将取决于您的内容想要(事实上,如果这是家庭作业的一部分,你可能甚至不需要使用完整的哈希表实现,但可能会使用性能较低的静态编码)。

在a [b]构造的“索引位置”中使用字符串(OK,char数组)的示例:

int main (void)
{
  char *str = "This is a test string";
  int x;

  for (x=0; x < 12; x += 3)
    putchar(x[str]);

  printf("\n");

  return 0;
}

据我所知,上面是合法的C,具有明确定义的输出(字符串“Tss ssi”)。它依赖于a [b]被定义为与*(a + b)相同的事实。