I need to build an Coin Dispenser application. I've written the withdrawal and deposit parts but in item inventory creation I couldn't create a solution to that. Item names should be taken from keyboard as strings. Item prices corresponding to the items should be taken from keyboard as unsigned ints.
Arrays should be variable-sized, aka VLAs. I've googled it and found some resources about creating VLAs, I think I should allocate memory to them dynamically using malloc. I couldn't do that, so I basically created limited sized arrays with using BUFSIZ.
How can I use VLAs in this case, and how can I fill them with strings?
Also I should prevent buffer overrun. This will be the second case.
Macros and code blocks:
#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;
}
Also program should output the item names and prices as a list. Function dispenserMain does this:
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]));
}
...
}
Edit (new code):
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
It outputs:
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:
Dispenser function:
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("");
...
}
counterItemNames < itemQuantityfor condition. Then you don't have to subtract one from the index inside the loop. You do it in some places but not in others, consistency is good when programming. It will make the code easier to read and understand, especially for yourself in a few months time.char ** itemNames[BUFSIZ];because it is one too many levels of pointer. You might usechar *itemNames[BUFSIZ];. To get VLAs, you could use:char itemNames[itemQuantity][ITEM_NAME_LEN+1];andunsigned itemPrices[itemQuantity];. By definition, you are not allowed to provide initializers for VLAs. Remember to use"%9s"for inputting the strings to prevent overflows.gets(). No program that usesgets()can defend itself against attack, or protect itself from overflow. It is no longer part of Standard C. You should assume that it crashes your program with a core dump.