Input to an array of pointers from a file showing error - c

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 :))

Related

Why does where you declare function matter?

So im just learning C but from my understand we can create Function Prototypes anywhere right?
So then when i was experimenting with function and structure why is it that. If i put the function prototype before the structure declaration is does not work but when i put the function prototype after the structure declaration it does work ?.
Could some kind soul explain this?
Before structure declaration (Does not Work)
/* Function Prototypes */
void printID(struct studentID person);
/* Structure Decleration */
struct studentID{
char Name[50];
int Age;
int Birth_Year;
};
int main(){
struct studentID me = {"BOB", 25, 1996};
printID(me);
return 0;
}
/* Function Details */
void printID(struct studentID person){
printf("Your Name is %s\n", person.Name);
printf("Your Age is %d\n", person.Age);
printf("Your date of birth is %d\n", person.Birth_Year);
}
After Structure declaration (Does Work)
/* Structure Decleration */
struct studentID{
char Name[50];
int Age;
int Birth_Year;
};
/* Function Prototypes */
void printID(struct studentID person);
int main(){
struct studentID me = {"BOB", 25, 1996};
printID(me);
return 0;
}
/* Function Details */
void printID(struct studentID person){
printf("Your Name is %s\n", person.Name);
printf("Your Age is %d\n", person.Age);
printf("Your date of birth is %d\n", person.Birth_Year);
}
Data types must be defined before you can use them.
Since printID has a parameter of type struct studentID, the definition of struct studentID must come before the declaration of printID.
C compilers process files in a single pass, so all types must be defined before they can be used, and all functions must be at least declared before they can be called.
A type definition must be complete before you can create an instance (object) of that type. For struct, union, and enum types, the type definition isn’t complete until the closing }.
However, you can declare pointers to incomplete types; IOW, the following would be perfectly legal:
struct studentID; // incomplete type definition
void printID( struct studentID *person );
struct studentID {
...
}; // type definition is now complete
You would still need the definition of struct studentID to be complete before you could dereference it in the body of printID, so you would have to put the body of printID after this.

Pass a string in a struct to a function and return it

