C 如何填充字符串大小可变的数组?
我需要建立一个硬币分配器应用程序。我已经编写了取款和寄存部分,但在项目库存创建中,我无法创建解决方案。项目名称应作为字符串从键盘中获取。与项目对应的项目价格应从键盘上取为C 如何填充字符串大小可变的数组?,c,arrays,C,Arrays,我需要建立一个硬币分配器应用程序。我已经编写了取款和寄存部分,但在项目库存创建中,我无法创建解决方案。项目名称应作为字符串从键盘中获取。与项目对应的项目价格应从键盘上取为unsigned ints 阵列应该是可变大小的,也称为VLA。我在谷歌上搜索了一下,找到了一些关于创建VLA的资源,我想我应该使用malloc动态地为它们分配内存。我不能这样做,所以我基本上使用BUFSIZ创建了有限大小的数组 在这种情况下,如何使用VLA,以及如何用字符串填充它们 我还应该防止缓冲区溢出。这将是第二种情况 宏
unsigned int
s
阵列应该是可变大小的,也称为VLA。我在谷歌上搜索了一下,找到了一些关于创建VLA的资源,我想我应该使用malloc
动态地为它们分配内存。我不能这样做,所以我基本上使用BUFSIZ
创建了有限大小的数组
在这种情况下,如何使用VLA,以及如何用字符串填充它们
我还应该防止缓冲区溢出。这将是第二种情况
宏和代码块:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMBER_OF_COINS 5
#define ITEM_NAME_LEN 9
编辑(新代码):
分配器功能:
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("");
...
}
void分发器main(char(*itemNames)[ITEM_NAME_LEN+1],未签名的int itemPrices[]
{
printf(“%s\n\n”,可用项目oo”);
printf(“%10s%15s%14s\n”、“#”、“项目名称”、“价格”);
printf(“%10s%15s%14s\n”、“=”、“================”、“=======”;
认沽权(“”);
unsigned int counterItemNames=0;//初始化计数器
对于(counterItemNames=1;counterItemNames,其中写入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[]);
如果您想使用原始的DispenderMain
语法,那么您必须分配一个指针数组,而不是像我所描述的那样使用二维数组。在这种情况下,您将使用char**itemNames=malloc(itemQuantity*sizeof*itemNames)
和循环通过和malloc
每个指针指向与您的问题无关的更多长度存储ITEM\u NAME\u LEN+1
,但是处理数组上循环的通常方法是从零开始,并使用例如counterItemNames
作为条件。然后您不必从t中减去一他在循环内部建立索引。你在某些地方这样做,但在其他地方不这样做,编程时的一致性很好。这将使代码更易于阅读和理解,特别是在几个月的时间内。你不需要char**itemNames[BUFSIZ];
,因为它是一个太多级别的指针。你可以使用char*itemNames[BUFSIZ]
。要获取VLA,您可以使用:char itemNames[itemQuantity][ITEM_NAME_LEN+1];
和未签名itemPrices[itemQuantity];
。根据定义,您不允许为VLA提供初始值设定项。请记住使用%9s”
用于输入字符串以防止溢出。为什么ItemName是指向字符指针的指针数组?为什么不只是指向字符的指针数组。即使如此,谁分配了这些字符缓冲区?显然没有人…而且从来没有,从来没有,从来没有,从来没有,从来没有,从来没有使用get()
。没有使用get()的程序
可以抵御攻击,或保护自身免受溢出。它不再是标准C的一部分。您应该假设它会通过核心转储使您的程序崩溃。现在我已经完成了您所说的操作,但是我也遇到了相同的问题。它传递了第一项的名称。让我澄清一下,当我运行程序时,我可以成功地输入t项目数量、项目价格和项目名称(第一个除外)。此外,它不会以表格格式输出,价格以新行形式输出。还有一件事,程序传递第一个项目名称,它不会从键盘上获取任何字符串,也不会问它。#1来了,它直接去问#2项目名称。在输出第一个项目的名称时是空白的。你对此有何看法?我看你之前没有提到这个问题;你能描述一下你给出了什么输入,发生了什么,以及你预期会发生什么吗?用新代码在你的帖子上发布更新也是一个好主意(在最后做这件事,不要更改原始代码)
char (*itemNames)[ITEM_NAME_LEN+1];
itemNames = calloc( itemQuantity, sizeof *itemNames );
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[]);