How to dynamically allocate vector and struct in a code? - c

I'm trying to allocate a struct and an array in the code below, but I have no idea how to proceed.
I'm trying to do this without adding other libraries.
It's in portuguese so I'm sorry if you don't understant the meaning.
struct RegistroAluno{
int Matricula;
char Nome[20];
int AnoNascimento;
};
int main()
{
int QuantidadeAlunos;
printf("Quantos alunos serão armazenados?\n");
scanf("%i", &QuantidadeAlunos);
struct RegistroAluno P1[QuantidadeAlunos];
struct *P1=(int *)malloc(QuantidadeAlunos*sizeof(struct));
for(int i=0; i<QuantidadeAlunos; i++){
printf("Qual a matrícula do aluno?\n");
scanf("%i", &P1[i].Matricula);
}/* I gotta do the same to all the other elements of the struct*/
return 0;
}
I'm trying to allocate a struct and an array

You allocate a variable length array (VLA) of struct RegistroAluno here:
struct RegistroAluno P1[QuantidadeAlunos];
Alternatively, you can allocate the array dynamically like this:
struct RegistroAluno *P1 = malloc(QuantidadeAlunos*sizeof(*P1));
Here the complete program with includes and error handling:
#include <stdlib.h>
#include <stdio.h>
struct RegistroAluno{
int Matricula;
char Nome[20];
int AnoNascimento;
};
int main(void) {
printf("Quantos alunos serão armazenados?\n");
int QuantidadeAlunos;
if(scanf("%i", &QuantidadeAlunos) != 1) {
printf("scanf failed\n");
return 1;
}
if(QuantidadeAlunos < 1) {
printf("QuantidadeAlunos must be > 0\n");
return 1;
}
struct RegistroAluno *P1 = malloc(QuantidadeAlunos*sizeof(*P1));
if(!P1) {
printf("malloc failed\n");
return 1;
}
for(int i=0; i<QuantidadeAlunos; i++){
printf("Qual a matrícula do aluno?\n");
if(scanf("%i", &P1[i].Matricula) != 1) {
printf("scanf failed\n");
return 1;
}
}
}
and example session:
Quantos alunos serão armazenados?
2
Qual a matrícula do aluno?
3
Qual a matrícula do aluno?
4

Related

trying to add a variable of a certain type inside an array of that type