I want to return the name of the smallest city population-wise, if it is the second city. (Please don't mind the if statement, I know it's bland), the missing return is what bothers me.
I assume I should declare a pointer inside the function rSmallestCity, like *rtrn but I guess the source variable is destroyed before it is used?
typedef struct Coordinate{
int x,y;
}Coordinate;
typedef struct city{
char name[20];
int population;
Coordinate coordinates;
}city;
char *rSmallestCity(city **cl, int n)
{
char *rtrn = NULL;
if(cl[n-2]->population>cl[n-1]->population)
{
rtrn = &cl[n-1]->name;
}
return rtrn;
}
int main()
{
city c1 ={.name="Mumbai", .population=310, .coordinates.x=3, .coordinates.y=4};
city c2 ={.name="Delhi", .population=300, .coordinates.x=3, .coordinates.y=2};
city *clist[2];
clist[0]=&c1;
clist[1]=&c2;
printf("\n%s is smallest\n",rSmallestCity(clist,2));
}
warning: assignment to 'char ' from incompatible pointer type 'char ()[20]' [-Wincompatible-pointer-types]|
I assume I should declare a pointer inside the function rSmallestCity, like *rtrn but I guess the source variable is destroyed before it is used?
A good question. And your assumption is correct. Creating a variable inside a function it's existence ends upon leaving the function. But in this case, because the struct member name is already a char * you do not need to create another variable. Just return c1.name. (see code example below.)
A few other suggestions:
In the struct declaration:
typedef struct Coordinate{
int x,y;
}Coordinate;
You've used the same symbol (Coordinate) for the struct name, and for it's typedef. This is not a good practice. If you need both a struct name and a typedef, pick different symbols. BTW, in this this example, only one or the other is needed. Say you pick the typedef, then the struct is completely defined by:
typedef struct {
int x,y;
}Coordinate;
That suggestion applies to both struct declarations in your example code.
The signatures for the main function do not include int main(){...} rather
int main(void){..., return 0;} and int main(int argc, char *argv[]){..., return 0;}
The following code example illustrates some of the other suggestions for improvements in comments under your post,
typedef struct {
int x,y;
}Coordinate;
typedef struct {
char name[20];
int population;
Coordinate coordinates;
}city;
//return char * rather than char to allow for full null terminated char array (string)
char * rSmallestCity(city c1[],int cityCount)//generisize function prototype to
{ //to easily accommodate bigger arrays if needed
long long size, sizeKeep = 8e9; //index and population. initialize larger than possible population
int indexKeep = 0;
//note you do not need to define a char *, the struct already contains one
for(int i=0; i<cityCount; i++)//use a loop rather than a single comparison, keep the smalles
{
size = c1[i].population;
sizeKeep = (size < sizeKeep) ? indexKeep = i, size : sizeKeep;
}
printf("\n%s\n",c1[indexKeep].name);
return c1[indexKeep].name;
};
int main(void)//use minimum signature for main, and call return before leaving.
{
//combining your original declarations and assignments for struct
//into a single declaration/definition.
city c1[] = {{.name="Mumbai", .population=310, .coordinates.x=3, .coordinates.y=4},
{.name="Delhi", .population=300, .coordinates.x=3, .coordinates.y=2}};
int cityCount = sizeof(c1)/sizeof(c1[0]);
printf("\n%s is smallest",rSmallestCity(c1, cityCount));
return 0;
};
The solution that I originally left in comment under OP (remove & in the line &cl[n-1]->name;) needs some explanations to avoid problems later.
(It is an educational answer not a full answer on pointers, array decay, ... And many examples can be found on stackoverflow. I tried to simplify)
Try this simple code.
int main()
{
char myString1[25]="Toulouse" ; // French City
printf("%p\n",myString1);
printf("%p\n",&myString1);
}
The output is the same, but an array name and the address of an array name are not the same. The array name is evaluated to the address of its first element. So it works in your case but a warning is issued during compilation and it is very important. Firstly, do not remove compilation warnings.
Now, try this code :
int main()
{
char myString1[25]="Toulouse" ; // French City
printf("%p\n",myString1+1);
printf("%p\n",&myString1+1);
}
The outputs are different. Because myString1 is evaluated to char* and &myString1 to char [25]. So +1, in the first, case adds one (sizeof char) to the pointer and in the other case, it adds 25.
Delete the "&" in the line:
rtrn = &cl[n-1]->name;
To extremely simplify, you assigned an "address of char[]" to a char*, but array syntax makes it work regardless.

Passing an element of an array of structs in C

I was trying to pass one of the 20 "database" structs I made
here is my prototype for the function "add"
void add(struct database test);
I want to pass my database struct and for now i'll just call it "test"
Here is my database structure
struct database
{
char ID[6];
char Duration[3];
};
main()
{
char menu;
struct database employee[20]; // I make 20 employee variables
int a = 0; /*A counter I use to edit certain structs
ie a=2 "employee[a]" = "employee[2]" */
I then call the function like this:
add(employee[a]);
a++; /*Once it exits this I want it to go to the next employee
variable so I increment the counter */
The actual function looks like this:
void add(struct database test)
{
static int a = 0;
printf("\nPlease enter a 5 digit employee number: ");
scanf("%s", test[a].ID);
a++
}
while doing this I get the error:
Error E2094 Assignment.c 64: 'operator+' not implemented in type 'database' for arguments of type 'int' in function add(database)
It says the error is at
scanf("%s", test[a].ID);
Thanks in advance for any help, and I apolgise if I have formatted this wrong, still learning for to use stack overflow, so sorry!
This is what you need to do in order to get it right:
void add(struct database* test)
{
printf("\nPlease enter a 5 digit employee number: ");
scanf("%s",test->ID);
}
int main()
{
...
int a;
struct database employee[20];
for (a=0; a<sizeof(employee)/sizeof(*employee); a++)
add(&employee[a]); // or add(employee+a);
...
}
add(struct database test) declares a struct database as parameter. This is not an array, so you cannot index it.
So
test[a]
is invalid.
Also the int a inside add() is different from the int a defined in main(). Inside add() the latter a is hidden by the former a.
Also^2 you are passing to add() a copy of the array's element declared in main(). So any modifications done to test in side add() are lost when returning from add(). They won't be visible in the array declated in main().

Sub-scripted value is neither array nor pointer

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.

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