Structer pointer and pointer char array malloc array - c

I want to do structer array but I don't know structer array size therefore I need to use pointer structer and I want to do char array in the structer and I don't know char array size therefore I need to use pointer char in this structer but I don't understand malloc and realloc functions. How can I do this ?
#include <stdio.h>
#include <stdlib.h>
struct School{
char *school_name;
int student_size;
}*high_school;
void createSchool(struct School *s, char *schl_name, int student, int school_size)
{
int i = 0;
if(school_size == 1){
s = (struct School*) malloc(sizeof(struct School));
}
else{
s = (struct School*) realloc(s, (school_size*sizeof(struct School)));
}
(s+(school_size-1))->student_size = student;
(s+(school_size-1))->school_name = (char *) malloc(20); // 20 it is not important
(s+(school_size-1))->school_name = schl_name;
for(i; i<school_size; i++){
printf("%s\t%d\n",(s+i)->school_name, (s+i)->student_size);
}
printf("\n\n");
}
int main()
{
int i = 1;
createSchool(high_school, "Harvard", 50, i);
i++;
createSchool(high_school, "Oxford", 40, i);
i++;
createSchool(high_school, "MIT", 30, i);
}
I want to do screen shoot:
Harvard 50
Harvard 50
Oxford 40
Harvard 50
Oxford 40
MIT 30
but screen shoot of program :
Harvard 50
└1q 7405760
Oxford 40
7405760
(null) 0
MIT 30

Your pointer inside createSchool has local scope, so global pointer is not modified. Faster fix is to return new allocated memory back to caller.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct School{
char *school_name;
int student_size;
}*high_school;
struct School* createSchool(struct School *s, char *schl_name, int student, int school_size)
{
if(school_size == 1)
{
s = malloc(sizeof(struct School));
}
else
{
s = realloc(s, (school_size*sizeof(struct School)));
}
if (s != NULL)
{
s[school_size-1].student_size = student;
s[school_size-1].school_name = malloc(strlen(schl_name)+1);
strcpy(s[school_size-1].school_name, schl_name);
for(int i=0; i<school_size; i++)
{
printf("%s\t%d\n", s[i].school_name, s[i].student_size);
}
printf("\n\n");
}
return s;
}
int main(void)
{
int i = 1;
high_school = createSchool(high_school, "Harvard", 50, i);
i++;
high_school = createSchool(high_school, "Oxford", 40, i);
i++;
high_school = createSchool(high_school, "MIT", 30, i);
}
Minimal signature for main is int main (void)
Take note that malloc/realloc returned value have to be checked.
With your code, in case of realloc fails, you are loosing the pointer to the already allocated memory. So you should use a temp pointer to store the realloc result and check for integrity. After that you can reassign it ot your pointer.
struct School* createSchool(struct School *s, char *schl_name, int student, int school_size)
{
if(school_size == 1){
s = malloc(sizeof(struct School));
}
else
{
struct School *temp = realloc(s, (school_size*sizeof(struct School)));
if (temp == NULL)
return s;
s = temp;
}
if (s != NULL)
{
s[school_size-1].student_size = student;
s[school_size-1].school_name = malloc(strlen(schl_name)+1);
strcpy(s[school_size-1].school_name, schl_name);
for(int i=0; i<school_size; i++)
{
printf("%s\t%d\n", s[i].school_name, s[i].student_size);
}
printf("\n\n");
}
return s;
}
Different solution can be implemented using double pointer:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct School{
char *school_name;
int student_size;
}*high_school;
void createSchool(struct School **s, char *schl_name, int student, int school_size)
{
if(school_size == 1)
{
*s = malloc(sizeof(struct School));
}
else
{
struct School *temp = realloc(*s, (school_size*sizeof(struct School)));
if (temp == NULL)
return;
*s = temp;
}
if (*s != NULL)
{
(*s)[school_size-1].student_size = student;
(*s)[school_size-1].school_name = malloc(strlen(schl_name)+1);
strcpy((*s)[school_size-1].school_name, schl_name);
for(int i=0; i<school_size; i++)
{
printf("%s\t%d\n", (*s)[i].school_name, (*s)[i].student_size);
}
printf("\n\n");
}
}
int main(void)
{
int i = 1;
createSchool(&high_school, "Harvard", 50, i);
i++;
createSchool(&high_school, "Oxford", 40, i);
i++;
createSchool(&high_school, "MIT", 30, i);
}
Last thing take note that,to assign the name of school you can simply use:
(*s)[school_size-1].school_name = schl_name;