So i want to create an array of a structure that i made called jogo
Structure:
typedef struct jogo
{
int ident;/*idp of a product*/
char nome[1024]; /* string that describes a team eg. Barcelona */
char *equipas[2]; /*array of strings like {"Barcelona","Madrid"}*/
int score[2]; /*array of strings like {"Barcelona","Madrid"}*/
}* jogo;
I want to create an array without a specific size to store variables of type jogo.
When i type (add) a nome:equipa1:equipa2_score1:score2 like a elclassico:barcelona:madrid:1:0,i want to create a variable of type jogo and store it inside the array sistema_jog.
if i store something and the array is full i want reallocate the size of the array in order to store more variables of type jogo.
But for some reason im always getting segmentation fault core dumped when i try to do it and i dont know why.
Program:
#include<stdlib.h>
#include<stdio.h>
#include <string.h>
#define MAX_CHARS 1024 /* max characters of a word */
#define MAX_SIZE 5
int line = 1; /* counts the number of lines of the stdin */
static int size = MAX_SIZE;
int i = 0; /*ident of the variable jogo*/
int size_until = 0;
typedef struct jogo
{
int ident;/*idp of a product*/
char nome[MAX_CHARS]; /* string that describes a team eg. Barcelona */
char *equipas[2];
int score[2];
}* jogo;
jogo *sistema_jog;
void a(char nome[],char team1[],char team2[],int score1,int score2);
int team_not_in(char team1[],char team2[]);
int nome_in(char nome[]);
void cria_jogo(jogo s,char nome[],char equipa1[],char equipa2[],int score1,int score2);
int main() {
char c; char nome_jg[MAX_CHARS]; char eq1[MAX_CHARS]; char eq2[MAX_CHARS]; int pont1; int pont2;
sistema_jog = (jogo*) calloc(MAX_SIZE,sizeof(jogo));
while ((c = getchar())!= 'x') {
switch (c)
{
case 'a':
{
scanf("%1023[^:\n]:%1023[^:\n]:1023%[^:\n]:%d:%d",nome_jg,eq1,eq2,&pont1,&pont2);
i++;
printf("nome: %s",sistema_jog[0]->nome);
//a(nome_jg,eq1,eq2,pont1,pont2);
break;
}
}
}
return 0;
}
int nome_in(char nome[])
{
int i;
for(i=0; i < size; i++)
{
if (strcmp(sistema_jog[i]->nome,nome) == 0)
return 1;
}
return 0;
}
int team_not_in(char team1[],char team2[])
{
int i;
for (i=0;i<size;i++)
{
if((strcmp(sistema_jog[i]->equipas[0],team1) != 0) || (strcmp(sistema_jog[i]->equipas[1],team2) != 0))
return 1;
}
return 0;
}
void cria_jogo(jogo s,char nome[],char equipa1[],char equipa2[],int score1,int score2)
{
strcpy(s->nome,nome);
strcpy(s->equipas[0],equipa1);
strcpy(s->equipas[1],equipa2);
s->score[0] = score1;
s->score[1] = score2;
}
void a(char nome[],char team1[],char team2[],int score1,int score2)
{
int NL = line;
if (nome_in(nome) == 1)
printf("%d Jogo existente.",NL);
else if (team_not_in(team1,team2) == 0)
{
printf("%d Equipa existente.",NL);
}
else
{
jogo novo_jogo = (jogo) calloc(sizeof(jogo),sizeof(jogo));
cria_jogo(novo_jogo,nome,team1,team2,score1,score2);
if (size_until <= MAX_SIZE)
{
sistema_jog[size_until] = novo_jogo;
size_until++;
}
else
{
sistema_jog = (jogo*) realloc(system, sizeof(jogo)*size_until);
sistema_jog[size_until] = novo_jogo;
size_until++;
}
}
}
I am not surprised that you are confused.
As Christian Gibbons, Barmar and user12986714 said jogo must be your jogostruct and not a pointer to jogo. I supposed you changed, at some stage, } jogo; to }* jogo; because of compilation errors. But, it was not the original problem and after you are confused.
Let me explain shortly, try this basic code :
#include<stdlib.h>
#include<stdio.h>
#include <string.h>
#define MAX_CHARS 1024 /* max characters of a word */
#define MAX_SIZE 5
int line = 1; /* counts the number of lines of the stdin */
static int size = MAX_SIZE;
int i = 0; /*ident of the variable jogo*/
int size_until = 0;
typedef struct jogo
{
int ident;/*idp of a product*/
char nome[MAX_CHARS]; /* string that describes a team eg. Barcelona */
char *equipas[2];
int score[2];
}* jogo;
typedef struct jogo2
{
int ident;/*idp of a product*/
char nome[MAX_CHARS]; /* string that describes a team eg. Barcelona */
char *equipas[2];
int score[2];
} jogo2;
int main() {
printf("sizeof jogo %d\n",sizeof(jogo));
printf("sizeof jogo2 %d\n",sizeof(jogo2));
return 0;
}
As you could see jogo has a pointer size and jogo2 has the size of your struct.
More, there are various problems in your code. Everything is briefly commented directly in the code. Do not hesitate to ask questions.
#include<stdlib.h>
#include<stdio.h>
#include <string.h>
#define MAX_CHARS 1024
#define MAX_SIZE 5
int line = 1;
// static int size = MAX_SIZE; // Not useful. It is the same than MAX_SIZE
// int i = 0; this variable is not really used
int size_until = 0;
typedef struct jogo
{
// int ident; Never used
char nome[MAX_CHARS];
char equipas[2][1024]; // equipas is an array of two strings. If you use char *equipas[2], you will have to alloc memory for each string
int score[2];
} jogo; // * has been removed
jogo **sistema_jog; //sistema_jog is an array of pointer to jogo struct. You allocate it after.
// you could also have an array of jogo struct but it would need more modifications in your code.
// I suppose the confusion is here. To train, you could try to do : jogo * sistema_jog and to modify what it is needed in your code.
void a(char nome[],char team1[],char team2[],int score1,int score2);
int team_not_in(char team1[],char team2[]);
int nome_in(char nome[]);
void cria_jogo(jogo* s,char nome[],char equipa1[],char equipa2[],int score1,int score2); // *: s is a pointer to jogo struct. See comment on sistema_jog declaration
int main() {
char c; char nome_jg[MAX_CHARS]; char eq1[MAX_CHARS]; char eq2[MAX_CHARS]; int pont1; int pont2;
sistema_jog = (jogo**) calloc(MAX_SIZE,sizeof(jogo*)); // Each element of sistema_jog is a pointer to a jogo struct
while ((c = getchar())!= 'x') {
switch (c)
{
case 'a':
{
scanf("%1023[^:\n]:%1023[^:\n]:%1023[^:\n]:%d:%d",nome_jg,eq1,eq2,&pont1,&pont2); // be carefull, see % and 1023 in the third field of your code
// i++; not used elsewhere
a(nome_jg,eq1,eq2,pont1,pont2);
break;
}
}
}
// Only to check
for (int i=0; i<size_until;i++)
printf ("%s:%s:%s:%d:%d\n",
sistema_jog[i]->nome,
sistema_jog[i]->equipas[0],
sistema_jog[i]->equipas[1],
sistema_jog[i]->score[0],
sistema_jog[i]->score[1]);
return 0;
}
int nome_in(char nome[])
{
int i;
for(i=0; i < size_until; i++) // size_until : You have to check only elements that exist either you have less or more elements than size (static int = MAX_SIZE)
{
if (strcmp(sistema_jog[i]->nome,nome) == 0)
return 1;
}
return 0;
}
int team_not_in(char team1[],char team2[])
{
int i;
for (i=0;i<size_until;i++) // size_until : Idem as above
{
if((strcmp(sistema_jog[i]->equipas[0],team1) != 0) || (strcmp(sistema_jog[i]->equipas[1],team2) != 0))
return 1;
}
return 0;
}
void cria_jogo(jogo* s,char nome[],char equipa1[],char equipa2[],int score1,int score2) // * : s is a pointer to jogo struct
{
strcpy(s->nome,nome);
strcpy(s->equipas[0],equipa1);
strcpy(s->equipas[1],equipa2);
s->score[0] = score1;
s->score[1] = score2;
}
void a(char nome[],char team1[],char team2[],int score1,int score2)
{
int NL = line;
if (nome_in(nome) == 1)
printf("%d Jogo existente.",NL);
/* else if (team_not_in(team1,team2) == 0)
{
printf("%d Equipa existente.",NL);
} */ // I do not understand the objective of this test. So, I commented it. But it is not the question
else
{
jogo* novo_jogo = (jogo*) malloc(sizeof(jogo));
cria_jogo(novo_jogo,nome,team1,team2,score1,score2);
if (size_until < MAX_SIZE) // = has been removed. Index of array goes from 0 to size of array-1
{
sistema_jog[size_until] = novo_jogo;
size_until++;
}
else
{
sistema_jog = (jogo**) realloc(sistema_jog, sizeof(jogo**)*(size_until+1)); // *: see comment on sistema_jog declaration, +1: array index goes from 0 to size-1
// Remark : It is not efficient to realloc one by one. It would better to realloc MAX_SIZE by MAX_SIZE. You could try to do it
sistema_jog[size_until] = novo_jogo;
size_until++;
}
}
}

