美元中,penny(一美分)、nickel(5美分)、dime(10美分)、quarter(25美分)、half-dollar(50美分)。 做这样一个程序:输入一个面额,输出面额对应的名称。
数据结构中有一种:散列表(hash table),很适合做这件事。比如将10作为key存入hash表中,对应的value就是dime。 但还没学,先尝试用C语言来解决。
方法一:构建两个数组,在对应的位置上有对应的值。 比如,输入10,得到在这个数组上的位置是2,那么在另一个数组位置2上可以得到dime。
#include <stdio.h>
int amount[] = {1,5,10,25,50}; //定义了一个整形数组amount,里面存储了不同面额的硬币
const char *name[] = {"penny", "nickel", "dime", "quarter", "half-dollar"}; /*定义了一个字符串指针数组name,
其中数组中的每个元素都是指向一个字符串常量的指针,这些字符串常量是用花括号括起来的一组字符串字面值。
这些字符串分别代表一些硬币的名称。
具体来说, const char *name[] 中:
- const 表示这些字符串是常量,不能被修改。
- char * 表示每个元素是一个指向字符的指针,也可以表示字符串。
- [] 表示这是一个数组,它的每个元素都是指向字符的指针。
- name 是这个数组的名称。
- = {"penny", "nickel", "dime", "quarter", "half-dollar"} 则是在初始化数组。
大括号中的每一个字符串常量依次被赋值给了数组中的元素,也就是每个指针。
因此,可以使用name[0]访问"penny",name[1]访问"nickel",以此类推。
'字符串字面值'指的是一串由双引号包围的字符序列。
在C语言中,字符串字面值的类型是const char[],意味着在程序运行时,字符串字面值的值是不可改变的。
如:"penny"就是一个字符串字面值,它的类型是const char[]。 */
int search(int key, int a[], int len) /*`search`函数用于在数组中查找一个值的位置,它接收三个参数:要查找的值 `key`、
要查找的数组 `a`、以及数组长度 `len`。函数使用循环遍历数组,如果找到了目标值,
就将其在数组中的位置作为返回值返回;否则,返回 `-1`。*/
{
int ret = -1;
for ( int i=0; i<len; i++)
{
if ( key == a[i] )
{
ret = i;
break;
}
}
return ret;
}
int main() /*`main` 函数是程序的主要入口。它首先要求用户输入一个面额,
然后调用 `search` 函数查找该面额在 `amount` 数组中的位置。如果找到了,就输出面额对应的名称;否则,输出提示信息。*/
{
int k;
printf("请输入面额:");
scanf("%d", &k);
int r = search(k, amount, sizeof(amount)/sizeof(amount[0]));
if ( r > -1 )
{
printf("%s\n", name[r]); //%s是输出字符串
} else {
printf("不在范围内\n");
}
return 0;
}
①如果直接使用char *name[] = {}; 会出现warning:deprecated conversion from string constant to 'char *' 因为char *背后的含义是:给我个字符串,我要修改它。
而理论上,我们传给函数的字面常量是没法被修改的。
所以说,比较合理的办法是把参数类型修改为const char *。
这个类型背后的含义是:给我个字符串,我只要读取它。
②割裂的两个数组对高速缓冲存储器(Cache)是不友好的。因此考虑更好的做法。
方法二:希望是一个数组,需要用到结构体,结构体数组
#include <stdio.h>
int amount[] = {1,5,10,25,50}; //定义了一个整形数组amount,里面存储了不同面额的硬币
const char *name[] = {"penny", "nickel", "dime", "quarter", "half-dollar"}; /*定义了一个常量字符指针数组name,
里面存储了对应面额硬币的名称(是字符串)。 */
struct x {
int amount;
const char *name;
} coins[] = {
{1, "penny"},
{5, "nickel"},
{10, "dime"},
{25, "quarter"},
{50, "half-dollar"}
}; /* 这段代码定义了一个结构体 `x`,其中包含两个成员:`amount` 存储货币的面值(整型),`name` 存储货币的名称(常量字符串指针)。
然后定义了一个长度为5的 `coins` 结构体数组,用于存储不同的硬币。数组元素的类型是结构体 `x`。
`coins[]` 中的初始化列表包含5个元素,每个元素都是一个结构体 `x` 类型的值,对应5种硬币(分别是1分、5分、10分、25分和50分),
并且每个结构体中的 `amount` 和 `name` 成员都用相应的值进行了初始化。
这样就可以通过数组索引的方式访问硬币数组中的元素,并获取对应的硬币面值和名称。
*/
int search(int key, int a[], int len) /*`search`函数用于在数组中查找一个值的位置,它接收三个参数:要查找的值 `key`、
要查找的数组 `a`、以及数组长度 `len`。函数使用循环遍历数组,如果找到了目标值,
就将其在数组中的位置作为返回值返回;否则,返回 `-1`。*/
{
int ret = -1;
for ( int i=0; i<len; i++)
{
if ( key == a[i] )
{
ret = i;
break;
}
}
return ret;
}
int main() /*`main` 函数是程序的主要入口。它首先要求用户输入一个面额,
然后调用 `search` 函数查找该面额在 `amount` 数组中的位置。如果找到了,就输出面额对应的名称;否则,输出提示信息。*/
{
int k;
printf("请输入面额:");
scanf("%d", &k);
for ( int i=0; i<sizeof(coins)/sizeof(coins[0]); i++ ) /* 循环的次数为`sizeof(coins)/sizeof(coins[0])`(也就是`coins`数组的元素个数),
每循环一次,`i`的值会自增1。循环体中,首先判断`k`是否等于`coins[i].amount`,如果是,就会执行输出`coins[i].name`的语句并跳出循环。
`coins`数组的类型是一个结构体数组,其中包含`name`和`amount`两个成员,`name`用于存放硬币的名字,`amount`用于存放硬币的面值。
因此,这段代码的作用是:在`coins`数组中查找面值等于`k`的硬币,并输出该硬币的名称。如果没有找到面值等于`k`的硬币,则不会有任何输出。 */
{
if ( k == coins[i].amount){
printf("%s\n", coins[i].name);
break;
}
}
return 0;
}