C 我如何知道为一个数组分配多少空间?
我正在创建一个简单的程序(下面的代码),它向用户询问他/她的名字,并向您问好。我只是想知道我在代码中的注释是否正确。我试图理解数组是如何创建的,我们如何为它们分配空间,如何处理它们,这样我们就不会超出内存的界限C 我如何知道为一个数组分配多少空间?,c,arrays,C,Arrays,我正在创建一个简单的程序(下面的代码),它向用户询问他/她的名字,并向您问好。我只是想知道我在代码中的注释是否正确。我试图理解数组是如何创建的,我们如何为它们分配空间,如何处理它们,这样我们就不会超出内存的界限 #include <stdio.h> // "-" (no quotes, just the dash) means garbage values int main() { char name[5]; // name = [0] [1] [2] [3] [
#include <stdio.h>
// "-" (no quotes, just the dash) means garbage values
int main() {
char name[5];
// name = [0] [1] [2] [3] [4] [5]
// - - - - - -
char fav_nums[5];
// fav_nums = [0] [1] [2] [3] [4] [5]
// - - - - - -
printf("What is your name (max characters 5)?\n");
scanf("%s\n", name);
// I typed "Sammy" (no quotes)
// name = [0] [1] [2] [3] [4] [5]
// S a m m y \0
printf("Hi, %s\n", name);
printf("Enter your 5 favorite numbers!\n");
int i = 0;
while (i < 5) {
scanf("%d", fav_nums[i]);
i++;
}
// I typed 2 3 6 7 1
// fav_nums = [0] [1] [2] [3] [4] [5]
// 2 3 6 7 1 -
fav_nums[5] = '\0';
// fav_nums = [0] [1] [2] [3] [4] [5]
// 2 3 6 7 1 \0
printf("Cool, I love");
i = 0;
while (i < 5) {
printf(" %d", fav_num[i]);
i++;
}
printf("\n");
return 0;
}
#包括
//“-”(没有引号,只有破折号)表示垃圾值
int main(){
字符名[5];
//姓名=[0][1][2][3][4][5]
// - - - - - -
charfav_nums[5];
//fav_nums=[0][1][2][3][4][5]
// - - - - - -
printf(“您的名字是什么(最多5个字符)?\n”);
scanf(“%s\n”,名称);
//我输入了“Sammy”(没有引号)
//姓名=[0][1][2][3][4][5]
//“是的,是的\0”
printf(“高,%s\n”,名称);
printf(“输入您最喜爱的5个数字!\n”);
int i=0;
而(i<5){
scanf(“%d”,fav_nums[i]);
i++;
}
//我打了23671
//fav_nums=[0][1][2][3][4][5]
// 2 3 6 7 1 -
fav_nums[5]='\0';
//fav_nums=[0][1][2][3][4][5]
// 2 3 6 7 1 \0
printf(“酷,我爱”);
i=0;
而(i<5){
printf(“%d”,fav_num[i]);
i++;
}
printf(“\n”);
返回0;
}
如何知道在一个数组中要分配多少空间
让我们先看看这个名字
很好,您请求的输入具有上限
printf("What is your name (max characters 5)?\n");
糟糕,
name[5]
太小,无法作为一个字符串保存,一个包含5个字符的名称<代码>“%s”不正确。输入没有限制。不要在“%s”
之后扫描空格。它会一直阻塞,直到检测到以下非空白。检查返回值
// bad
char name[5];
scanf("%s\n", name);
相反,name[]
需要容纳5个特许人和一个空字符
使用匹配的说明符和类型。一个好的、功能良好的编译器应该已经告诉您了,并且节省了我们所有的时间
// not
char fav_nums[5];
scanf("%d", fav_nums[i]); // bad char,%d
// Instead
int fav_nums[5];
scanf("%d", fav_nums[i]); // good int,%d
// or
signed char fav_nums[5];
scanf("%hhd", fav_nums[i]); // good signed char,%hhd
// or
unsigned char fav_nums[5];
scanf("%hhu", fav_nums[i]); // good unsigned char,%hhu
// or
char fav_nums[5];
int num;
scanf("%d", &num); // good int,%d
fav_nums[i] = num;
更深的 如果您想让代码健壮地完成这项工作,代码需要检查更多的内容 将输入与数据存储分开 使用
fgets()
读取用户输入,允许缓冲区至少为预期最大需要量的2倍
然后,它足够大,可以处理数据,一个'\n'
,一个'\0'
和额外的前导,中间是最后的空白,可能是数字输入的非信息性前导'0'
对于2x,代码也不允许误用和滥用超长输入。此类输入应被检测并标记为恶意
将数据读入缓冲区后,对其进行名称解析并保存到name[]
一些伪代码
char buffer[2*sizeof name];
fgets(buffer, ...);
trim_leading_trailing_whitespace(buffer);
insure_not_too_big(buffer, sizeof name);
copy buffer to name
除了@chux'答案外,如果您想读取任意长度的行:
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *name = NULL;
size_t length = 0;
size_t size = 0;
size_t const buffer_growth = 10; // +10 ... or whatever length you expect
int ch;
while ((ch = getchar()) != EOF && ch != '\n' && ch != '\r')
{
if (length + 1 >= size) {
if(size + buffer_growth <= size) // we reached or overflow the max
break; // object size on the platform
char *new_name = realloc(name, size += buffer_growth);
if (!new_name) {
free(name);
fputs("Memory allocation failed :(\n\n", stderr);
return EXIT_FAILURE;
}
name = new_name;
}
name[length++] = ch;
name[length] = '\0';
}
printf("\"%s\"\n", name);
}
#包括
#包括
#包括
内部主(空)
{
char*name=NULL;
尺寸长度=0;
大小\u t大小=0;
大小常数缓冲区增长=10;//+10…或任何您期望的长度
int-ch;
而((ch=getchar())!=EOF&&ch!='\n'&&ch!='\r')
{
如果(长度+1>=尺寸){
如果(size+buffer\u growth)”我只是想知道我在代码中所做的评论是否正确。“不,它们不是。数组的有效索引范围是0
到size-1
,因此char foo[5];
的第一个索引是0
,最后一个是4
。此外,您不应该使用scanf(%s)//…
不限制要读取的字符数:scanf(“%4s\n”,名称)
-->4char
s和终止的'\0'
max.…Siddig El-Tahir El-Fadil El-Siddig Abderrahman Mohammed Ahmed Abdel Karim El-Mahdi在使用你的程序时可能会遇到问题。@Swardfish但我想当你使用char-foo[5]
这意味着索引0-4用于字符,索引5用于“\0”?或者这仅适用于int数组?inti=0;而(i<5){/*.*/i++;}
只是请求成为的循环:用于(inti=0;i<5++i)/*.*/
一个功能良好的编译器会警告像char fav_nums[5];
。节省时间并启用所有警告。什么%hhd
mean@Suku:@Suku%hhd“
withscanf()
用于写入有符号字符%d”
用于写入int
.UV质量“读取任意长度的行”代码。但我现在放弃了用户输入的任意长度,因为它提供了一个黑客攻击:允许外部用户用一条长线来压倒内存资源。相反,我提倡允许大量但有限的输入缓冲区大小,并且失败超过长输入。当然,对于像OP这样的学习者来说,学习不同的方法来解决问题是很好的olve a coding task.@chux如何利用答案中所示的输入法?利用:用户输入数据千兆字节长的文本以使用大量内存资源。可能会导致后续字符串代码错误处理2G字符串,甚至是简单的直接内存不足。甚至少于1000字符
@chux在我的示例中无法利用内存溢出。如果大小\u t
溢出,则会发生奇怪的事情,同意。@chux添加代码以防止realloc()
溢出大小
字节^^
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *name = NULL;
size_t length = 0;
size_t size = 0;
size_t const buffer_growth = 10; // +10 ... or whatever length you expect
int ch;
while ((ch = getchar()) != EOF && ch != '\n' && ch != '\r')
{
if (length + 1 >= size) {
if(size + buffer_growth <= size) // we reached or overflow the max
break; // object size on the platform
char *new_name = realloc(name, size += buffer_growth);
if (!new_name) {
free(name);
fputs("Memory allocation failed :(\n\n", stderr);
return EXIT_FAILURE;
}
name = new_name;
}
name[length++] = ch;
name[length] = '\0';
}
printf("\"%s\"\n", name);
}