Related

Memory allocation of an array of struct in a C function

I am trying to pass the pointer to a struct to a function to create an array of the struct there. The overall idea is:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct items
{
int number;
char *name;
char *description;
} ITEMS;
int process(ITEMS **items)
{
int i = 0, something = 200;
// for loop is for the representation.
// The actual data come from MySQL row loop
for (int j = 100; j < something; j++)
{
// Growing the array of struct
items = realloc(items, (i + 1) * sizeof(*items));
// Adding items here
items[i]->number = j;
strcpy(items[i]->name, "Some name"); // it comes from a variable
strcpy(items[i]->description, "Some text");
i++;
}
return i;
}
int main()
{
ITEMS *items;
int num_items = process(&items);
for (int i = 0; i < num_items; i++)
{
printf("%d - %s - %s\n", items[i].number, items[i].name,
items[i].description);
}
return 0;
}
but I am struggling with reallocating the memory for the struct (and with the pointers too).
The pointer to pointer must be de-referenced in the function so the allocation is visible in the calling function.
strdup is use to allocate memory to the pointers in the structure.
It is better to use a temporary variable for the reallocation.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct items
{
int number;
char *name;
char *description;
} ITEMS;
int process(ITEMS **items)
{
int i = 0;
// Growing the array of struct
*items = realloc(*items, (i + 1) * sizeof(**items));
// repeating this step in a loop of adding items
// Adding items here
(*items)[i].number = 72;
(*items)[i].name = strdup( "Some name"); // it comes from a variable
(*items)[i].description = strdup ("Some text");
i++;
*items = realloc(*items, (i + 1) * sizeof(**items));
// another item
(*items)[i].number = 88;
(*items)[i].name = strdup( "Some name"); // it comes from a variable
(*items)[i].description = strdup ("Some text");
i++;
return i;
}
int main()
{
ITEMS *items = NULL;
int num_items = process(&items);
for (int i = 0; i < num_items; i++)
{
printf("%d - %s - %s\n", items[i].number, items[i].name, items[i].description);
}
return 0;
}
With better error detection
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct items
{
int number;
char *name;
char *description;
} ITEMS;
int process(ITEMS **items)
{
ITEMS *temp = NULL;
int i = 0;
// Growing the array of struct
if ( NULL == ( temp = realloc(*items, (i + 1) * sizeof(**items)))) {
fprintf ( stderr, "realloc problem\n");
return i;
}
*items = temp;
// repeating this step in a loop of adding items
// Adding items here
(*items)[i].number = 72;
(*items)[i].name = strdup( "Some name"); // it comes from a variable
(*items)[i].description = strdup ("Some text");
i++;
if ( NULL == ( temp = realloc(*items, (i + 1) * sizeof(**items)))) {
fprintf ( stderr, "realloc problem\n");
return i;
}
*items = temp;
// another item
(*items)[i].number = 88;
(*items)[i].name = strdup( "Some name"); // it comes from a variable
(*items)[i].description = strdup ("Some text");
i++;
return i;
}
int main()
{
ITEMS *items = NULL;
int num_items = process(&items);
for (int i = 0; i < num_items; i++)
{
printf("%d - %s - %s\n", items[i].number, items[i].name, items[i].description);
}
return 0;
}

Function to add struct to another struct in C