Allocate memory dynamically of a vector of struct

I can't access my pointer by index notation in main function. The way I'm passing the pointer as paramter to the functions, is that right ? I tried without the & and It didnt work neither. Here is my code:
//My Struct
typedef struct{
int a;
double d;
char nome[20];
}contas;
//Function to allocate memory
void alloca_vetor(contas *acc, int linhas){
acc = malloc(linhas * sizeof(contas));
if(acc == NULL){
printf("ERRO AO ALOCAR MEMORIA\n");
exit(0);
}
printf("ALLOCATION SUCCESSFUL");
}
//Function to fill the vector
void fill_vetor(contas *acc, int linhas){
int i,a;
for(i=0; i< linhas; i++){
acc[i].a = i;
}
printf("FILL SUCCESSFUL !\n");
for(i=0; i< linhas; i++){
printf("%i\n", acc[i].a);
}
}
int main()
{
int i, num_linhas = 5;
contas *array;
alloca_vetor(&array, num_linhas);
fill_vetor(&array, num_linhas);
// ERROR HAPPENS HERE - Segmentation Fault
for(i=0; i < num_linhas; i++){
printf("%i\n", array[0].a);
}
free(array);
return 0;
}
Rewrite function alloca_vetor the following way
void alloca_vetor( contas **acc, int linhas ){
*acc = malloc(linhas * sizeof(contas));
if(*acc == NULL){
printf("ERRO AO ALOCAR MEMORIA\n");
exit(0);
}
printf("ALLOCATION SUCCESSFUL");
}
And call function fill_vetor like
fill_vetor(array, num_linhas);

