我需要构建一个Coin Dispenser应用程序。我已经写了提款和存款部分,但在项目库存创建中,我无法创建解决方案。项目名称应从键盘作为字符串。对应于这些项目的商品价格应从键盘上取unsigned int
s。
阵列应该是可变大小的,即VLA。我用Google搜索并发现了一些关于创建VLA的资源,我想我应该使用malloc
动态地为它们分配内存。我不能这样做,所以我基本上使用BUFSIZ
创建了有限大小的数组。
在这种情况下如何使用VLA,如何用字符串填充它们?
另外我应该防止缓冲区溢出。这将是第二种情况。
宏和代码块:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMBER_OF_COINS 5
#define ITEM_NAME_LEN 9
...
void editorMain(void)
{
printf("Please enter the number of items: ");
scanf("%u", &itemQuantity);
printf("\n\n");
char ** itemNames[BUFSIZ] = {0};
unsigned int itemPrices[BUFSIZ] = {0};
printf("Please enter the names of items: \n");
for (int i = 0; i < itemQuantity; ++i) {
printf("#%d: ", i + 1);
gets(** itemNames[i]);
puts("");
}
printf("Please enter the prices of items: \n");
for (int i = 0; i < itemQuantity; ++i) {
printf("#%d: ", i + 1);
scanf("%u", &itemPrices[i]);
puts("");
}
dispenserMain(*itemNames, itemPrices);
return;
}
程序也应该将项目名称和价格作为列表输出。函数dispenserMain
执行此操作:
void dispenserMain(char * itemNames[], unsigned int itemPrices[]) {
...
for (counterItemNames = 1; counterItemNames <= itemQuantity; ++counterItemNames) { //the for loop will print out the item name and prices with their correspondence.
printf("%10u.%14s%12.2f TL\n", counterItemNames, itemNames[counterItemNames - 1], currencyConverter(itemPrices[counterItemNames - 1]));
}
...
}
编辑(新代码):
void editorMain(void)
{
printf("Please enter the number of items: ");
scanf("%u", &itemQuantity);
printf("\n\n");
char itemNames[itemQuantity][ITEM_NAME_LEN+1];
memset(&itemNames, 0, sizeof(itemNames));
printf("Please enter the names of items: \n");
char line[ITEM_NAME_LEN+1];
for (int i = 0; i < itemQuantity; ++i) {
printf("#%d: ", i + 1);
if (! fgets(line, sizeof(line), stdin) || !line[0])
// abort...
// fgets leaves the trailing newline in the input
if (line[strlen(line)-1] == '\n') {
line[strlen(line)-1] = 0;
}
snprintf(itemNames[i], ITEM_NAME_LEN+1, "%s", line);
puts("");
}
unsigned int itemPrices[] = {0};
printf("Please enter the prices of items: \n");
for (int i = 0; i < itemQuantity; ++i) {
printf("#%d: ", i + 1);
scanf("%u", &itemPrices[i]);
puts("");
}
dispenserMain(itemNames, itemPrices);
return;
} //end globalMenuOut
输出:
Welcome to CoinedDispenser!
Author: Buğra Ekuklu
Contact: bugraekuklu [at] hotmail.de
1. Dispenser
2. Editing variables
3. Readme
Please make a choice: 2
Please enter the number of items: 3
Please enter the names of items:
#1:
#2: blabla
#3: glagla
Please enter the prices of items:
#1: 45
#2: 65
#3: 75
................... AVAILABLE ITEMS oo
# Item Name Price
= ========= ======
1.
0.45 TL
2. blabla
0.65 TL
3. glagla
0.75 TL
Enter your item selection:
分配器功能:
void dispenserMain(char (*itemNames)[ITEM_NAME_LEN+1], unsigned int itemPrices[])
{
printf("%s\n\n", " ................... AVAILABLE ITEMS oo");
printf("%10s%15s %14s\n", "#", "Item Name", "Price");
printf("%10s%15s %14s\n", "=", "=========", "======");
puts("");
unsigned int counterItemNames = 0; //initializing counter
for (counterItemNames = 1; counterItemNames <= itemQuantity; ++counterItemNames) { //the for loop will be print out the item name and prices with their correspondence.
printf("%10u.%12s%12.2f TL\n", counterItemNames, itemNames[counterItemNames - 1], currencyConverter(itemPrices[counterItemNames - 1]));
}
puts("");
...
}
答案 0 :(得分:1)
你写char ** itemNames[BUFSIZ] = {0};
的地方应该是:
char itemNames[itemQuantity][ITEM_NAME_LEN+1];
这是一个VLA,因为它有一个已知维度的数组
运行。通过malloc
分配的空间不是VLA。
不幸的是,VLA不能使用初始化程序,因此您也可以使用 写:
memset(&itemNames, 0, sizeof itemNames);
如果要动态分配此数组,则为:
char (*itemNames)[ITEM_NAME_LEN+1];
itemNames = calloc( itemQuantity, sizeof *itemNames );
并且在两种情况下使用都是相同的。 itemNames[i]
指定您已分配的数组。
您的代码gets(** itemNames[i]);
有两个问题;它取消引用空指针,并使用允许用户导致缓冲区溢出的gets
函数。您应该阅读数组itemNames[i]
,在使用上面的建议后,指定您已分配的存储空间。
不幸的是,在C中只输入一个固定长度的字符串很尴尬。如果用户键入的行数超过行长,则必须担心会发生什么。如果那不太关心你那么:
char line[BUFSIZ];
if ( ! fgets(line, sizeof line, stdin) || !line[0] )
// abort...
// fgets leaves the trailing newline in the input
if ( line[strlen(line)-1] == '\n' )
line[strlen(line)-1] = 0;
snprintf(itemNames[i], ITEM_NAME_LEN+1, "%s", line);
要调用你的函数,请执行以下操作:
dispenserMain(itemNames, itemPrices);
并且函数必须是
void dispenserMain(char (*itemNames)[ITEM_NAME_LEN+1], unsigned int itemPrices[]);
如果你想使用原始dispenserMain
的语法,那么你必须分配一个指针数组,而不是像我所描述的那样使用二维数组。在这种情况下,您将使用char **itemNames = malloc(itemQuantity * sizeof *itemNames);
和每个指针的循环和malloc
指向更多长度为ITEM_NAME_LEN+1
的存储。