so I have 3 structs here:
typedef struct {
char *name; // allocated
int commonality;
int weight;
} monster;
typedef struct {
char *name; // allocated
char *description; // allocated
double area;
int monsters;
monster **monsters; // allocated
} region;
typedef struct {
char *name; // allocated
double diameter;
int regions;
region **regions; // allocated
} planet;
I already have function:
monster *new_monster(char *name, int commonality, int weight);
I am trying to create these functions:
void add_monster_to_region(region *r, char *mname, int mcommonality, int weight);
void delete_region_from_planet(planet *p, char *rname);
This is what I have so far, but I don't believe it's right, can anyone tell me what I'm doing wrong and how I can fix it?
void add_monster_to_region(region *r, char *mname, int mcommonality, int mweight)
{
for (int i = 0; i < mcommonality; i++)
{
if (strcmp(mname, r->monsters[i]->name) == 0)
{
r->monsters[i]->name = mname;
}
}
}
Thank you
It would be very helpful to have a minimal reproducible example. It would also clarify what was meant with fully allocated NOT a reference array.
Nevertheless, here is my take on how to create a planet, two regions and how to populate the regions with monsters:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char *name; // allocated
int commonality;
int weight;
} monster;
typedef struct {
char *name; // allocated
char *description; // allocated
double area;
int monster_count;
monster **monsters; // fully allocated, NOT a reference array
} region;
typedef struct {
char *name; // allocated
double diameter;
int region_count;
region **regions; // fully allocated, NOT a reference array
} planet;
monster *new_monster(char *name, int commonality, int weight) {
monster *new_monster = calloc(sizeof(monster), 0);
if (new_monster != NULL) {
new_monster->name = strdup(name);
if (new_monster->name == NULL) {
free(new_monster);
return NULL;
}
new_monster->commonality = commonality;
new_monster->weight = weight;
}
return new_monster;
}
void free_monster(monster *the_monster) {
if (the_monster != NULL) {
if (the_monster->name != NULL) {
free(the_monster->name);
}
free(the_monster);
}
}
void add_monster_to_region(region *r, char *mname, int mcommonality, int mweight)
{
monster *a_monster = new_monster(mname, mcommonality, mweight);
if (a_monster == NULL) return; // no memory
monster **monsters = NULL;
if (r->monsters != NULL) {
monsters = realloc(r->monsters, (r->monster_count + 1) * sizeof(monster *));
} else {
monsters = calloc(sizeof(monster *), 0);
}
if (monsters == NULL) {
free_monster(a_monster);
return; // no memory
}
r->monsters = monsters;
r->monsters[r->monster_count] = a_monster;
r->monster_count++;
}
void delete_region_from_planet(planet *p, char *rname) {
// TODO
}
int main() {
region desert = {"Desert", "Sunny and warm place.", 50.0, 0, NULL};
region ocean = {"Ocean", "Huge wet place.", 500.0, 0, NULL};
region *regions[] = {&desert, &ocean};
planet mud = {"Mud", 100.00, 2, regions};
add_monster_to_region(&desert, "Bug", 100, 100);
add_monster_to_region(&desert, "Zombie", 10, 20);
add_monster_to_region(&ocean, "Shark", 20, 40);
for (int i = 0; i < mud.region_count; i++) {
for (int j = 0; j < mud.regions[i]->monster_count; j++) {
printf("%s %d %d\n",
mud.regions[i]->monsters[j]->name,
mud.regions[i]->monsters[j]->commonality,
mud.regions[i]->monsters[j]->weight
);
}
}
// TODO: release allocated memory
return 0;
}
We can see all monsters in all regions of the defined planet:
$ gcc -Wall monsters.c
$ ./a.out
Bug 100 100
Zombie 10 20
Shark 20 40
$

how do I deal with this segmentation error