Dynamically allocating array of struct from file C

I have a program that i am trying to write that will open a file named hw3.data, this file will contain a string, a float, an int, and a string on each line. Example: someword 5.4 200000 someword
I do not know the size of the file or the size of the strings within the file. I need to dynamically allocate at array of struct to store the info. I am fairly new to C and have looked over other various questions and articles however none of them really helped me grasp how to solve this.
I figured the best way to go about solving this was to first statically declare a structure. Read the file for the length and then take the information from the static struct and then dynamically allocate.
Here is my code thus far:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
//Static Array of Struct
struct record{
char name[100];
float hp;
int size;
char color[30];
};
//getData from file
int getData(FILE*, struct record[], int currSize){
fp = fopen("hw3.data","r");
if (fp !=NULL){
printf("file Open");
while(3==fscanf(fp, "[^,],%f,%d,[^,]", records[i].name &records[i].hp, &records[i].size, records[i].color)){
currSizef++;
}
} else {
printf("failed");
}
return 0;
}
//First sorting function to sort by FLOAT value
//Second sorting function to sort by INT value
int main()
{
int currSizef=0;
struct record *records;
FILE* fp = NULL;
int choice;
//menu
do
{
printf("\t\tMenu\n");
printf("Options:\n");
printf("Input a number to select option:\n");
printf("1-Sort floats high to low\n 2-Sort floats low to high\n");
printf("3-Sort intergers high to low\n 4-Sort intergers low to high\n");
printf("5-Exit\n");
scanf("%d", &choice);
switch (choice)
{
case 1: /*Print high to low floats*/
break;
case 2: /*print low to high floats*/
break;
case 3: /*print high to low ints*/
break;
case 4: /*print low to high ints*/
break;
}
}while(choice !=5);
return 0;
}
You can try loading the data to a temporary record and use realloc to dynamically extend the data size.
NOTE: if NULL is passed to realloc then realloc will behave like the malloc function for the specified size.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//Static Array of Struct
typedef struct record{
char name[100];
float hp;
int size;
char color[30];
}RECORD;
void record_copy(RECORD *dest, RECORD* src) {
strcpy(dest->name,src->name);
dest->hp = src->hp;
dest->size = src->size;
strcpy(dest->color,src->color);
}
//LoadData from file
RECORD* LoadData(FILE* fp,int *size){
int i = 0;
RECORD temp;
RECORD *data= NULL,*tempptr = NULL;
while( fscanf(fp, "%[^,],%f,%d,%[^,],", temp.name,&temp.hp,&temp.size,temp.color)==4 ) {
if( (tempptr = (RECORD*) realloc( data, sizeof(RECORD) * (i+1) )) )
data = tempptr;
else
return (NULL);
record_copy(&data[i],&temp);
i++;
}
*size = i;
return (data);
}
void record_sort(RECORD *data, int size) {
int i,j;
RECORD temp;
for (i = 0 ; i < ( size - 1 ); ++i)
for (j = 0 ; j < (size - i - 1); ++j )
if( data[j].hp > data[j+1].hp ) {
record_copy(&temp,&data[i]);
record_copy(&data[i],&data[i+1]);
record_copy(&data[i+1],&temp);
}
}
int main() {
FILE *fp = fopen("<fileName>","r");
RECORD *data = NULL;
int i;
int size;
if( fp != NULL ) {
data = LoadData(fp,&size);
}
record_sort(data,size);
for(i = 0;i<size;i++) {
printf("%s:%f:%d:%s\n",data[i].name,data[i].hp,data[i].size,data[i].color);
}
free(data);
return 0;
}
with respect to sorting you can use any sorting algorithm to sort your record. I have given an example for that.

