Initializing and accessing char array in struct - c

I cannot seem to find a way to initialize a struct without getting segmentation fault .
Here is the assignment `
int id = 5;
// scanf ("%10d", &id);
printf("Please give an name\n");
char *tmpName = (char*)malloc(MAXSTRING * sizeof(char));
fgets(tmpName,MAXSTRING,stdin);
student newStudent = (student){ .id = id , .name = tmpName };
printf("%d",newStudent.id);
printf("%s",newStudent.name);
`
And here is the struct itself
#define MAXSTRING 256
typedef struct{
char *name;
int id;
}student;
I can successfully initialize the struct , but I cannot get access to the name variable , any thoughts?
EDIT : Answers submitted at the time offered nothing , the problem was the way the struct was initialized
char tmpName[MAXSTRING] = {0};
scanf("%s",tmpName);
student newStudent = { .id = id };
strcpy(newStudent.name,tmpName );
This block fixed the issue , will close the topic.

You define a pointer
char *tmpName;
you do nothing to make it actually point to some useable space, especially there is no malloc() or similar.
The you have scanf() (if successful...) write to the pointer, but a string, not any meaningful address. I.e. if that string is not extremely short, you certainly write beyond.
scanf("%s",&tmpName);
Do not be surprised by segfaults, be surprised if there are none.
Later on you then read from where that weird non-pointer points to...
To solve, insert a malloc() after the pointer definition. Alternatively use fixed array of char as an input buffer.
Use the pointer itself, not its address, in scanf() to write the string into the malloced space. (Or the array identifier.)
The rest is the typical set of problems with having enough space, failing to scan, without checking return value etc. Here is a great set of basic hints for getting input right:
How to read / parse input in C? The FAQ

When you declare char name[MAXSTRING], you are telling your compiler that it will always have the exact length of MAXSTRING.
When the compiler hears that, he will most likely replace your string with a lot of static char members.
#define MAXSTRING 4
typedef struct{
char name[MAXSTRING];
int id;
}student;
Would be extended and compiled more like so :
#define MAXSTRING 4
typedef struct{
char name0;
char name1;
char name2;
char name3;
int id;
}student;
Although you would still need to access those using the syntax name[index], as you declared an array, the array pointer is in fact nowhere to be found. So you can't directly assign it.
This is basically what happens with any fixed-length array, they won't allow you to asign them since their content is directly stored in the stack or in the datastructure enclosing it.
You would need to declare.
typedef struct{
char *name;
int id;
}student;
To get a char array pointer of variable length that you can assignate.
That should answer your question, now, as stated by someone in your comment section, there are other things wrong in your code and even with the correct structure, you will probably be unnable to do what you want since scanf is probably returning an arror right now. ^^'
Try allocating the memory beforehand doing so :
char *yourstring = (char*)malloc(MAXSTRING * sizeof(char));
And of course, don't forget to free when you don't need either the string or your student structure :
free(yourstring);
Then again, there's another small issue with your assignement since you do something like this :
.name = *yourstring
While using pointers, prefixing them with * will access the value at the pointed address.
Supposing char *yourstring = "I love cats.";
Doing .name = *yourstring will result in .name being equal to 'I' character, which is first in the array pointed to by yourstring. (Most compiler would complain and ask you to cast.. do not do that.)
So what you really need to do is to assign the pointer to your .name array pointer.
.name = yourstring

Related

Insert string or character in Linked-list C

I'd like to understand how to store correctly a certain string into linked list.
For example the list is defined :
typedef struct node {
int code;
char surname[n];
struct node *next;
}Student;
typedef Student *List;
Is the definition correct ?
Or should i insert a pointer to a char ? for example char *pc ?
The question is how to store the surname properly, if i had to insert a value into 'code' it is relatively simple because i simply for example declare a pointer 'aux' and then aux->code = x, where x is an integer.
The problem is how to scan or how to put a string of characters into the surname[n] place,for example calling a function.
For example creating an other vector of size n,vet[n] scan this one and then assign aus->surname = vet[n] will work?
An other info, maybe related with the first question, could the size of the array defined into the struct be variable ?
The way you define it n needs to be a compile-time-constant; so - regarding the last part of the question - n cannot vary from object to object and hence makes no sense in the struct itself.
The difference between *surname and surname[n] is that you need to allocate memory for it using malloc, whereas the latter provides the memory within each object. Both will work; However, assigning an array will not work in neither case:
char* surname;
...
char vec[100];
scanf("%99s",vec);
surname = malloc(strlen(vec)+1);
strcpy(surname,vec);
Don't forget to free surname once the object shall be discarded.
or:
char surname[100];
...
char vec[100];
scanf("%99s",vec);
strcpy(surname,vec);

