我有以下工作代码。但是我误读了指令并创建了一个包含数组而不是结构数组的结构。
以下是来自阵列结构的工作代码。下面是我认为我理解将其更改为结构数组,这可能是错误的。我还需要弄清楚如何在最后打印时对输入的学生ID进行排序,但这并不重要。谢谢你的帮助!
#include <stdio.h>
struct student {
int studID;
int marks[100];
};
int main() {
struct student s[100];
int i, j, val, flag=0;
printf(" \n Please enter the students ID# followed by their grades. When done entering\n");
printf(" grades, enter 101 to start a new student or 102 to exit entry.\n\n\n ");
for(i=0;i<10;) {
printf("Enter student ID#: ");
scanf("%d",&s[i].studID);
printf("\nFor student ID# %d\n",s[i].studID);
for(j=0;j<100;j++) {
printf("Enter grades: ");
scanf("%d",&val);
if(val>=0 && val<=100) {
s[i].marks[j]=val;
}
else if(val==101) {
s[i].marks[j]=-1;
break;
}
else if(val==102) {
s[i].marks[j]=-1;
flag=1;
break;
}
else {
printf("\ninvalid entry\n");
j--;
}
}
printf("\n\n----------\n\n");
i++;
if(flag==1)
break;
}
int num=i;
for(i=0; i<num ; i++) {
printf("\nInformation for student ID number %d:\n",s[i].studID);
for(j=0; s[i].marks[j]!=-1; j++)
printf("Grades: %d\n",s[i].marks[j]);
}
return 0;
}
我认为我需要做的是
struct student {
int studID;
int marks; //remove the array from marks
};
int main() {
struct student s[100];
struct student m[100]; //maybe add this second array?
我不确定在那之后会去哪里。如果我从结构中的标记中删除数组,那么s[i].marks[j]
我得到错误&#34;下标值既不是数组也不是指针,也不是向量&#34;。任何有关如何理顺这一点的帮助将不胜感激。
答案 0 :(得分:1)
//maybe add this second array?
我不这么认为。你说你想要一组结构。那就是s
。结构也包含数组的事实对我来说似乎不是问题,除非它被一些奇怪的规则明确禁止。
我不确定在那之后会去哪里。如果我删除数组 从结构中的标记,任何地方
s[i].marks[j]
我得到错误 “下标值既不是数组也不是指针也不是矢量”。
你当然可以。如果删除数组维度,则marks
为int
,而不是数组。只有s
是一个数组。只有数组或指针可以是[indexed]
。
但请看你原来的例子。你有10个学生,每个学生有100分。通过将数组保留在struct
定义中,代码应该正常工作。您说'抓取学生i
,然后是他们的标记j
'。这应该工作正常。不是吗?你得到什么错误?
答案 1 :(得分:1)
误读了指令并创建了一个包含数组的结构而不是结构数组
简单的答案是
不,结构数组可以由具有数组作为其成员的结构或数组结构
组成
在以下结构的代码中:
struct student //this is a structure of array
{
int studID;
int marks[100];
};
struct student s[100]
绝对是结构数组。因此,您对指令没有任何作用,您的第一个代码确实是结构数组的实现:)
但是,如果不允许您使用数组作为结构成员,请阅读其余部分。
不使用数组结构实现
问题: (使用您的方法)
struct student
{
int studID;
int marks; //you made array to a single variable
};
s[i].marks[j]
,因为现在 {{ 1}} 是一个包含单个整数 的变量,它不能用于使用marks
等索引存储多个值解决方案:
如果您的目标只是避免将数组用作结构成员,并且如果您想访问s[i].marks[index]
并使用下标存储它,那么您可以声明{ {1}}使用marks
函数(包括 marks
文件)作为指向动态分配内存的基址的指针:< / p>
malloc()
然后,在第一个stdlib.h
循环中,添加以下内容:
struct student
{
int studID;
int *marks;
};
//so now in this structure there is no array,
//you just have a integer and integer pointer as members
您正在为要输入的for
成绩分配内存。现在,如果用户只为学生输入for(i=0;i<10;)
{
printf("Enter student ID#: ");
scanf("%d",&s[i].studID);
s[i].marks = malloc(100*sizeof(int)); //here you are allocating memory
个分数,那么100
个等级的剩余分配内存就会被浪费掉。您可以通过将10
的大小重新分配到足够数量的等级来避免这种情况
当用户输入90
时,它会标记当前s[i].marks
的成绩/分数结束,因此您可以通过这种方式重新分配:
101
同样,当您输入student
时,您可以通过这种方式调整else if(val==101)
{
s[i].marks[j]=-1;
s[i].marks = realloc(s[i].marks,(j+1)*sizeof(int)); //resize
break;
}
//`(j+1)*sizeof(int)` because there are `j` number of grades
//and an additional `-1` to mark the end of array.
的大小:
102
现在您可以使用s[i].marks
最后不要忘记以这种方式使用 else if(val==102)
{
s[i].marks[j]=-1;
s[i].marks = realloc(s[i].marks,(j+1)*sizeof(int)); //resize
flag=1;
break;
}
功能释放指定的内存:
s[i].marks[j]
(不使用数组结构)
free()
答案 2 :(得分:1)
继续注释,包含数组的结构数组开头是正确的。如上所述,唯一缺失的部分是添加一个成员来捕获/存储每个 studentID 的标记(成绩)数量。添加它将允许逻辑工作并简化处理程序输出。实际上,它会将逻辑简化为类似于以下的内容(包括按ID排序结果):
...
/* constants for max students and marks */
enum { NSTD = 64, NMARK = 100 };
typedef struct {
int sid; /* student ID */
int nmarks; /* number grades */
int marks[NMARK]; /* grades array */
} student;
int main (int argc, char **argv) {
int i, j, sidx = 0;
student s[NSTD] = {{ .sid = 0 }};
...
for (; sidx < NSTD;) { /* for each id up to max NSTD */
int grade = 0;
printf (" enter student ID: "); /* enter/validate ID */
while (scanf (" %d", &s[sidx].sid) != 1) { ... }
printf (" Enter grades for student %d: ", s[sidx].sid);
while (scanf (" %d", &grade) == 1) { /* for each grade */
...
s[sidx].marks[s[sidx].nmarks++] = grade;
}
sidx++; /* increment student index */
}
...
通过输入所有数据并了解每个studentID有多少等级,迭代数据成为每个studentID和标记的简单嵌套循环,例如:
for (i = 0; i < sidx; i++) {
printf ("\n Student ID : %3d grades :", s[i].sid);
for (j = 0; j < s[i].nmarks; j++)
printf (" %2d", s[i].marks[j]);
}
要对数据进行排序(或者当您认为排序 C中的任何内容时),请使用qsort
。使用qsort
的唯一挑战是编写一个小函数来告诉qsort
如何对传递的内容进行排序。 (您将传递指向student
的指针,因此所需要的只是基于student->sid
进行排序。由于比较函数的输入将是const void *
(常量无效指针),您只需要转换为student *
并引用ID成员:
int cmpsid (const void *a, const void *b)
{
student *s1 = (student *)a; /* technically you should add 'const' */
student *s2 = (student *)b; /* omitted for simmplicity */
/* comparing (a > b) - (a < b) prevents potential overflow */
return (s1->sid > s2->sid) - (s1->sid < s2->sid);
}
您可以通过简单地在比较中应用强制转换来避免中间变量s1
和s2
:
int cmpsid (const void *a, const void *b)
{
/* (a > b) - (a < b) prevents potential overflow */
return (((student *)a)->sid > ((student *)b)->sid) -
(((student *)a)->sid < ((student *)b)->sid);
}
(以较清楚的方式)
您对qsort
的调用只需对结构s
数组进行排序:
qsort (s, sidx, sizeof *s, cmpsid); /* sort by student ID */
完全放入并添加其他有意义的验证,您可以执行以下操作。代码读取文本文件中的数据(如果没有给出文件名,则默认输入提示符):
#include <stdio.h>
#include <stdlib.h> /* for qsort */
/* constants for max students and marks */
enum { NSTD = 64, NMARK = 100 };
typedef struct {
int sid; /* student ID */
int nmarks; /* number grades */
int marks[NMARK]; /* grades array */
} student;
int cmpsid (const void *a, const void *b); /* qsort comparison */
int main (int argc, char **argv) {
int i, j, sidx = 0;
student s[NSTD] = {{ .sid = 0 }};
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
printf ("\n enter student ID followed by grade (0-100)\n"
" 101 for next student, 102 when finished.\n\n");
for (; sidx < NSTD;) { /* for each id up to max NSTD */
int grade = 0, tries = 0;
printf (" enter student ID: "); /* enter/validate ID */
while (scanf (" %d", &s[sidx].sid) != 1) {
fprintf (stderr, " error: invalid student ID.\n");
if (++tries == 3) {
fprintf (stderr, " (max attempts reached, exiting.)\n");
goto done;
}
printf (" enter student ID: ");
}
printf (" Enter grades for student %d: ", s[sidx].sid);
while (scanf (" %d", &grade) == 1) { /* for each grade */
if (grade < 0 || 102 < grade) { /* invalid entry */
fprintf (stderr, " warning: invalid entry '%d'.\n", grade);
continue;
}
if (grade == 101) break; /* next student */
if (grade == 102) { /* exit input */
if (s[sidx].nmarks) sidx++;
goto done;
}
s[sidx].marks[s[sidx].nmarks++] = grade;
if (s[sidx].nmarks == NMARK) {
fprintf (stderr, " warning: max grades for ID %d.\n",
s[sidx].sid);
break;
}
}
sidx++; /* increment student index */
}
done:;
if (fp != stdin) fclose (fp); /* close file if not stdin */
qsort (s, sidx, sizeof *s, cmpsid); /* sort by student ID */
for (i = 0; i < sidx; i++) { /* output sorted data */
printf ("\n Student ID : %3d grades :", s[i].sid);
for (j = 0; j < s[i].nmarks; j++)
printf (" %2d", s[i].marks[j]);
}
putchar ('\n');
return 0;
}
/* integer comparison (use for all numeric types) */
int cmpsid (const void *a, const void *b)
{
/* (a > b) - (a < b) prevents potential overflow */
return (((student *)a)->sid > ((student *)b)->sid) -
(((student *)a)->sid < ((student *)b)->sid);
}
int cmpsid2 (const void *a, const void *b);
int cmpsid2 (const void *a, const void *b)
{
student *s1 = (student *)a; /* technically you should add 'const' */
student *s2 = (student *)b; /* omitted for simmplicity */
/* comparing (a > b) - (a < b) prevents potential overflow */
return (s1->sid > s2->sid) - (s1->sid < s2->sid);
}
示例输入
输入10名学生,每名10个年级:
$ cat dat/idmarks.txt
667 82 79 78 78 97 84 85 77 95 86 101
166 97 97 88 97 74 81 98 82 93 76 101
497 77 95 80 98 71 80 91 77 75 98 101
31 82 78 79 95 92 86 87 95 91 83 101
515 76 76 93 87 71 72 77 92 72 93 101
145 81 79 95 91 99 93 95 99 83 77 101
517 92 98 96 75 83 89 95 93 75 95 101
836 97 84 98 98 91 98 88 71 90 75 101
381 82 98 76 81 90 72 93 93 76 86 101
11 92 86 96 88 78 91 92 76 87 82 102
示例使用/输出
$ ./bin/studentmarks <dat/idmarks.txt
enter student ID followed by grade (0-100)
101 for next student, 102 when finished.
<snip prompts>
Student ID : 11 grades : 92 86 96 88 78 91 92 76 87 82
Student ID : 31 grades : 82 78 79 95 92 86 87 95 91 83
Student ID : 145 grades : 81 79 95 91 99 93 95 99 83 77
Student ID : 166 grades : 97 97 88 97 74 81 98 82 93 76
Student ID : 381 grades : 82 98 76 81 90 72 93 93 76 86
Student ID : 497 grades : 77 95 80 98 71 80 91 77 75 98
Student ID : 515 grades : 76 76 93 87 71 72 77 92 72 93
Student ID : 517 grades : 92 98 96 75 83 89 95 93 75 95
Student ID : 667 grades : 82 79 78 78 97 84 85 77 95 86
Student ID : 836 grades : 97 84 98 98 91 98 88 71 90 75
查看代码,以及其他答案,如果您有任何疑问,请告诉我。选择你的结构内容,以便它适合你,它应该让生活更轻松。