Error in printing the stack

I am trying to implement a program using stacks.But the stack is not getting displayed
#include<stdio.h>
int size=0,count=1,test=0;
struct Car
{
int registrationNo;
char *name;
};
struct ParkingLot
{
struct Car C[10];
};
struct stack
{
struct ParkingLot P;
int top;
} st;
int stfull()
{
if(st.top >= size-1)
return 1;
else
return 0;
}
void push(struct Car item) {
st.top++;
st.P.C[st.top] = item;
}
int stempty() {
if (st.top == -1)
return 1;
else
return 0;
}
void display() {
int i;
if (stempty())
printf("\nStack Is Empty!");
else {
//printf("%d\n",st.top);
for (i = 0; i<=st.top; i++)
printf("\n%s", st.P.C[i].name);
}
}
void Enter_ParkingLot()
{
struct Car CC;
int checkFull=stfull();
if(checkFull==1)
printf("Parking Lot is FUll\n");
else
{
CC.registrationNo=count;count++;
char ch[100];
printf("Enter name of owner\n");
scanf("%s",ch);
CC.name=ch;
push(CC);
}
}
int main()
{
printf("Enter size of Parking Lot\n");
st.top=-1;
scanf("%d",&size);
Enter_ParkingLot();
Enter_ParkingLot();
display();
return 0;
}
This was my input on terminal-
Enter size of Parking Lot
2
Enter name of owner
ABCD
Enter name of owner
EFGH
This was my output-
`#
`#
There was a blank line before first # in the output.
If you assign the pointer field in struct Car to a local variable, it will not work, you need to redeclare your struct Car like this
struct Car
{
int registrationNo;
char name[100];
};
and then instead of
CC.name=ch;
do it this way
strcpy(CC.name, ch);
also, it's better to write
scanf("%99s",ch);
to prevent overflowing ch, and in your case it would be even better to do
scanf("%99s", CC.name);
I fixed your code
#include <stdio.h>
#include <string.h>
struct Car
{
int registrationNo;
char name[100];
};
struct ParkingLot
{
struct Car C[10];
};
struct stack
{
struct ParkingLot P;
int top;
} st;
int stfull(int size)
{
if(st.top >= size - 1)
return 1;
return 0;
}
void push(struct Car item)
{
st.P.C[++(st.top)] = item;
}
int stempty()
{
if (st.top == -1)
return 1;
return 0;
}
void display()
{
int i;
if (stempty() != 0)
printf("\nStack Is Empty!");
else {
for (i = 0 ; i <= st.top ; i++)
printf("\n%s", st.P.C[i].name);
}
}
int Enter_ParkingLot(int count, int size)
{
struct Car CC;
if (stfull(size) == 1)
printf("Parking Lot is FUll\n");
else
{
CC.registrationNo = count;
printf("Enter name of owner\n");
scanf("%99s", CC.name);
push(CC);
}
return count + 1;
}
int main()
{
int size = 0, count = 1;
printf("Enter size of Parking Lot\n");
st.top = -1;
scanf("%d", &size);
count = Enter_ParkingLot(count, size);
count = Enter_ParkingLot(count, size);
display();
return 0;
}
I removed global variables, they where not needed.
I fixed some if/else's which made no sense.
I also applied my previously suggested fixes related to your original problem.
The Problem:
You store the name of the car into an array that is allocated on the stack.
You then copy the pointer to that array to your car object.
The original array then goes out of scope.
You then try to print that array, which no longer exists, via the pointer.
Undefined behavior occurs.
The Solution:
You need to allocate memory for the name of the car with malloc() and use strcpy() to copy it to the car object.

