Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 我如何知道为一个数组分配多少空间?_C_Arrays - Fatal编程技术网

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”,名称)
-->4
char
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“
with
scanf()
用于写入
有符号字符
%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);
}