你可以在这个练习中学到很多东西。缺少哈希表的最佳解决方案是使用stuct 来形成对,正如 Gene 在他的回答中所显示的那样。任何时候你需要协调不同类型的不相关值,你应该考虑struct。
但是,根据您的问题,尚不清楚您是否可以使用struct 来解决您的问题。如果不是,那么将不同类型的值关联起来的一种开始方式是简单地使用两个数组,其中键/值关联由 数组索引 提供。
正如我在对您问题的评论中提到的,您可以轻松地将您的键映射到 指针数组,例如:
char *arr[] = { "A", "A#", "B", "Bb", "C", "C#", "D", /* array of pointers */
"D#", "E", "F", "F#", "G", "G#" };
然后,您可以将值保存在具有相同数量元素的单独整数数组中,其中键 "A"(例如 0)的索引对应于值数组中的关联值(例如 values[0] = 10;)。这提供了"A" 到10 的简单映射。
然后给定您的指针数组和'key',然后您可以遍历您的数组,尝试将key 与每个字符串匹配。当在 index 找到匹配项时,您的关联键是 values[index];。
将它们放在一个简单的函数中,该函数循环遍历指针数组(下面的s)中的每个'n' 字符串以找到提供的key 并在成功时返回索引,或者-1 如果键-未找到,您可以执行以下操作:
/* locate index in 's' associated with 'key'.
* for 'n' keys in 's' return 'index' of matching 'key',
* otherwise return -1 if key not found.
*/
int getvalue (char **s, char *key, int n)
{
for (int i = 0; i < n; i++) { /* loop over all keys */
int found = 1; /* flag for key found */
for (int j = 0; key[j]; j++) { /* loop over all chars in key */
if (key[j] != s[i][j]) { /* if key doesn't match s[i] */
found = 0; /* set not found, break */
break;
}
}
if (found) /* if all chars in key match s[i] */
return i; /* return index of matching key */
}
return -1;
}
(注意:你可以用strcmp替换内循环,但不知道你是否有sting.h中的函数可用,一个简单的循环key中的字符就可以了每次。但是,如果您确实有string.h 可用,那么strcmp 将比滚动您自己的要好得多。您甚至可以使用strncmp (key, s[i], KEYSIZE) 将大缓冲区中的比较限制为仅感兴趣的字符)
将所有部分放在一个简短的示例中,该示例简单地将值随机分配给0 -> No. keys - 1 数量范围内的每个键,并让用户输入一个键以获取相关值直到@987654346输入@ 或用户使用手动生成的EOF 取消输入(例如Linux 上的Ctrl+d 或windoze 上的Ctrl+z - 如果启用了旧模式),您可以执行以下操作:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
enum { KEYSZ = 2, BUFSZ = 256 }; /* if you need a constant, define it */
/* simply print of all mappings */
void prnmapping (char **s, int *a, int n)
{
for (int i = 0; i < n; i++)
printf (" %-2s : %2d\n", s[i], a[i]);
}
/* locate index in 's' associated with 'key'.
* for 'n' keys in 's' return 'index' of matching 'key',
* otherwise return -1 if key not found.
*/
int getvalue (char **s, char *key, int n)
{
for (int i = 0; i < n; i++) { /* loop over all keys */
int found = 1; /* flag for key found */
for (int j = 0; key[j]; j++) { /* loop over all chars in key */
if (key[j] != s[i][j]) { /* if key doesn't match s[i] */
found = 0; /* set not found, break */
break;
}
}
if (found) /* if all chars in key match s[i] */
return i; /* return index of matching key */
}
return -1;
}
int main (void) {
char *arr[] = { "A", "A#", "B", "Bb", "C", "C#", "D", /*array of pointers*/
"D#", "E", "F", "F#", "G", "G#" };
int nelem = sizeof arr / sizeof *arr, /* number of elements */
values[nelem]; /* VLA for values */
srand (time (NULL)); /* initialize random seed */
for (int i = 0; i < nelem; i++) /* initialize values array */
values[i] = rand() % nelem;
printf ("initial string mappings:\n"); /* just dump initial mappings */
prnmapping (arr, values, nelem);
putchar ('\n');
for (;;) { /* loop continually prompting for key input until 'quit' */
char buf[BUFSZ] = "", /* buffer for line */
key[KEYSZ + 1] = ""; /* buffer for key (can just use buf) */
int index = 0; /* int to hold index matching key */
size_t len = 0; /* length of input string */
printf ("enter key ('quit' to exit): "); /* prompt */
if (fgets (buf, BUFSZ, stdin) == NULL) { /* catch manual EOF */
printf ("user canceled input.\n");
break;
}
if ((len = strlen (buf)) <= 1) { /* continue if empty line */
fprintf (stderr, "error: insufficient input.\n");
continue;
}
if (buf[len - 1] == '\n') /* check buf for trailing '\n' */
buf[--len] = 0; /* overwrite with nul-terminating char */
else { /* otherwise input equals or exceeds buffer length */
fprintf (stderr, "error: input exceeds %d chars.\n", BUFSZ - 2);
break;
}
if (strcmp (buf, "quit") == 0) /* compare for 'quit' */
break;
strncpy (key, buf, KEYSZ); /* copy KEYSZ chars from buf to key */
key[len] = 0; /* nul-terminate key (already done by initialization) */
if ((index = getvalue (arr, key, nelem)) == -1) /* key not found */
fprintf (stderr, "error: key not found.\n");
else /* success - key found, output associated value */
printf (" key: '%s' - value: %d\n", key, values[index]);
}
return 0;
}
(注意: 提供了合理的错误处理。无论您使用哪种方式获取用户输入(尽管我们鼓励您使用 fgets 或 POSIX getline 而不是 scanf对于scanf) 中的许多陷阱,您必须验证所有输入。这意味着检查您使用的任何输入函数的返回——至少,并通过生成EOF 来处理用户取消输入)
使用/输出示例
$ ./bin/array_map_values
initial string mappings:
A : 4
A# : 4
B : 1
Bb : 7
C : 1
C# : 11
D : 8
D# : 3
E : 4
F : 2
F# : 6
G : 8
G# : 10
enter key ('quit' to exit): A
key: 'A' - value: 4
enter key ('quit' to exit): A#
key: 'A#' - value: 4
enter key ('quit' to exit): D
key: 'D' - value: 8
enter key ('quit' to exit): D#
key: 'D#' - value: 3
enter key ('quit' to exit): G#
key: 'G#' - value: 10
enter key ('quit' to exit): g@
error: key not found.
enter key ('quit' to exit): B
key: 'B' - value: 1
enter key ('quit' to exit): quit
查看一下,如果您还有其他问题,请告诉我。正如我在开始时所说,您可以在此练习中包含大量学习内容。