我正在创建一个简单的程序(下面的代码),该程序向用户询问他/她的名字,并向您问好。我只是想知道代码中的注释是否正确。我试图了解如何创建数组,以及如何为它们分配空间并处理它们,因此我们不会超出内存范围。
#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;
}
答案 0 :(得分:2)
我怎么知道要在数组中分配多少空间?
让我们先看看这个名字。
好,您要输入一个上限。
printf("What is your name (max characters 5)?\n");
错误,name[5]
太小,不足以作为 string (一个包含5个字符的名称)保存。 "%s"
不好。输入无限制。在"%s"
之后不扫描空白。它一直阻塞,直到检测到跟随非空白区域为止。检查返回值。
// bad
char name[5];
scanf("%s\n", name);
相反,name[]
需要5个宪章和一个空字符的空间。
char name[5+1];
if (scanf("%5s", name) == 1) Success();
使用匹配的说明符和类型。一个运行良好的良好编译器会已经告诉您了,并节省了我们的所有时间。
// 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
答案 1 :(得分:2)
除了@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);
}