C语言-结构体-学生成绩录入-scanf_s()字符串输入缓存区参数问题
在学习结构体时候,在给其赋值时突然报错,详细看是scanf_s()报错了,我们来看一下是什么原因,下面是原始报错代码
#include <stdio.h>
typedef struct Studt{
char id[20];
char name[20];
int sorce1;
int sorce2;
int sorce3;
}Student;
void stuSorce() {
int n = 0;
scanf_s("%d", &n);
Student stu[100],first;
int maxTotal = 0;
int nowTotal = 0;
for (int i = 0; i < n; i++) {
scanf_s("%s %s %d %d %d", &stu[i].id,
&stu[i].name,
&stu[i].sorce1,
&stu[i].sorce2,
&stu[i].sorce3);
}
first = stu[0];
maxTotal = stu[0].socre1 + stu[0].socre2 + stu[0].socre3;
for (int i = 0; i < n;i++) {
nowTotal = stu[i].sorce1 + stu[i].sorce2 + stu[i].sorce3;
if (nowTotal > maxTotal) {
maxTotal = nowTotal;
first = stu[i];
}
}
printf("%s %s %d %d %d", first.id, first.name, first.sorce1, first.sorce2, first.sorce3);
}报错
`1>正在生成代码...
1>D:\program-pack\c\cStudyPro\cStudyPro\stuSorce.c(18,11): warning C4477: “scanf_s”: 格式字符串“%s”需要类型“unsigned int”的参数,但可变参数 2 拥有了类型“char (*)[20]”
1> D:\program-pack\c\cStudyPro\cStudyPro\stuSorce.c(18,11):
1> 此参数用作缓冲区大小
1>D:\program-pack\c\cStudyPro\cStudyPro\stuSorce.c(18,11): warning C4477: “scanf_s”: 格式字符串“%s”需要类型“char *”的参数,但可变参数 3 拥有了类型“int *”
1> D:\program-pack\c\cStudyPro\cStudyPro\stuSorce.c(18,11):
1> 此参数由转换说明符使用
1>D:\program-pack\c\cStudyPro\cStudyPro\stuSorce.c(18,11): warning C4477: “scanf_s”: 格式字符串“%s”需要类型“unsigned int”的参数,但可变参数 4 拥有了类型“int *”
1> D:\program-pack\c\cStudyPro\cStudyPro\stuSorce.c(18,11):
1> 此参数用作缓冲区大小
1>D:\program-pack\c\cStudyPro\cStudyPro\stuSorce.c(18,11): warning C4473: “scanf_s”: 没有为格式字符串传递足够的参数
1> D:\program-pack\c\cStudyPro\cStudyPro\stuSorce.c(18,11):
1> 占位符和其参数预计 7 可变参数,但提供的却是 5 参数
1> D:\program-pack\c\cStudyPro\cStudyPro\stuSorce.c(18,11):
1> 缺失的可变参数 6 为格式字符串“%d”所需
1>cStudyPro.vcxproj -> D:\program-pack\c\cStudyPro\x64\Debug\cStudyPro.exe
1>已完成生成项目“cStudyPro.vcxproj”的操作。`scanf_s()问题所在
很明显,有问题的仅仅是scanf_s()这一句有问题,很明显,在struct中,id和name是char类型的数组,而socre申请的是一个int类型的变量,这里属于疏忽了,数组本身便是第一个元素的地址,因此不需要取地址符&,(尽管这里申请了student类型的stu数组,我们不考虑这一个,我们仅仅考虑student结构中的成员的类型,类似于类与对象中的)
然后最重要的是,在virtual studio中,scanf_s()用来输入字符串类型的数据时,为了防止缓存溢出,需要缓存区大小的参数。
scanf_s("%s", buffer, buffer_size);
- 第一个参数:格式字符串
"%s" - 第二个参数:字符数组的起始地址(数组名)
- 第三个参数:缓冲区大小(数组元素个数)
这里的缓存区大小,即我们申请的char数组的长度,即(unsigned)sizeof(stu[i].id),我们需要把sizeof返回的size_t的数据类型转换为unsigned int类型。最终修改后
#include <stdio.h> typedef struct Studt{ char id[20]; char name[20]; int socre1; int socre2; int socre3; }Student; void stuSorce() { int n = 0; scanf_s("%d", &n); Student stu[100],first; int maxTotal = 0; int nowTotal = 0; for (int i = 0; i < n; i++) { scanf_s("%s %s %d %d %d", stu[i].id, (unsigned)sizeof(stu[i].id), stu[i].name, (unsigned)sizeof(stu[i].name), &stu[i].socre1, &stu[i].socre2, &stu[i].socre3); } first = stu[0]; maxTotal = stu[0].socre1 + stu[0].socre2 + stu[0].socre3; for (int i = 0; i < n;i++) { nowTotal = stu[i].socre1 + stu[i].socre2 + stu[i].socre3; if (nowTotal > maxTotal) { maxTotal = nowTotal; first = stu[i]; } } printf("%s %s %d %d %d", first.id, first.name, first.socre1, first.socre2, first.socre3); }



