Sub-scripted value is neither array nor pointer - c

So I am trying to make a simple program which opens up a text file, reads the number of students that the file contains, their first names, last names and student numbers, and stores values in variables, and then finally returns a pointer to an array of those student objects. My code is as follows: -
#include <stdio.h>
#include <stdlib.h>
struct student
{
double studentNumber;
char *firstName;
char *lastName;
};
struct student *readStudentRecordFile(char *fileName, int *numOfStudents)
{
int i;
struct student a;
FILE *fp;
fp=fopen(fileName,"r");
fscanf(fp,"%d",&numOfStudents);
for(i=0;i<*numOfStudents;i++)
{
fscanf(fp, "%s" "%s" "%f", a[i].firstName,a[i].lastName,&a[i].studentNumber);
}
fclose(fp);
}
int main(void)
{
int nStudents;
struct student *readArray;
readArray=readStudentRecordFile("hello.txt", &nStudents);
return 0;
}
The problem is that when I run the program, I get an error stating the sub scripted value is neither an array nor pointer. I am sort of new to this concept, so I am sort of don't understand what it means. If anyone can tell me what I am doing wrong, and how I can achieve the result that I want, I will be very great-full. Thank you.

In your program a is neither an array nor a pointer. It is of struct student type . You should declare a as an array of struct.
struct student a[SIZE];

a[i].firstName
This is array notation.
a.firstName
This is variable notation.
struct student a;
This is what you have. It's a variable.
struct student a[LEN];
This is what you need. It's an array.

Related

Input to an array of pointers from a file showing error