"struct" objects with "for-loop" in C Programming

This code is about 'struct' in C..
I created a struct spieler with the properties name and age..
By using the for-loop I let the user to create the struct objects.
they are named as sp[i] --> sp1, sp2 etc.
the problem is the objects are created. But I can use them only inside the for-loop.
If I want to get the value of "sp1.name" in main function, it doesn't work.
How can I solve it?
struct spieler{
char name[20];
int age;
};
void erzeuge();
int main() {
int anzahl = 2;
printf("Anzahl Spielern: ");
scanf("%d",&anzahl);
erzeuge(anzahl);
printf("Es sind %d Spielern",anzahl);
/*for(i;i<anzahl;i++){
printf("%d.%s",i, sp[i].name);
}*/
getchar();
}
void erzeuge(int anzahl){
int i=0;
for(i;i<anzahl;i++){
struct spieler sp[i];
printf("Struct fuer Spieler_%d wurde erzeugt\n", i);
getchar();
printf("Name: ");
scanf("%s",sp[i].name);
printf("%s\n",sp[i].name);
}
You should declare sp as a pointer at the global scope, and allocate memory for it inside the function erzeuge using malloc.
#include <stdlib.h>
#include <stdio.h>
struct spieler {
char name[20];
int age;
};
struct spieler *sp; // Add this
void erzeuge();
int main() {
int anzahl;
printf("Anzahl Spielern: ");
scanf("%d", &anzahl);
erzeuge(anzahl);
printf("Es sind %d Spielern\n", anzahl);
int i;
for(i = 0; i < anzahl; i++){
printf("%d.%s\n", i, sp[i].name);
}
if (sp) {
free(sp);
}
getchar();
return 0;
}
void erzeuge(int anzahl) {
// Add the following line to allocate memory
sp = (struct spieler*) malloc(anzahl * sizeof(struct spieler));
int i;
for (i = 0; i < anzahl; i++) {
// Remove the following line because it create an array of "i" elements
// struct spieler sp[i];
printf("Struct fuer Spieler_%d wurde erzeugt\n", i);
getchar();
printf("Name: ");
scanf("%s",sp[i].name);
printf("%s\n",sp[i].name);
}
}
You'd have to return an array of players from erzeuge, something like
struct spieler *erzeuge(int anzahl){
struct spieler *mannschaft = malloc(anzahl*sizeof(struct spieler));
int i;
for(i = 0; i < anzahl; ++i){
// prompt
scanf("%18s",&mannschaft[i].name);
...
}
return mannschaft;
}
Alternative solution without malloc:
void erzeuge(struct spieler* sp, int anzahl)
{
...
}
int main()
{
int anzahl = 2;
...
struct spieler sp[anzahl];
erzeuge(sp,anzahl);
...
}

Resources