How to convert pointer array to char array? - c

I have this:
typedef struct nodebase{
char name[254];
char sex;
int clientnum;
int cellphone;
struct nodebase *next;
struct nodebase *encoding;
} clientdata;
I have added clientdata *curr[]; in seperate function. The reason why I made *curr into *curr[] instead is that this client data will be stored in a .txt file. So I came up with singly linked-list to read all the data and when the program fscanf every 5th variable, I will add 1 to clientcounter.
So, the *curr[] will be *curr[clientcounter].
Now, I need to convert this pointer array into char array named temp[clientcounter] because char array is needed to evaluate something else later in the code.
I came up with this code below:(Using Tiny C on Windows)
void loaded_data_transfer(clientdata *curr,clientdata temp[],int clientcounter)
{
clientdata temp[] = {0};
temp[clientcounter].name = curr[clientcounter]->name;
temp[clientcounter].sex = curr[clientcounter]->sex;
temp[clientcounter].clientnum = curr[clientcounter]->clientnum;
temp[clientcounter].cellphone = curr[clientcounter]->cellphone;
}
The problem is, Tiny C is giving me an error: lvalue expected at temp[clientcounter.name = ... part. Can anyone tell me what did I do wrong?
And if anyone knows a better way to keep track of the curr of clientdata by using counter and by using singly linked-list, please let me know.

You cannot assign an array to another. You should use strcpy or strncpy
strcpy(temp[clientcounter].name, curr[clientcounter]->name);

Maybe you meant to copy the entire struct:
void loaded_data_transfer(clientdata * curr, clientdata temp[], int clientcounter)
{
temp[clientcounter] = *curr; // Copy entire struct
}
It should work, because your struct doesn't any pointer members.
I am assuming you use it like this
clientdata * curr[CURR_SIZE];
clientdata temp[TEMP_SIZE];
/* init curr elements here */
loaded_data_transfer(*curr[clientcounter], temp, clientcounter);

Also, your declaration should be:
void loaded_data_transfer(clientdata *curr[],...

Related

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.

Understanding pointer structs in C

I am trying to understand an assignment I have before I have to take a final. I am trying to understand what exactly I am declaring.
So in a given file the typedef struct's are declared as so:
(Struct Declaration)
/** The following two structs must be defined in your <gamename>.c file **/
typedef struct game_position_t *game_position;
/* move struct must code enough information to reverse the move, given the resulting position */
typedef struct move_t *move;
I have then built the structs out as so (yes this has to be separated just because it is interfaced programming):
(Struct Definition)
/** The following two structs must be defined in your <gamename>.c file **/
struct game_position_t {
int mathy;
int numrows;
int *sizes;
};
/* move struct must code enough information to reverse the move, given the resulting position */
struct move_t {
int rownum;
int move_size;
};
Then an example of a functions and declaration of game_position for example is:
(Example Function)
/* return the starting position, NULL if error */
game_position starting_position(int me_first, int argc, char **argv) {
if (argc < 3) {
printf("\n\nToo few arguments, see help below\n\n");
game_help(argv[0]);
return NULL;
}
int mathy;
if (strcmp(argv[2],"search")==0)
mathy = 0;
else if (strcmp(argv[2],"mathy")==0)
mathy = 1;
else {
printf("\n\nSecond argument must be \"search\" or \"mathy\", see help below\n\n");
game_help(argv[0]);
return NULL;
}
int play_default = (argc==3);
if (play_default) printf("\n\nOK, we will play the default game of 7 5 3 1\n\n");
int defaultgame[4] = {7,5,3,1};
game_position result = malloc(sizeof(struct game_position_t)*1);
result->mathy = mathy;
if (result) {
result->numrows = (play_default ? 4 : argc-3);
result->sizes = malloc(sizeof(int)*(result->numrows));
int row;
for (row=0; row<(result->numrows); row++)
(result->sizes)[row] = (play_default ? defaultgame[row] : strlen(argv[row+2]));
}
return result;
}
So my main misunderstanding is when using a struct declaration in this manner, specifically putting the * before the name like this, typedef struct move_t *move;. Is that previous line saying move it a struct pointer or dereferencing move? Continuing from that. When defining them I just use the struct name such as struct move_t. I don't fully understand how they are linking together and in what matter. Then inside the function I just declare game_position, but still need to use a derefencer, 'p->`, to access it fields. So if someone could explain to me when these struct variables are points to structs and when they are the actual struct.
An example of my misunderstanding is that in the Example Function after result was declared. I first thought to use the . operator to access and set it's fields. I then changed it due to compiler errors, but now I want to understand my misunderstanding. And why did I I have to malloc game_position_t and not game_position?
typedef defines a type, so typedef struct move_t *move defines a new type named move, which is a pointer type, pointing to struct move_t. So after this if you define a variable with move ptr, ptr will have a pointer type so that you should use the syntax of accessing members through a pointer. When allocating memory for it, of course you have to specify the exact size of the structure other than the size of a pointer, that's sizeof(struct move_t)

read struct objects from a file and point to the object read using void* pointer

I have the following four structs in my program
struct SType{
int type;//struct type
};
struct S1{
};
struct S2{
};
struct S3{
};
I am saving the states of these structs in a file using the following code:
void store(struct SType s1,void *s){
//open file and stuff
//s points to either one of the last three structs
fwrite(&s1,sizeof(s1),1,file); fwrite(s, size, 1, file);
//structs are always saved in the file in pairs of SType and either one of the last three structs
}
Now when i am trying to retrieve the second struct of the pair from the file using the following code, i get segmentation fault. So how do i retreive an object of an arbitary struct type using fread()?
void read(){
void *record;
//read struct SType object from the file
//now read the second struct of the pair
fread(record,size,1,file);
}
You have to read into valid memory. void means "I don't know" and the system cannot and will not guess that value for you!!
What you have is:
void read(){
void *record;// This pointer currently is a random value - this will cause a fault when you try and copy data into it by calling:
fread(record,size,1,file);
}
It should be:
void read(){
void *record;
len = ?; // Your program needs to know this. You must know which structure it is somehow if you are to cast it later. Therefore you should know its size.
record = malloc(len); // Where len has been previously found to be AT LEAST big enough to read into
fread(record,size,1,file);
}
As you say your code is not psuedocode, then also put something in your structs so they're not empty. It would also be advisable to do something with the structure once you've read it, for example return the void * from your fread.
Hope that helps.
You read a record to uninitialized pointer, I guess you should alloc memory first.
void *record = maloc( size )
And do not forget to free ...
May I suggest you to use a Union?
Your type definitions will look like this:
struct SType{
int type;//struct type
};
struct S1{
};
struct S2{
};
struct S3{
};
union S{
S1 s1;
S2 s2;
S3 s3;
};
now read and write can be done like this:
SType stype;
S s;
fread(&stype,sizeof(stype),1,file);
size = ??? //get according to type
fread(&s,size,1,file);
// your data will be stored according to type in s.s1, s.s2 or s.s3
size = ??? //get according to type
fwrite(&stype,sizeof(stype),1,file);
fwrite(&s,size,1,file);
Next stage, is to unify the Type with the rest:
struct S{
int type;//struct type
union {
S1 s1;
S2 s2;
S3 s3;
}s;
};
/* in case you don't care about loosing file space,
you can read\write all in a single operation like this:
*/
S s;
fread(&s,sizeof(s),1,file);
// now according to the type you take s.s.s1, s.s.s2 or s.s.s3.
fwrite(&s,sizeof(s),1,file);
/* if you do care about loosing file space, you work like before */
S s;
fread(&s.type,sizeof(int),1,file);
size = ??? //get according to type
fread(&s.s,size,1,file);
// as before, you take s.s.s1, s.s.s2 or s.s.s3.
size = ??? //get according to type
fwrite(&s.type,sizeof(int),1,file);
fwrite(&s.s,size,1,file);

a way to copy a 2dimensional array into a struct array

I have this array filled up with characters in my maze.c file:
char normalMazeArray[6][12]; dynamically filled as mazeArray[row][column]
Now I want to pass what the array to the mazeArray that is located in my struct (maze.h)
my struct is called:
typedef struct {
char mazeArray;
} maze_t;
I have tried copying it as follows:
maze_t* maze;
char normalMazeArray[6][12]; // filled with info
typedef struct {
char mazeArray;
} maze_t;
maze->mazeArray = normalMazeArray;
however it is not working,
anyone who could help me?
The thing what you're trying to do is not exactly possible. There are two slightly different solutions you can use, though.
normalMazeArray is of type char [6][12] - it's an array. You can either copy its contents to the same type of array using memcpy():
typedef struct {
char mazeArray[6][12];
} maze_t;
memcpy(maze->mazeArray, normalMazeArray, sizeof(normalMazeArray));
or if your normalMazeArray persists throughout the lifetime of the program, you can assign a pointer to it in the structure:
typedef struct {
char (*mazeArray)[12];
} maze_t;
maze->mazeArray = normalMazeArray;
Wait, how??
First of all, maze is a pointer, so you can't have maze.mazeArray. Second of all, maze->mazeArray is of type char, while mazeArray is of type char**. No can do.
You should write a function which allocates char** array, and then strdups strings from mazeArray. Or, if you want ownership transfer, and not just copy, you could go like this:
typedef struct {
char** mazeArray;
} maze_t;
maze_t maze;
maze.mazeArray = mazeArray;

C: copying struct/array elements

I have a file in a known format and I want to convert it to a new format, eg.:
struct foo {
char bar[256];
};
struct old_format {
char name[128];
struct foo data[16];
};
struct new_format {
int nr;
char name[128];
struct foo data[16];
};
static struct old_format old[10];
static struct new_format new[10];
Problem: after filling 'old' with the data I don't know how to copy its content to 'new'. If I do
new[0].name = old[0].name;
new[0].data = old[0].data;
I get a compile error about assigning char * to char[128] (struct foo * to struct foo[16], respectively).
I tried a solution I found via Google for the string part:
strcpy (new[0].name, old[0].name);
new[0].data = old[0].data;
but I have no idea how to handle the struct. Seems I lack basic understanding of how to handle arrays but I don't want to learn C - I just need to complete this task.
If you don't want to learn C, you should be able to read the old file format in any language with a half-decent IO library.
To complete what you're trying to do in C, you could use memcpy.
So instead of:
new[0].data = old[0].data;
Use
memcpy(new[0].data, old[0].data, sizeof(foo) * 16);
You can also wrap the C arrays in a struct. Then copying elements will copy the array automatically.
typedef struct {
char name[100];
} name_array_t;
struct {
name_array_t name_struct;
...
} x;
struct {
name_array_t name_struct;
... other members ...
} y;
x.name_struct = y.name_struct;
(too obvious solution may be)
As we are dealing with the array, we can not do this kind of operation
new.name = old.name;
so i suppose you have to write a function
void Function (char *name , struct new_format *new );
where you need to assign charecter one by one.
Obviously you will Call like this : Function (old.name , &new)

Resources