#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h> // sqrtf
#include <limits.h> // INT_MAX
#include <string.h> // strcmp, strlen, strcat
#include <time.h> // time.NULL
int logger = 0;
struct obj_t {
int id;
float x;
float y;
};
struct cluster_t {
int size;
int capacity;
struct obj_t *obj;
};
void point_ctor(struct obj_t *p,int id, float x, float y){
p->id = id;
p->x = x;
p->y = y;
}
void init_cluster(struct cluster_t *c, int cap)
{
assert(c != NULL);
assert(cap >= 0);
// TODO
c->capacity = cap;
c->size = 0;
c->obj = NULL;
}
/// Chunk of cluster objects. Value recommended for reallocation.
const int CLUSTER_CHUNK = 10;
struct cluster_t *resize_cluster(struct cluster_t *c, int new_cap)
{
// TUTO FUNKCI NEMENTE
assert(c);
assert(c->capacity >= 0);
assert(new_cap >= 0);
if (c->capacity >= new_cap)
return c;
size_t size = sizeof(struct obj_t) * new_cap;
void *arr = realloc(c->obj, size);
if (arr == NULL)
return NULL;
c->obj = (struct obj_t*)arr;
c->capacity = new_cap;
return c;
}
void append_cluster(struct cluster_t *c, struct obj_t obj)
{
// TODO
if(c->size == c->capacity){
resize_cluster(c,(c->capacity) 1);
}
c->size = 1;
//point musim pridat c->obj[(c->size)-1] strukt arg 2
c->obj[((c->size)-1)].id = obj.id;
printf("TUSOM");
c->obj[(c->size)-1].x = obj.x;
printf("TUSOM");
c->obj[(c->size)-1].y = obj.y;
printf("TUSOM");
}
void print_cluster(struct cluster_t *c)
{
// TUTO FUNKCI NEMENTE
for (int i = 0; i < c->size; i )
{
if (i) putchar(' ');
printf("%d[%g,%g]", c->obj[i].id, c->obj[i].x, c->obj[i].y);
}
putchar('\n');
}
void print_clusters(struct cluster_t *carr, int narr)
{
printf("Clusters:\n");
for (int i = 0; i < narr; i )
{
printf("cluster %d: ", i);
print_cluster(&carr[i]);
}
}
int load_clusters(char *filename, struct cluster_t **arr){
assert(arr != NULL);
FILE * obj;
assert(obj = fopen(filename, "r"));
//count init for number of objects
char tempcount[100]; char countnumbers[100]; int count;
int numberstart; int counter = 0;
fscanf(obj, "%s", tempcount);
for(int i = 0; i<strlen(tempcount); i ){
if(tempcount[i] == '='){
numberstart = i;
break;
}
}
for(int i = numberstart; i < strlen(tempcount); i ){
if(tempcount[i] >= 48 && tempcount[i] <= 57){
countnumbers[counter] = tempcount[i];
counter ;
}
}
assert(strlen(countnumbers) > 0);
count = atoi(countnumbers);
// Get ID, X, Y
int id, x, y, pos = 0;
struct obj_t point[count];
while(fscanf(obj, "%d %d %d", &id, &x, &y) == 3) {
// Build array
point_ctor(&point[pos],id,x,y);
arr[pos] = malloc(sizeof(struct obj_t));
init_cluster(arr[pos],count);
append_cluster(arr[pos], point[pos]);
printf("Object %d at X%f Y%f\n", arr[pos]->obj[pos].id,arr[pos]->obj[pos].x, arr[pos]->obj[pos].y);
pos ;
}
fclose(obj);
return 0;
}
int main(int argc, char *argv[])
{
struct cluster_t *cluster;
char extension[4];
strcpy(extension,".txt");
char subor[100];
strcpy(subor,argv[1]);
strcat(subor,extension);
load_clusters(subor, &cluster);
//print_clusters(&cluster[3],20);
// Lloydov algoritmus
return 0;
}
the program is run: ./program objekty
objekty - name of file without .txt
An example of an input file: "objekty.txt":
count=20
40 86 663
43 747 938
47 285 973
49 548 422
52 741 541
56 44 854
57 795 59
61 267 375
62 85 874
66 125 211
68 80 770
72 277 272
74 222 444
75 28 603
79 926 463
83 603 68
86 238 650
87 149 304
89 749 190
93 944 835
The problem seems to be at around in function append_cluster in line: c->obj[((c->size)-1)].id = obj.id; (line 150) A brief explanation before going through the code: Here are my structs:
```
struct obj_t {
int id;
float x;
float y;
};
struct cluster_t {
int size;
int capacity;
struct obj_t *obj;
};
```
Full code pastebin: https://pastebin.com/cffiDYBm
I make an array of cluster_t structs in main(); (struct cluster_t *cluster;)
I pass this array to a function load_clusters(filename, &cluster); Function def: int load_clusters(char *filename, struct cluster_t **arr)
I do some code and pass an index of the cluster array to an append function append_cluster(arr[pos], point[pos]); this function effectively adds a point at the end of the array. (resizes if needed) Function def: void append_cluster(struct cluster_t *c, struct obj_t obj);
The problem: I need to be able to change data of a specific obj_t in a cluster_t array (cluster_t->obj[n]).
The results being that my code stopped running and the line was not processed. Is there any other way to do this? Is it a small change in syntax? I'm out of ideas.
I tried:
c->obj[(c->size)-1].id = obj.id;
Also I made a function which did this for me but I got the same results:
void obj_ctor(struct obj_t *p, struct obj_t obj){
p->id = obj.id;
p->x = obj.x;
p->y = obj.y;
}
Here is the problem which should be as minimal as possible: (I'm trying to get both printfs on stdout)
#include <stdio.h>
#include <stdlib.h>
struct obj_t {
int id;
float x;
float y;
};
struct cluster_t {
int size;
int capacity;
struct obj_t *obj;
};
void obj_ctor(struct obj_t *p, struct obj_t obj){
p->id = obj.id;
p->x = obj.x;
p->y = obj.y;
}
void pass(struct cluster_t *p, struct obj_t add){
obj_ctor(&p->obj[0],add);
p->size = 1;
}
void pass1(struct cluster_t **arr){
struct obj_t o3;
o3.id = 1; o3.x = 2; o3.y = 3;
int count = 20;
int pos = 0;
while(pos < 3){
arr[pos]->capacity = 3;
arr[pos]->size = 0;
arr[pos]->obj = malloc(count*sizeof(struct obj_t));
pass(arr[pos], o3);
pos ;
}
}
int main(int argc, char *argv[])
{
printf("Testing");
struct cluster_t *test;
pass1(&test);
printf("GOT HERE");
}
CodePudding user response:
The final minimal example is nicely manageable — thank you. Here is a fairly straight-forward extension of that code. It is lazy in that it uses assert()
to enforce necessary properties.
It includes a function to dump the data in a struct cluster_t
structure. I regard such functions as a necessity — at the very least, they're extremely helpful. Quite often, I write them to take a FILE *fp
argument so that messages can be written to standard output, standard error or to a log file, or, indeed, anywhere you can point a file stream. Often, I'd have a separate dump_obj()
function that would be invoked from dump_cluster()
, but it doesn't seem necessary here.
The key point is that it ensures that test.obj
in main()
points to an array of 3 struct obj_t
. If you want dynamic memory allocation, changes are needed.
/* SO 7467-2430 */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
struct obj_t
{
int id;
float x;
float y;
};
struct cluster_t
{
int size;
int capacity;
struct obj_t *obj;
};
static void obj_ctor(struct obj_t *p, struct obj_t obj)
{
p->id = obj.id;
p->x = obj.x;
p->y = obj.y;
}
static void pass(struct cluster_t *p, struct obj_t add)
{
assert(p != NULL && p->obj != NULL);
assert(p->size < p->capacity);
obj_ctor(&p->obj[p->size], add);
p->size = 1;
}
static void dump_cluster(const char *tag, struct cluster_t *p)
{
printf("%s (%p):\n", tag, p);
if (p != NULL)
{
printf("size = %d, capacity = %d, objects = %p\n", p->size, p->capacity, p->obj);
for (int i = 0; i < p->size; i )
printf(" [%d] id = %d, pos = (%g, %g)\n", i, p->obj[i].id, p->obj[i].x, p->obj[i].y);
}
}
int main(void)
{
printf("Testing\n");
struct cluster_t test;
struct obj_t o1, o2, o3;
o1.id = 1;
o2.id = 2;
o3.id = 3;
o1.x = 1;
o2.x = 2;
o3.x = 3;
o1.y = 1;
o2.y = 2;
o3.y = 3;
test.capacity = 3;
test.size = 0;
struct obj_t arr[3];
test.obj = arr;
pass(&test, o3);
printf("GOT HERE\n");
dump_cluster("After adding 1", &test);
pass(&test, o2);
pass(&test, o1);
dump_cluster("After adding 3", &test);
return 0;
}
Example output (the addresses will probably differ for you):
Testing
GOT HERE
After adding 1 (0x7ffeed15b3b0):
size = 1, capacity = 3, objects = 0x7ffeed15b3c0
[0] id = 3, pos = (3, 3)
After adding 3 (0x7ffeed15b3b0):
size = 3, capacity = 3, objects = 0x7ffeed15b3c0
[0] id = 3, pos = (3, 3)
[1] id = 2, pos = (2, 2)
[2] id = 1, pos = (1, 1)