file into dynamic arrays

S

Steve Chow

I have two structures;

struct cordsys {
int y, x, length
};

struct provinces {
int number;
int type;
struct cordsys cord;
};

and a file that looks like:

1
68 78 83
69 78 87
70 78 89
71 78 91
72 78 93
73 77 95
1

2
110 77 180
111 77 182
112 77 184
113 76 186
114 76 188
115 76 189
116 76 191
117 76 192
2
.................

what i need to do is read the beginning number into provinces.number.
and read the next rows. with three numbers each. read into
provinces.cords.y provinces.cord.x provinces.cord.length

creating a new cord array (while keeping the old one) with each row.
when it hits a number that matches the beginning cord. i need it to add
a new province array (while keeping the old one)

i'm new to c so know nothing about memory management. not asking anyone
to do my work also. just need a detailed explanation of the concepts,
possibly functions, and a general idea. think who/what/where/why. thank
you.
 
N

Nick Keighley

Steve said:
I have two structures;

struct cordsys {
int y, x, length
};

struct provinces {
int number;
int type;
struct cordsys cord;
};

and a file that looks like:

1
68 78 83
69 78 87

1

2
110 77 180
111 77 182

2
................

what i need to do is read the beginning number into provinces.number.
and read the next rows. with three numbers each. read into
provinces.cords.y provinces.cord.x provinces.cord.length

creating a new cord array (while keeping the old one) with each row.
when it hits a number that matches the beginning cord. i need it to add
a new province array (while keeping the old one)

i'm new to c so know nothing about memory management. not asking anyone
to do my work also. just need a detailed explanation of the concepts,
possibly functions, and a general idea. think who/what/where/why. thank
you.

I suppose the thing to do is to break the problem into chunks. Ignore
the
memory management problem to begin with. Write a program to read a
single
province's worth of data into a fixed structure.Your struct provinces
isn't
going to hack it, is it? It only holds a single coordinate. perhaps an
array of
coordinates would be better. With provinces pointing to it. Consider:-

struct cordsys {
int y, x, length
};

struct provinces {
int number;
int type;
struct cordsys *cord; // pointer to coord_table
};

struct cordsys coord_table [64]; /* larger than expected number of
entries */

Then do the i/o stuff. Then read up on linked lists. Since you don't
know
how many cordinates or provinces there are in advance a linked lists
seems
a good choice. I cannot be certain as I don't know what you are going
to do
with the data...

So for i/o use fgets(), sscanf()
for memory allocation malloc(), free()

If you're still stuck you need to explain which bit you have a problem
with.
 
N

Nick Keighley

Steve Chow wrote:

creating a new cord array (while keeping the old one) with each row.
when it hits a number that matches the beginning cord. i need it to add
a new province array (while keeping the old one)

<snip>

you might take a look at realloc() as well
 
B

Barry Schwarz

I have two structures;

struct cordsys {
int y, x, length
};

struct provinces {
int number;
int type;
struct cordsys cord;
};

and a file that looks like:

1
68 78 83
69 78 87
70 78 89
71 78 91
72 78 93
73 77 95
1

2
110 77 180
111 77 182
112 77 184
113 76 186
114 76 188
115 76 189
116 76 191
117 76 192
2
................

what i need to do is read the beginning number into provinces.number.
and read the next rows. with three numbers each. read into
provinces.cords.y provinces.cord.x provinces.cord.length

creating a new cord array (while keeping the old one) with each row.

cord is not an array. It is an instance of a single struct cordsys
inside a struct provinces. From your description, I believe you want
an array of such cordsys in each struct provinces.

If the number of elements of this array is constant across all
struct provinces, then simply declare it an array in the declaration
of struct provinces.

If the number of elements varies among the different
provinces, then change cord from a struct cordsys to a pointer to
struct cordsys. You can then allocate memory for the pointer to point
to and also reallocate when necessary.
when it hits a number that matches the beginning cord. i need it to add
a new province array (while keeping the old one)

If you don't know how many struct provinces you will need, then define
a pointer to struct provinces and allocate memory for it to point to.
As above, you can reallocate memory when the need arises.
i'm new to c so know nothing about memory management. not asking anyone
to do my work also. just need a detailed explanation of the concepts,
possibly functions, and a general idea. think who/what/where/why. thank
you.

The memory allocation functions are malloc and realloc. You should
also free (using the function of that name) any memory allocated when
you are done with it.


Remove del for email
 
S

Steve Chow

i'm sorry it was a misprint. i meant *cords.
here is my current code. can't seem to figure out why it's crashing.

--NOTE; i changed the block indentifer from the file from an int to
array as well as some other things. I also don't intend to keep the
while(1) just there for testing

typedef struct
{
int y;
int xl;
int xr;
}Cords;

typedef struct
{
char *name;
char type;

Cords *cords;
}State;

void loadmap(State *t_states)
{
FILE *mapfile =
fopen("map.tbl", "r");

Cords t_cords;

int s_s = 0, s_c = 0;

fscanf(mapfile, "%s", &t_states[s_s].name);

t_states[s_s].cords =
malloc(sizeof(Cords)*1);

while(1)
{
if(fscanf(mapfile, "%d %d %d", &t_states[s_s].cords[s_c].y,
&t_states[s_s].cords[s_c].xl, &t_states[s_s].cords[s_c].xr)
< 3)
{
t_states = realloc(t_states, sizeof(State)*1);
fscanf(mapfile, "%s", &t_states[++s_s].name);
s_c = 0;
}

printf("%d %d %d\n", t_states[s_s].cords[s_c].y,
t_states[s_s].cords[s_c].xl, t_states[s_s].cords[s_c].xr);

t_states[s_s].cords =
realloc(t_states[s_s].cords, sizeof(Cords)*1);

s_c++;
}
}
 
