我需要帮助解决下面的代码。在使用gcc编译代码之后,它可以像./compiledFile inputFile.txt
一样运行它应该在输入文件时使用inputFile.txt读取它,同时为每个变量动态分配内存,在本例中为name和courseID,但我的代码不起作用。我不太了解并需要帮助的地方是分配内存,将数据插入结构并打印数据,如下面给出的示例。通过这段代码你可以看出我是c的新手以及动态内存分配和结构。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct people
{
char* name[10];
char* courseID[15];
int grade;
};
void printData(struct people student[], int count);
int main(int argc, char* argv[])
{
FILE *in_file;
char buffer[30];
char *token, *del=",";
int count=0;
struct people student[20];
if(( in_file = fopen(argv[1], "r")) == NULL)
{
printf("unable to open the file");
}
while (fgets(buffer, sizeof(buffer), in_file))
{
student = malloc(sizeof(struct people));
token = strtok(buffer, del);
strcpy(student[count].name, token);
count++;
}
fclose(in_file);
printData(student, count);
}
void printData(struct people student[], int count)
{
int i;
for(i=0; i<count; i++)
{
printf("%s", student[i].courseID);
if (strcmp((student[i].name, student[i].courseID) > 0))
{
printf("%s %s", student[i].name, student[i].grade)
}
}
}
data.txt文件具有由comman分隔的以下内容:
John,MATH 1324,90
David,SCI 1401,88
Omondi,MATH 1324,89
David,MATH 1324,90
打印出来时应如下所示:
MATH 1324
John 90
Omondi 89
David 90
SCI 1401
David 88
答案 0 :(得分:2)
首先,如果您还可以分享运行此程序时获得的实际输出或错误,那就太棒了。
大多数情况下,当我们不知道数据元素的实际大小时使用动态内存分配,但是在这里你已经修改了struct people student的大小为20
struct people student[20];
这绝对没问题,但是你在while循环中做了malloc
student = malloc(sizeof(struct student);
你已经使用数组声明分配了20个位置,现在不需要malloc。 如果你想使用指针进行学习目的的动态内存分配,那么你应该首先将student声明为指向struct struct的指针
struct people* student;
在while循环中动态分配内存
student=(struct people*) malloc(sizeof(struct people));
然后访问它
*(student+count)
希望这有帮助,如果您仍有疑问/问题编辑问题并包含编译/运行此程序时得到的输出/错误。
答案 1 :(得分:1)
问题代码的几个问题......
1)main()的定义:
int main(int argc, char* argv[])
必须返回一个整数。在main()的末尾添加一个return语句,然后做一个正确的&#34; CLEANUP&#34;部分:
printData(student, count);
CLEANUP:
if(in_file)
fclose(in_file);
return(0);
}
2)更好地处理fopen()错误条件:
if(( in_file = fopen(argv[1], "r")) == NULL)
{
printf("unable to open the file");
goto CLEANUP;
}
并初始化in_file
指针:
int main(int argc, char* argv[])
{
FILE *in_file = NULL;
3)接下来,需要确定student
的确切定义。它是静态数组,还是指向动态分配数组的指针?我假设您想使用动态数组(给出问题文本)。但是,此假设与以下行冲突,后者将student
定义为静态数组:
struct people student[20];
将其更改为:
struct people *student = NULL;
4)现在,以下问题代码为每个学生分配一个新的(单独的)内存块:
student = malloc(sizeof(struct people));
然而,所需要的是一个阵列中的所有学生记录,在同一块内存中。因此,我们需要的是扩展一块内存,以便在阅读时包含学生记录,如下所示:
while (fgets(buffer, sizeof(buffer), in_file))
{
void *tmp = realloc(student, sizeof(struct people) * (count + 1));
if(NULL == tmp)
{
printf("realloc() failed.\n");
goto CLEANUP;
}
student = tmp;
token = strtok(buffer, del);
5)看看人员结构:
struct people
{
char* name[10];
char* courseID[15];
int grade;
};
对于指针而言,问题代码似乎有些困难。阵列。代码试图将name和courseID字段定义为指针和数组。鉴于问题与动态分配东西有关,我选择朝那个方向发展。因此,此结构应更改为以下内容:
struct people
{
char *name;
char *courseID;
int grade;
};
6)因此,每次循环时,学生姓名将被放置在已分配的存储空间中,并由.name字段指向。所以,改变这个:
token = strtok(buffer, del);
strcpy(student[count]->name, token);
count++;
}
到此:
token = strtok(buffer, del);
student[count].name = strdup(token);
count++;
}
if (strcmp((student[i].name, student[i].courseID) > 0))
我倾向于消除它。
8)以下行有缺陷:
printf("%s %s", student[i].name, student[i].grade)
将其更改为打印整数grade
(并且不要忘记结束分号):
printf("%s %d\n", student[i].name, student[i].grade);
&#39; \ n&#39;使输出看起来更好,每行一条记录。
9)由于student
是指向动态分配的内存(不是静态数组)的指针,因此请更改:
void printData(struct people student[], int count)
到此:
void printData(struct people *student, int count)
10)现在,完成解析数据的任务;从这个:
token = strtok(buffer, del);
strcpy(student[count].name, token);
count++;
}
到此:
token = strtok(buffer, del);
student[count].name = strdup(token);
token = strtok(NULL, del);
student[count].courseID = strdup(token);
token = strtok(NULL, del);
student[count].grade = strtol(token, NULL, 10);
count++;
}
11)现在,为了让生活更轻松,请对数组进行排序。首先按courseID,然后按名称:
...
count++;
}
/** Sort the array by coursID, then by name. **/
qsort(student, count, sizeof(*student), CmpStudentRecs);
printData(student, count);
...
这将需要额外的&#34;比较学生成绩&#34;功能:
int CmpStudentRecs(const void *recA, const void *recB)
{
int result = 0;
struct people *stuRecA = (struct people *)recA;
struct people *stuRecB = (struct people *)recB;
/** First compare the courseIDs **/
result=strcmp(stuRecA->courseID, stuRecB->courseID);
/** Second (if courseIDs match) compare the names **/
if(!result)
result=strcmp(stuRecA->name, stuRecB->name);
return(result);
}
12)使用printData()函数进行一些最后润色:
void printData(struct people *student, int count)
{
int i;
char *courseID = "";
for(i=0; i<count; i++)
{
if(strcmp(courseID, student[i].courseID))
{
printf("%s\n", student[i].courseID);
courseID = student[i].courseID;
}
printf("\t%s %d\n", student[i].name, student[i].grade);
}
}
成品。输出:
SLES11SP2:~/SO> ./test data.txt
MATH 1324
David 90
John 90
Omondi 89
SCI 1401
David 88
SLES11SP2:~/SO>
答案 2 :(得分:0)
将people
的定义更改为:
struct people
{
char name[10];
char courseID[15];
int grade;
};
这假设name
不会超过9个字符,coursID
不会超过14个字符。如果不是这样,请相应地更改它们。
该行:
student = malloc(sizeof(struct student);
在某些方面是错误的。
student
已被声明为people
的数组。您无法将其指定为指向由malloc
分配的内存。
struct student
不是类型。
该行可以删除。
该行
strcpy(student[count].name, token);
如果token
的长度超过10
(或您在name
中为people
选择的任何尺寸),则会导致问题。更安全的事情是使用strncpy
。
strncpy(student[count].name, token, 10);
student[count].name[9] = '\0';
您尚未在任何地方设置courseID
的值。但是,您正试图在printData
中打印它。你正在为grade
做同样的事情。您需要更新输入行的处理以正确设置它们。
将while
循环更改为:
while (fgets(buffer, sizeof(buffer), in_file))
{
token = strtok(buffer, del);
strncpy(student[count].name, token, 10);
student[count].name[9] = '\0';
token = strtok(NULL, del);
strncpy(student[count].courseID, token, 15);
student[count].courseID[14] = '\0';
token = strtok(NULL, del);
student[count].grade = atoi(token);
count++;
}
printData
中有几个语法错误。但是,修复这些语法错误并不能满足您的打印要求。如果对数据进行排序,将按照您希望的顺序打印数据会更容易。以下功能将帮助您对数据进行排序。
int compareStudent(const void* ptr1, const void* ptr2)
{
struct people* p1 = (struct people*)ptr1;
struct people* p2 = (struct people*)ptr2;
return (strcmp(p1->courseID, p2->courseID));
}
void sortData(struct people student[], int count)
{
qsort(student, count, sizeof(struct people), compareStudent);
}
您可以在致电sortData
之前致电printData
或先致电sortData
致电printData
。打印数据的逻辑需要稍微更新一下。这是一个更新的printData
。
void printData(struct people student[], int count)
{
int i;
int j;
sortData(student, count);
for(i=0; i<count; ++i)
{
printf("%s\n", student[i].courseID);
printf("%s %d\n", student[i].name, student[i].grade);
for ( j = i+1; j < count; ++j )
{
if (strcmp(student[i].courseID, student[j].courseID) == 0)
{
printf("%s %d\n", student[j].name, student[j].grade);
}
else
{
i = j-1;
break;
}
}
}
}
答案 3 :(得分:0)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct people {
char name[10];//char *name[10] is array of pointer
char courseID[15];
int grade;
};
void printData(struct people student[], int count);
int main(int argc, char* argv[]){
FILE *in_file;
char buffer[30];
char *token, *del=",";
int count=0;
struct people student[20];
if((in_file = fopen(argv[1], "r")) == NULL){
printf("unable to open the file");
return -1;//It is not possible to continue the process
}
while (fgets(buffer, sizeof(buffer), in_file)){
//student = malloc(sizeof(struct people));//It is by securing an array already
token = strtok(buffer, del);
strcpy(student[count].name, token);
token = strtok(NULL, del);
strcpy(student[count].courseID, token);
token = strtok(NULL, del);
student[count].grade = atoi(token);
count++;
}
fclose(in_file);
printData(student, count);
}
int cmp(const void *a, const void *b){
const char *x = ((const struct people*)a)->courseID;
const char *y = ((const struct people*)b)->courseID;
return strcmp(x, y);
}
void printData(struct people student[], int count){
qsort(student, count, sizeof(struct people), cmp);//sort by courseID
char *prev = "";
int i;
for(i=0; i<count; i++){
if(strcmp(prev, student[i].courseID)!=0){
prev = student[i].courseID;
printf("\n%s\n", prev);
}
printf("%-9s %d\n", student[i].name, student[i].grade);
}
}