我需要编写一个程序来查找学生的平均范围。如果学生的姓氏是Константинопольский,我不明白如何灵活char name
?
struct student {
char group[5];
char name[21];
char exam[5];
char test[12];
};
void student_average_scope(FILE *file) {
struct student this;
int i;
int sum;
while (fgets((char *)&this, sizeof(this), file) != NULL) {
this.name[20] = '\0';
this.exam[4] = '\0';
for (i = 0, sum = 0; i < 4; i++) {
sum += this.exam[i] - '0';
}
printf("%s - %.1f\n", this.name, (float)sum / 4);
}
fclose(file);
}
我的学生名单:
4273 Багров Д. С. 5454 знззз
4273 Нуйикн А. А. 4333 знзнз
4272 Галкин Г. А. 5445 ззззз
4273 Иванов А. А. 3433 знззн
4272 Козлов И. И. 4443 ззззз
4272 Козлов В. И. 4444 знззз
4272 Бобров П. Н. 4543 знззз
4272 Шмелев И. И. 4443 знззн
答案 0 :(得分:3)
根据@Jongware的要求,这是一个基于scanf系列的解决方案,如果输入的结构相对恒定,这是解析字符串的一种非常方便的方法。
给定输入字符串
4273 Багров Д. С. 5454 знззз
我假设在这个例子中我们所遵循的常量模式是一个int后跟3个字符串,后跟一个int和一个字符串。还有其他方法,我会回到这些。
一个非常基本的演示:
#include <stdio.h>
int main(void) {
char * inputdata = "4273 Багров Д. С. 5454 знззз";
// variables to receive the scanned data
int firstint, secondint;
char firststring[32];
char secondstring[32];
char thirdstring[32];
char fourthstring[32];
// important, you should check whether the number of converted elements
// matches what you expect:
int scannedelements;
// let's scan the input
scannedelements = sscanf (inputdata,"%d %s %s %s %d %s",&firstint, &firststring, secondstring,
thirdstring,&secondint,fourthstring);
// and show what we found. Notice the similarity between scanf and printf
// but also note the subtle differences!!!
printf("We scanned %d %s %s %s %d %s\n",firstint, firststring, secondstring,
thirdstring,secondint,fourthstring);
printf("That's a total of %d elements %d\n",scannedelements);
return 0;
}
输出:
We scanned 4273 Багров Д. С. 5454 знззз
That's a total of 6 elements
请注意,我将您命名为考试的字段扫描为整数,您可以通过digit = data % 10; data = data / 10;
现在,第一组字符串被切入3个不同输出的事实可能很烦人。根据输出数据,我们可以指示sscanf读取,直到遇到数字:
#include <stdio.h>
int main(void) {
char * inputdata = "4273 Багров Д. С. 5454 знззз";
// variables to receive the scanned data
int firstint, secondint;
char firststring[32];
char secondstring[32];
char thirdstring[32];
char fourthstring[32];
// important, you should check whether the number of converted elements
// matches what you expect:
int scannedelements;
// Alternatively, let's scan the group of 3 strings into 1 variable
scannedelements = sscanf (inputdata,"%d %[^0-9] %d %s",&firstint, firststring, &secondint,fourthstring);
// and show what we found.
printf("We scanned %d %s %d %s\n",firstint, firststring,secondint,fourthstring);
printf("That's a total of %d elements %d\n",scannedelements);
return 0;
}
输出:
We scanned 4273 Багров Д. С. 5454 знззз
That's a total of 4 elements -1079150400
注意Багров Д. С.
中的尾随空格,这可能是也可能不是问题,但很容易删除。
为方便起见,此代码可在ideone上使用:http://ideone.com/4gFlxf#sthash.KQfhcYxr.dpuf
这个例子几乎没有涉及scanf的可能性,我鼓励你探索它manpage以发现更多的可能性。
-
关于如何计算平均分数:
#include <stdio.h>
int main(void) {
int inputdata = 24680;
int average = 0;
int number_digits = 0;
int digit = 0;
int digits = 0;
while (inputdata > 0) {
digit = inputdata % 10; // modulo by 10 is the last digit
average += digit;
digits++;
inputdata = inputdata / 10; // integer division by 10 = remove last digit
}
if (digits > 0) { // to avoid dividing by zero is some edge case
printf ("The average over %d scores is %.1f\n", digits, (double) average / digits);
} else {
printf ("As the input was 0, the average is 0");
}
return 0;
}
答案 1 :(得分:1)
最简单的方法是增加char name
的大小,以允许最长的可能的学生姓名。但是将原始数据直接读入结构体是非常不安全的;最好使用临时字符串并解析它。
请注意,这样您就不再需要struct student
了,也不需要name
成为char *
。仍存在某种限制:读取缓冲区必须足够大才能读取每一行的所有数据。就其本身而言,fgets
可以读取“太长”的行(它们不会以\n
结尾),但是您需要很多标记才能确保正在解析正确的数据。在这种情况下,更容易使缓冲区“确实足够大”。
void student_average_scope(FILE *file) {
int i;
int sum;
char read_buf[128]; /* must be long enough! */
char *name_ptr, *exam_ptr;
while (fgets(read_buf, sizeof(read_buf), file) != NULL)
{
/* find name */
name_ptr = strchr (read_buf, ' ');
if (!name_ptr) continue;
/* 'name_ptr' now points to last name */
/* we need some trickery to skip zero(!) or more initials ... */
exam_ptr = name_ptr;
while (*exam_ptr && !isdigit(*exam_ptr))
{
exam_ptr++;
}
if (!*exam_ptr) continue;
/* exam_ptr now points to first digit after name */
exam_ptr[-1] = 0;
sum = 0;
for (i = 0; i < 4; i++) {
sum += exam_ptr[i] - '0';
}
printf("%s - %.1f\n", name_ptr, (float)sum / 4);
}
fclose(file);
}
输出
Багров Д. С. - 4.5
Константинопольский А. А. - 3.2
Галкин Г. А. - 4.5
Иванов А. А. - 3.2
Козлов И. И. - 3.8
Козлов В. И. - 4.0
Бобров П. Н. - 4.0
Шмелев И. И. - 3.8