I keep receiving the same message "segmentation fault: 11"
gdb tells me that the break point is just after the main function. in the line where I declare the int j;
i really do not understand how can that possibly break the code.
the input this function reads is made up of simply 1 string followed by 2 numbers like
john 22 43 sam 11 23
all it's supposed to do is simply to store the entire input in "elenco" and then print the strings.
first i created a struct that matches the input.
then i made a function with the purpose of reading the input and store in a variable.
then i made a function whose variables is the output of the function that read the input ( so the input ) and that prints the strings given
can anybody help me identify the problem and solve it?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char name[20];
int distance;
int point;
} throw;
throw *read_file(FILE *f, int *j)
{
int i = 0;
int c;
int Dim = 32;
char buf[1000];
throw *list;
list = malloc(Dim *sizeof(*list));
if (list == NULL)
{
(*j) = 0;
return NULL;
}
while (fgets(buf, sizeof(buf), f)!= NULL)
{
sscanf(buf, "%19s %d %d",
list[*j].name,
&list[*j].distance,
&list[*j].point);
*j += 1;
if ( *j >= Dim)
{
Dim = Dim*2;
list = realloc(list, Dim *sizeof(*list));
if (list == NULL)
{
return NULL;
}
}
}
return list;
}
void print_everything(throw *list, int j)
{
int c;
for (c=0; c < j; c++ )
{
printf("%d\n",list[c].distance);
}
}
int main(int argc,const char *argcv[])
{
int j = 0;
FILE *file;
throw *list;
if (!( argc != 3))
{
printf("file's dimension is wrong\n");
return -1;
}
file = fopen(argcv[1], "r");
list = read_file(file, &j);
print_everything(list, j);
fclose(file);
return 0;
}
input1.txt
Mario 20 30
Giorgio 30 40
Mario 40 40
Davide 32 20
Mario 9 32
that is exactly what the file contained
Your program is fine. Your problem is in input1.txt , you need
Mario 20 30
Giorgio 30 40
Mario 40 40
Davide 32 20
Mario 9 32
Each line needs a \n as you read with fgets()
Made some changes on you code you are making the use of the lists wrong try to use pointers
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSTR 250
typedef struct elenco
{
char *name;
int distance;
int point;
struct elenco *next;
} throw;
throw *list_add(throw *list, int distance, int point, const char *name)
{
throw *new = malloc(sizeof(throw));
if (new != NULL) {
new->distance = distance;
new->point = point;
new->name =(char*)malloc(strlen(name)+1);
strcpy(new->name,name);
new->next = list;
return new;
}
return list;
}
throw *read_file(FILE *f)
{
char buf[MAXSTR];
throw *list = malloc(sizeof(throw));
while (fgets(buf, sizeof(buf), f)!= NULL)
{
char name[MAXSTR];
int distance;
int point;
sscanf(buf, "%s %d %d",
name,
&distance,
&point);
list = list_add(list, distance, point, name);
}
return list;
}
void print_everything(throw *list)
{
while (list) {
printf("%d\n",list->distance);
list = list->next;
}
}
int main()
{
int argc;
const char *argcv;
FILE *file;
if (!( argc != 3))
{
printf("file's dimension is wrong\n");
return -1;
}
file = fopen(&argcv[1], "r");
throw *list = read_file(file);
print_everything(list);
fclose(file);
return 0;
}

Function to read in a word into a struct array