I am facing this error "subscripted value is not an array, pointer, or vector" for the empF[i]
here is my code
employee empF[100];
int i=0;
void test(){
FILE *fp;
employee empF;
fp=fopen("employee.csv","r");
employee temp;
char x[100];
while(fgets(x,100,fp)!=NULL){
removeCommas(x);
sscanf(x,"%d %s %ld %s %d",&(temp.employee_id),temp.employee_name,&(temp.phno),temp.shift,&(temp.area_code));
empF[i].employee_id=temp.employee_id;
empF[i].employee_name=temp.employee_name;
empF[i].phno=temp.phno;
empF[i].shift=temp.shift;
empF[i].area_code=temp.area_code;
i+=1;
}
fclose(fp);
}
here is the employee struct
typedef struct employee
{
int employee_id;
char employee_name[20];
long int phno;
char shift[10];
int area_code;
}employee;
It seems to run just fine if I don't use an array of structs. What exactly I am missing here?
You redefined the variable name empF in the function, and declared with employee (non-array) type.
void test(){
FILE* fp;
employee empF; /* <-- here */
/* ... */
}
So when you're referencing empF, you're referencing the non-array local variable inside the function.
I guess you forgot removing
employee empF;
line when you switched from one employee to many. This declaration overrides previous array declaration.
(Also, you don't actually need temp employee; you can directly scan to empF[i] but you may have your reasons :))

Trying to display to student data from file according to sorted student ID

I am not able to sort the data i am fetching from file, i want it to print to console by ascending order of ID, I am not able to convert char ID to integer ID to compare
struct student{
char ID[15];
char name[20];
char add[20];
char parname[20];
int Class;
float gpa;
long unsigned int phone_no;
};
void sort_accord_id()
{
while(fread(&stu,sizeof(stu),1,fp))
{
strcpy(s[count].ID,stu.ID);
strcpy(s[count].name,stu.name);
printf("ID:%s\n", stu.ID);
printf("\t%s",s[count].ID);
printf("\t%s",s[count].name);
count++;
}
for(i=0;i<=count-1;i++)
{
for(j=0;j<=count-1;j++)
{
if(s[j].ID-'0'<s[j+1].ID-'0')
{
temp=s[j];
s[j]=s[j+1];
s[j+1]=temp;
}
}
}
}
If it is reading properly to (what I'm assuming to be) the student struct 'object' stu, one approach would be to keep them all in an array (dynamically allocated on heap would be best, otherwise just large enough to keep them all [careful with that!]), then sort them with stdlib.h's qsort().
I can offer help on dynamic arrays if you want but some googling would also do the trick I'm sure.
If you had an array of student structs (which I also suggest you typedef, but for the sake of this answer's clarity I won't) called arr, you could sort them like so:
First #include <stdlib.h> at the top of your file
Then the following function to compare their ID's with strcmp:
int student_cmp(const void* a, const void* b)
{
struct student* studentA = (struct student*)a;
struct student* studentB = (struct student*)b;
return strcmp(studentA->ID, studentB->ID);
}
And finally, you can call qsort in your sort_accord_id() like so:
qsort(arr, 2, sizeof(struct student), student_cmp);
Let me know if you have other questions. And welcome to Stack Overflow!

using structure pointer in scanf doesnt work even with syntax &(struct_pointer->struct_var)

(There was a similar question but the answer given doesn't work)
There is no warning. But after entering values, segmentation fault appears.
#include <stdio.h>
typedef struct
{
int a;
char b;
}PO;
PO *P[1000];
int main()
{
scanf("%d%c",&(P[0]->a),&(P[0]->b));
}
PO *P[1000];
defines an array of 1000 pointers to PO structures.
Written like that it would probably be clearer:
PO* P[1000]; // <-- P is an array of 1,000 pointers to PO
What you probably want is a preallocated array of structures, not pointers to those, e.g.:
PO Data[1000];
In this case, you can read data into it with code like this:
scanf("%d%c", &(Data[0].a), &(Data[0].b));
Or, if you still want an array of pointers, you should allocate each structure using malloc() and then free() it after use.
This code should work:
typedef struct
{
int a;
char b;
}PO_t;
int main(void)
{
unsigned int i=0;
PO_t PO[1000]; //create a 1000 struct of the type PO
PO_t* ptr[1000]; //create 1000 pointers to struct of type PO_t
for(i=0;i<1000;i++)
{
ptr[i]=&PO[i]; //or ptr[i]=&PO[0] if you want 1000 pointers to a single struct
}
for(i=0;i<1000;i++)
{
scanf("%d%c\n",&(PO[i].a),&(PO[i].b));
}
for(i=0;i<1000;i++)
{
printf("%d%c\n",ptr[i]->a),ptr[i]->b));
}
return 0;
}

How to loop through a struct inside a struct while looping through the outer struct C Program

Hi I am trying to create a structure inside a structure, the first structure will contain details for a number of students, the second structure will contain details of a number of modules from each student. Each time asking the user to input details for each student. I was able to create an instance of student structure called data and each time loop through each instance of data and scan in information for each student once only that worked for me. I am now trying to create another inside loop that will scan in a number of different modules that will assign these to each student. I am having problems with the second loop and would appreciate some guidance.
struct module{
char moduleid[5];
int credit;
float grade;
};
//create structure student at includes a datatype
//module
struct student{
char id[10];
char fname[15];
char lname[15];
struct module results;
};
int main()
{
int i;
int j;
int numStuds;
int numMods = 10;
printf("Enter number of students\n");
scanf("%d",&numStuds);
struct student data[numStuds]; //create an instance of structure student called data
struct data.results mods[numMods];
//input data
for (i=0; i<numStuds; i++){
printf("PLEASE ENTER STUDENT DATA :\n\nID, FNAME AND LNAME\n");
scanf("%s%s%s",data[i].id,data[i].fname,data[i].lname);
for (j=0; j<numMods; j++){
printf("\nENTER MODULE DATA: \nMODULEID, CREDIT, GRADE :\n");
scanf("%s%d%f",data[i].results.mods[j].moduleid,&data[i].result.smods[j].credit,&data[i].results.mods[j].grade);
}
}
I think that your main problem is that in the way you have declared "results" inside your student struct you can only have one result for each student. Try to use an static array (if you know how many results you have) or a dynamic one if you want to declare its size during runtime.
e.g
struct student{
char id[10];
char fname[15];
char lname[15];
struct module *results; //Pointer to declare a dynamic array
};
For static declaration
struct student{
char id[10];
char fname[15];
char lname[15];
struct module results[size]; //Pointer to declare a dynamic array
};
If you use the pointer solution remember to access that attribute using "->" operator
Like acostela said, you might want a pointer to a dynamic array. However, I do not see why each student needs multiple results. So when you have the number of students entered, you would just know that each student had one module, referred to as data.result or data->result if you used malloc. If you really need dynamic arrays, I can show you some macros to do this easily.
Okay. I will just show you creation and deletion macros, you can do expansion, inserting, and deleting with realloc and memmove; it would take me too long to write them all out.
#include <stdint.h>
#define ARRAY_DECL(name, type) struct { uint32_t count; type *array } name;
#define ARRAY_DESTROY(name) free(name.array);
These macros create what is called an anonymous structure; this means that it is a one-of-a-kind struct, in this case called name. ARRAY_DESTROY then frees the array inside the struct.

What am i doing wrong in this code?

#include <stdio.h>
main()
{
typedef struct{
char *name;
int age;
}person[5];
int i;
for (i=0;i<5;i++){
printf ("name:");
scanf("%s",person[i].name);
printf("\nage:");
scanf("%d",&person[i].age);}
for (i=0;i<5;i++){
printf ("person:%d",i);
printf ("name:%s",person[i].name);
printf ("age:%d",person[i].age);
}
}
this is the sample program i have. But while compiling i keep getting the error "expected expression before person in line 10,12,16 and 17? What am i doing wrong?
To fix the syntax error, remove the typedef keyword (you're trying to declare a variable, not a type).
Better yet, change to:
typedef struct{
char *name;
int age;} Person;
Person person[5];
Also, the following is wrong:
scanf("%s",person[i].name);
You need to first allocate memory for person[i].name (for example, using malloc()).
Lastly, the %s format specifier in the following line is not correct:
printf ("age:%s",person[i].age);
person is a type, not an object. You cannot "scanf() into a type: person".
I'd simply remove the typedef and just leave the struct definition outside the body of main; and create an object inside
struct person { /* ... */ };
int main(void) {
struct person person[5];
/* ... */
return 0;
}

Resources