S

Steve Chow

sorry meant to include the actual error

268 232 258
269 234 254
270 238 252
875704842 808727840 892679456 <--- Right where it hits the string and
is supposed to allocate a new state
*** glibc detected *** realloc(): invalid pointer: 0xb7f628dd ***
Aborted
 
N

Nick Keighley

Steve said:
i'm sorry it was a misprint. i meant *cords.

*what* was a misprint? If you need to refer to a previous post then
put it in the post- as I have done.
here is my current code. can't seem to figure out why it's crashing.

nor can I. Could you post a complete program?
--NOTE; i changed the block indentifer from the file from an int to
array as well as some other things. I also don't intend to keep the
while(1) just there for testing

typedef struct
{
int y;
int xl;
int xr;
}Cords;

typedef struct
{
char *name;
char type;

Cords *cords;
}State;

void loadmap(State *t_states)
{

we don't know what t_states is pointing at. Did you allocate space
for name?
FILE *mapfile =
fopen("map.tbl", "r");

always check the return value of fopen()
Cords t_cords;

int s_s = 0, s_c = 0;

fscanf(mapfile, "%s", &t_states[s_s].name);

fscanf() is potentially dangerous. Did you really mean to pass a
char**?
Remove the &. It is good practice to check the return value.
t_states[s_s].cords =
malloc(sizeof(Cords)*1);

always check the return value of malloc(). Why *1?
while(1)
{
if(fscanf(mapfile, "%d %d %d", &t_states[s_s].cords[s_c].y,
&t_states[s_s].cords[s_c].xl, &t_states[s_s].cords[s_c].xr)
< 3)
{

why <3? If I remember correctly fscanf() returns the number of items
read. So you only reallocate when you have a failure?
t_states = realloc(t_states, sizeof(State)*1);

and if realloc() fails? You should assign to a temporary, check for
NULL then assign. This function can't modify t_states as far as the
caller
is concerned because it's only a State*. It needs to be a State**. Why
*1?
Won't this always allocate a block of the same size? I think you need
to
re-read the realloc() documentation.
fscanf(mapfile, "%s", &t_states[++s_s].name);
s_c = 0;
}

printf("%d %d %d\n", t_states[s_s].cords[s_c].y,
t_states[s_s].cords[s_c].xl, t_states[s_s].cords[s_c].xr);

how many times does it loop?
t_states[s_s].cords =
realloc(t_states[s_s].cords, sizeof(Cords)*1);

again all the things I said before about realloc()
s_c++;
}
}

fix the things above. Work out how to terminate the loop. Add trace
prints so you can see what it's doing. If you still have a problem
post a ***short but complete program***
 
B

Ben Bacarisse

i'm sorry it was a misprint. i meant *cords. here is my current code.
can't seem to figure out why it's crashing.

It crashed because you were lucky this time. Had you been unlucky, you
would not have discovered that you program is wrong until much later!
typedef struct
{
int y;
int xl;
int xr;
}Cords;

typedef struct
{
char *name;
char type;

Cords *cords;
}State;

void loadmap(State *t_states)
{
FILE *mapfile =
fopen("map.tbl", "r");

Cords t_cords;

int s_s = 0, s_c = 0;

fscanf(mapfile, "%s", &t_states[s_s].name);

1. name is an uninitialised pointer to char. Where is the string supposed
to go? You have not allocated any memory to store it.

2. Don't use fscanf's %s format because it can read an uncontrolled number
of characters and might thus overflow any buffer you read into. Use fgets
or at the very least put maximun size into the format.
t_states[s_s].cords =
malloc(sizeof(Cords)*1);

You allocate space for one set of Cords but this:

suggests that you plan to read lots. You have nowhere to put them.
{
if(fscanf(mapfile, "%d %d %d", &t_states[s_s].cords[s_c].y,
&t_states[s_s].cords[s_c].xl, &t_states[s_s].cords[s_c].xr) < 3)
{
t_states = realloc(t_states, sizeof(State)*1); fscanf(mapfile, "%s",
&t_states[++s_s].name); s_c = 0;
}

printf("%d %d %d\n", t_states[s_s].cords[s_c].y,
t_states[s_s].cords[s_c].xl, t_states[s_s].cords[s_c].xr);

t_states[s_s].cords =
realloc(t_states[s_s].cords, sizeof(Cords)*1);

s_c++;
}
}

I would suggest some more functional decomposition. Write a function to
safely read a name. Use a large fixed-size buffer for example and then
return a copy of the (shorter) string actually read. Write one that can
fill a Cords structure. Write another that can read lots of Cords and
return a copy of the array of Cords actually seen and so one. Test each
one really well before moving on.

If you don't like the idea of copying like this then you will either need
to read your data twice (to count things first) or use a structure that
can grow like a linked list.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,175
Messages
2,570,944
Members
47,491
Latest member
mohitk

Latest Threads

Top