I am having an error with the code we are using, was wondering if someone could help debug. Seems like we are getting a malloc error. Thanks.
void readWords(char norm_word[MAXSIZE], Word ** array) {
int i = 0;
bool found = false;
int result = 0;
Word * current_pointer = malloc (sizeof(Word*));//creates a temporary variable for each pointer in the array
for (i=0; i<word_counter; i++) {
current_pointer = *(array+i); //accesses the current pointer
result = strcmp(norm_word, (current_pointer -> word)); //compares the string to each stored string
if (result == 0) {
found = true;
(current_pointer->freq)++;
break;
}
}
if(!found) {
if(pointer_counter == word_counter) {
array = realloc(array, sizeof(array)*2);
pointer_counter*=2;
}
Word * new_pointer = (Word*) malloc (sizeof(Word*));
strcpy(new_pointer -> word, norm_word);
*(array + (pointer_counter - 1)) = new_pointer;
word_counter++;
}
;
}
All pointers have the same size on your system. So a sizeof always returns the same size for any pointer. You want to allocate for the structure, so you need to use sizeof on the name without the star. malloc will return the pointer to that block of memory afterwards.
Here is a short implementation:
#include <iostream>
#include <string>
typedef struct
{
int num;
int numnum;
}numbers;
int main(int argc, char ** argv)
{
numbers* n = (numbers*)malloc(sizeof(numbers));
n->num = 1;
n->numnum = 2;
free(n);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAXSIZE 64
typedef struct word {
char word[MAXSIZE];
int freq;
} Word;
int word_counter = 0;
size_t pointer_counter = 16;//Number of pointers that ensure
void readWords(char norm_word[MAXSIZE], Word ** array) {
int i = 0;
bool found = false;
Word *current_pointer = *array;
for (i=0; i<word_counter; i++) {
if(strcmp(norm_word, current_pointer->word) == 0){
found = true;
current_pointer->freq++;
break;
}
++current_pointer;
}
if(!found) {
if(pointer_counter == word_counter) {
pointer_counter *= 2;
*array = realloc(*array, sizeof(Word)*pointer_counter);
}
Word *new_pointer = *array + word_counter;
new_pointer->freq = 1;
strcpy(new_pointer->word, norm_word);
++word_counter;
}
}
int main(void){
Word *vocabulary = calloc(pointer_counter, sizeof(Word));
char norm_word[MAXSIZE];
while(1==scanf("%s", norm_word)){
readWords(norm_word, &vocabulary);
}
{
int i;
for(i = 0; i < word_counter; ++i){
printf("%s(%d)\n", vocabulary[i].word, vocabulary[i].freq);
}
}
free(vocabulary);
return 0;
}

Array of Structs strange output?

Can anyone give me some indication as to why array of structs doesn't print out properly ?
I think its something to do with the memory I have allocated to the struct I am unsure !!
Using mac osx mountain lion xcode 4 gcc
Thanks for any help completely stuck!!
(Please have patience I am only a student !)
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
typedef struct{
char* one;
char* two;
} Node;
Node *nodes;
int count = 0;
//-----------------------------------------------------------------------
void add(char *one,char*two){
char x[40];
char y[40];
printf("reached..\n");
strcpy(x,one);
strcpy(y,two);
printf("--> X: %s\n",x);
printf("--> Y: %s\n",y);
Node newNode;
newNode.one = x;
newNode.two = y;
nodes[count]= newNode;
count++;
}
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
void print(){
int x;
for (x = 0; x < 10; x++)
{
printf("%d : (%s, %s) \n",x,nodes[x].one, nodes[x].two);
}
}
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
void check(char **arg)
{
if(strcmp(*arg, "Add") == 0)
{
add(arg[1],arg[2]);
}else if(strcmp(*arg,"print") == 0)
{
print();
}else{
printf("Error syntax Enter either: \n Add [item1][item2]\n OR \n print\n");
}
}
//-----------------------------------------------------------------------
void readandParseInput(char *line,char **arg)
{
if (fgets (line, 512, stdin)!= NULL) {
char * pch;
pch = strtok (line," \n\t");
int count = 0;
arg[0] = pch;
while (pch != NULL)
{
count++;
pch = strtok (NULL, " \n\t");
arg[count] =pch;
}
}else{
printf("\n");
exit(0);
}
}
//-----------------------------------------------------------------------
int main()
{
int size = 100;
nodes = calloc(size, sizeof(Node));
int i;
for(i = 0;i <100; i++){
printf("%s , %s \n",nodes[i].one,nodes[i].two );
// nodes[i].one = ".";
// nodes[i].two = ".";
}
char line[512]; /* the input line */
char *arg[50]; /* the command line argument */
while (1)
{
readandParseInput(line,arg);
if(arg[0] != NULL){
check(arg);
}
}
return(0);
}
You're keeping pointers to the following automatic variables:
char x[40];
char y[40];
These go out of scope when add() returns, leaving you with dangling pointers.
You either have to turn Node::one and Node::two into arrays, or allocate memory for them on the heap.
In you add() function, you cannot assign one struct to another via an = operator... you would have to copy it...
memcpy( &nodes[count], &newNode )
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char *fn;
}NAME;
#define NAME_LEN 20
int main()
{
NAME name;
name.fn = (char *) calloc(NAME_LEN, sizeof(char));
strcpy(name.fn, "Namco");
printf("Name: %s\n", name.fn);
free(name.fn);
return 0;
}
you can't just assign a string like this in c
newNode.one = x;
newNode.two = y;
what is newNode.one referring to???
at Function add
newNode.one = x;
newNode.two = y;
to
newNode.one = strdup(x);
newNode.two = strdup(y);

Resources