当我学习用C语言编写关于结构和指针的代码时,我尝试制作一个计算学生成绩的程序。 我认为这可以从我之前没有指针和结构的计算中获得。但有了这些,它给了我在该计划中的疯狂结果。
#include <stdio.h>
#include <string.h>
/*
The program will scan year, name, score of three different subjects,
and calculate the sum and the average.
Three different people (using array) will be taken into account.
*/
struct grade {
int year;
char name[20];
int score[3];
int total;
float avg;
};
void main() {
struct grade p[3];
char str = 'c';
char *pstr = NULL;
int i, j;
pstr = &str;
for (j = 0; j < 3; j++) {
printf("Year of Admission: ");
scanf("%d", &p[j].year);
printf("Name of the Student: ");
scanf("%s", pstr);
strcpy(p[j].name, pstr);
for (i = 0; i < 3; i++) {
printf("The score for Subject %d: ", i + 1);
scanf("%d", &p[j].score[i]);
p[j].total += p[j].score[i];
}
p[j].avg = p[j].total / 3.0;
}
for (j = 0; j < 3; j++) {
printf("%s's\n", p[j].name);
printf("Total score: %d\n", p[j].total);
printf("Average: %.2f\n", p[j].avg);
}
}
我本可以将三个不同主题中的每一个都写成一个变量但是为了额外的“挑战”,我在结构中创建了一个数组。
int score [3];
但是,该程序仅打印出总数和平均数的极小数-89541694 ....
我认为for循环中的这一特定行是一个问题。
scanf(“%d”,&amp; p [j] .score [i]);
但我无法弄清楚原因。我对指针很新,还在学习它们。
我希望你的慷慨教学和解释。
提前谢谢。
答案 0 :(得分:2)
局部变量未初始化为0,因此您只需在计算总计之前将其归零:
p[j].total = 0;
之前
for (i = 0; i < 3; i++) {
printf("The score for Subject %d: ", i + 1);
scanf("%d", &p[j].score[i]);
p[j].total += p[j].score[i];
}
答案 1 :(得分:1)
而不是让pstr
成为指针,你可能想要像这样做
char pstr[30];
因此,您将使用scanf
scanf("%29s",pstr);
字符串并检查其返回值。
要稍微描述一下这个问题 - 你有一个指向char
的指针,它不能保存输入字符和相应的\0
(nul终止字符)。结果,这导致了不确定的行为。然后在strcpy
中使用它也是一个非法代码。 (未定义的行为)。
这里我给出的解决方案只是声明了一个30个字符的数组,我们使用scanf
限制字符串输入最多29个字符,因为我们需要存储终止空值。
向您展示至少一些代码,让您了解如何编写这些代码: -
if( scanf("%29s",pstr)!= 1){
fprintf(stderrm"Error in input");
exit(EXIT_FAILURE);
}
另一个问题是初始化变量 - 这里使用p[j].total += p[j].score[i];
最初p[j].total
的值是多少。它包含垃圾值。在循环中首先创建p[j].total = 0;
。这会给你正确的结果。
注意:野外结果是使用p[j].score[i]
添加一些垃圾值导致的垃圾值。
另请注意,如果您只更改初始化内容而未进行我所说的更改,那么代码也不会保证起作用。未定义的行为是未定义的行为 - 可能会出现这样的情况,这些情况只会让程序崩溃,让您想知道哪里出错了。
插图代码可以帮助您:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
The program will scan year, name, score of three different subjects,
and calculate the sum and the average.
Three different people (using array) will be taken into account.
*/
struct grade {
int year;
char name[20];
int score[3];
int total;
float avg;
};
int main(void) {
struct grade p[3];
char pstr[20];
int i, j;
for (j = 0; j < 3; j++) {
printf("Year of Admission: ");
if(scanf("%d", &p[j].year)!=1){
fprintf(stderr, "%s\n", "Error in input");
exit(EXIT_FAILURE);
}
printf("Name of the Student: ");
if(scanf("%19s", pstr)!=1){
fprintf(stderr, "%s\n", "Error in input");
exit(EXIT_FAILURE);
}
strcpy(p[j].name, pstr);
p[j].total = 0;
for (i = 0; i < 3; i++) {
printf("The score for Subject %d: ", i + 1);
if(scanf("%d", &p[j].score[i])!=1){
fprintf(stderr, "%s\n", "Error in input");
exit(EXIT_FAILURE);
}
if(p[j].score < 0){
fprintf(stderr, "%s\n", "Error in input");
exit(EXIT_FAILURE);
}
p[j].total += p[j].score[i];
}
p[j].avg = p[j].total / 3.0;
}
for (j = 0; j < 3; j++) {
printf("%s's\n", p[j].name);
printf("Total score: %d\n", p[j].total);
printf("Average: %.2f\n", p[j].avg);
}
return 0;
}
实际上,不是使用pstr
而是直接在结构变量实例本身中输入名称。无需使用临时变量。
答案 2 :(得分:1)
变量pstr
指向单个char
。对于单字符字符串,C中的字符串必须至少为两个字符:实际字符和 null终止符。
当您使用例如scanf
读取一个字符串,该函数将至少两个字节写入pstr
指向的内存。但由于它只指向一个字节,因此您将编写越界并导致undefined behavior。
如果您希望能够读取多个字符,则需要为字符串分配更多空间。而且你需要限制scanf
以便它不会写出界限。
例如
char pstr[40]; // Allows for strings up to 39 character, plus terminator
// ...
scanf("%39s", pstr); // Read at most 39 characters from standard input, and write to pstr
另一个问题是局部变量没有自动初始化,它们的值将不确定。
这意味着数组p
的内容未知且看似随机。
当你这样做时
p[j].total += p[j].score[i];
你使用看似随机的p[j].total
值来计算另一个看似随机的数字。
要将数组中的所有结构及其所有成员初始化为“零”,请执行以下操作:
struct grad p[3] = { 0 };