C, Expression must be a modifiable lvalue (changing the value of a struct's member) [duplicate]

This question already has answers here:
Assigning strings to arrays of characters
(10 answers)
Closed 4 years ago.
I'm an extreme newbie, I'm just trying to learn.. this is my simple struct that I've created
struct Student{
char FirstName[20];
char LastName[20];
char StudentID[10];
char Password[20];}
Then I'm creating an array of pointers;
struct Student *StudentList[10];
I am then calling my "Register" function and passing the first element in the array as a parameter, for the reason of changing values to that specific struct element in the array, for example I want to change the student's details;
Register(&StudentList[0]);
Further on, my function;
void Register(struct Student *student);
void Register(struct Student *student) {student->FirstName = "John";}
This is a very simplified example and sorry for not being able to correctly paste in the code here.
But why am I getting an "expression must be a modifiable lvalue", when I try to assign a value.
You can't assign array types like that in C, and "John" is an array of type char[5].
strcpy(student->FirstName, "John");
would do it or, better still, something of the form
strncpy(student->FirstName, "John", 20);
so you avoid overrunning the char buffer.
The firstName field is an array, and arrays cannot be assigned to as a whole. That's what the error message is telling you.
Since you're copying a string into this array, you should use strcpy:
strcpy(student->FirstName, "John");
In C, you do not set strings using = (and you do not compare them using == either).
You must use the strcpy function:
strcpy( student->firstName, "John" );
First thing you forget to put semicolon at the end of struct declaration struct Student { };
Secondly, you are passing &StudentList[0], instead just pass StudentList[0] and allocate memory dynamically for that first.
Finally, student->FirstName = "John"; because student->FirstName is one char buffer and "John" also one buffer so you can't do A = B where A and B both are char buffer, instead use strcpy(A,B);
Here is sample example
struct Student{
char FirstName[20];
char LastName[20];
char StudentID[10];
char Password[20];
}; /* you forget to put semicolon */
void Register(struct Student *student) {
strcpy(student->FirstName,"John"); /* use strcpy() */
printf("%s\n",student->FirstName);
}
int main() {
struct Student *StudentList[10];
for(int index = 0;index < 10;index++) {
StudentList[index] = malloc(sizeof(struct Student)); /* allocate memory for each Student */
}
Register(StudentList[0]);
/* free the dynamically allocated memory */
return 0;
}

Subscripted value is neither array nor pointer nor vector at array index

(Homework question)
I'm just learning C, and I'm making a program that reads data from a file, creates routers of that data, and puts pointers to the routers in an array of size 255, but I keep getting the title error on the line where I'm trying to add them to the array
#define ARRAY_SIZE 255
struct router routers[ARRAY_SIZE] = {0};
int main(int argc, char *argv[]){
unsigned char id;
char name[32];
struct router *new_router;
if(argc == 2){
//reads file with fread
//setting id and name which prints out as expected
new_router = make_router(id, name); //initialising method that returns a router pointer
routers[new_router->id] = new_router;
//error occurs here, at [new_router->id]. Have also tried just using id
}
}
I've searched a lot of threads with the same error message, but they're all either someone who didn't declare an array, or were suggested to try it with unsigned char as index number, which is what I'm already using. Would love some insight into this.
struct router{
unsigned char id;
char name[32];
}
struct router* make_router(unsigned char id, char* name){
struct router *r = malloc(sizeof(struct router));
r->id = id;
r->name = name;
return r;
}
Assuming make_router allocates a struct dynamically, then
routers[new_router->id] = *new_router; // note *
solves the compiler error.
However, you cannot copy structs like this if they have pointer members. You say that "Router is just a basic struct with an unsigned char for id, and a char* for name" so this is the case. But with an assignment like this, you won't get a hard copy of the pointed-at data.
Pointers are not data. They do not contain data. They point at data allocated elsewhere.
So probably what you are actually looking for is an array of pointers, as suggested in another answer. If so, you have to re-write this program.
This:
struct router routers[ARRAY_SIZE] = {0};
means routers is an array of ARRAY_SIZE structures. Not pointers to structures, which is what this:
routers[new_router->id] = new_router;
is trying to assign into one of the elements.
If make_router() is dynamically allocating the memory, the fix is probably to change the array declaration into an array of pointers:
struct router * routers[ARRAY_SIZE];
^
|
way
important
EDIT: Of course, I assumed that there was an actual declaration of struct router somewhere that you just omitted. Might be a good idea to include it, just for completeness' sake.

C - Incompatible types in assignment - structs and character arrays

Alright so the gist of my situation is that I'm stuck receiving an incompatibles types in assignment when trying to initialize my struct. I am fairly new to C and understanding pointers proves quite the challenge for me but I have looked at similar questions to this error and tried different fixes and have had no luck so far. If someone could fix this for me, you would be my hero.
struct Employee {
char* name[100];
int birth_year;
int starting_year;
};
struct Employee* make_employee(char* name, int birth_year, int starting_year);
int main(){
//some main stuff code
}
struct Employee* make_employee(char* name, int birth_year, int starting_year){
struct Employee* newEmpl = (struct Employee*)malloc(sizeof(struct Employee));
newEmpl->name = name;
newEmpl->birth_year = birth_year;
newEmpl->starting_year = starting_year;
return newEmpl;
}
The assignment errors occurs on the name = name line. I don't know why.
Also if I switch that line with
strcpy(&(newEmpl->name), name);
I get:
warning: passing argument 1 of 'strcpy' from incompatible pointer type
I've tried to find the problem for 2 hours, and no luck, thought I'd give a shot here.
char* name[100];
is an array of pointers to char but:
char* name;
is a pointer to char.
Here:
newEmpl->name = name;
You are trying to assign a pointer to char to the array but you cannot in C assign a pointer to an array! In fact you cannot assign anything to an array in C.
Check you are using the correct types in your program. Are you sure you want to use char *name[100]; and not char name[100]; (an array of char)? Then to copy a string it, use strcpy or strncpy and not the = operator as you cannot assign something to an array.
In your structure, change
char* name[100]; //an array of pointers to character
to
char name[100]; // a character array
Then, in your make_employee() function, instead of
newEmpl->name = name; //arrays cannot be assigned
use
strcpy(newEmpl->name, name); // copy the contains of name to newEmpl->name
or
strncpy(newEmpl->name, name, 99); // limit to 99 elements only + terminating null
Notes:
Please do not cast the return value of malloc() and family.
Please check for the success of malloc() and family before using the returned pointer.

display a specified index of a pointer char*

I am trying to point on a specified character in a string contained on a structure
here my code
typedef struct{
char *name;
int age;
}PERSON, *person;
int main(){
person serenity;
serenity = (person)malloc(sizeof(PERSON));
strcpy(&(serenity->name),"Serenity");
printf("%c",*(&(serenity->name)+1));
}
here i wanted to display the second character which is 'e' but it shows 'n' instead
anyone can explain me what is wrong with this,
thank you
You have not allocated memory for name
typedef struct{
char *name;
int age;
}PERSON, *person;
int main(){
person serenity;
serenity = malloc(sizeof(PERSON));
serenity->name = malloc(sizeof("Serenity")); //<< Missing
strcpy((serenity->name),"Serenity");
printf("%c",*((serenity->name)+1)); // << Also you want the value in pointer name NOT its address
return 0;
}
Outputs e. Also since you tagged C there is no need to cast the return type of malloc.
Okay, okay... All of those answers aside, if you do not aim to change the characters inside the string "Serenity" in the future, you could just do the following:
#include <stdio.h>
typedef struct{
const char *name; // <-- added const
int age;
}PERSON, *person;
int main( ){
person serenity;
serenity = (person) malloc( sizeof( PERSON ) );
serenity->name = "Serenity"; // <-- simply assigned the pointer with the
// address to the array of constant characters
printf( "%c", *( serenity->name + 1 ) ); // <-- changed this
}
This statement
serenity = (person)malloc(sizeof(PERSON));
allocates the structure
typedef struct{
char *name;
int age;
}PERSON
however name is kept uninitialized and points somewhere in memory causing a crash when you copy to it.
So instead of
strcpy(&(serenity->name),"Serenity");
write
serenity->name = strdup("Serenity");
which is the same as
serenity->name = malloc(strlen("Serenity")+1);
strcpy(serenity->name,"Serenity");
don't forget to free that string as well later.
Try printf("%c",*(serenity->name+1));, also do strcpy(serenity->name,"Serenity");.
If you have a pointer char* name; you access the second element by doing name[1] or *(name+1). &name will give you the address where the pointer address of name is stored. This is not what you want here.
Another issue in your program is that you never allocate memory for the variable name. You need a serenity->name = (char*)malloc(128);. But using an arbitrary length like 128 is very dangerous in combination with strcpy. Use strncpy instead of strcpy to work around this.

Resources