C: Segmentation Fault 11 strcpy pointer Array - c

The code compiles with no errors, but I get a segmentation Fault Error (11), I'm guessing the problem is when I use the strcpy() function in line 82 ,something goes wrong, why im not getting any compile errors and how can I fix it, are the char array pointers well implemented?. I can not modiffy the current structs of the code.
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
typedef struct
{
int n_uea;
char **nombre;
double *calificacion;
} UEA;
typedef struct
{
int n_pais;
char *nombre[50];
} PAIS;
typedef struct
{
char nombre[50];
UEA uea;
PAIS *pais;
} ALUMNO;
void AllocPais(PAIS *p, int np){
p = (PAIS*) malloc(sizeof(PAIS));
p = &p[0];
p->n_pais = np;
for (int i = 0; i < np; i++) {
p->nombre[i] = (char*) malloc(sizeof(char)*50);
}
}
void AllocUEA(UEA *u , int nu){
u->n_uea = nu;
u->nombre = (char **) malloc(sizeof(char*)*nu);
for (int i = 0; i < nu; i++) {
u->nombre[i] =(char*) malloc(sizeof(char)*50);
}
u->calificacion = (double*) malloc(sizeof(double) * nu);
}
void AllocAlumnoMemory(ALUMNO *a, int np, int nu){
AllocPais(a->pais,np);
AllocUEA(&(a->uea),nu);
}
int main(int argc, char const *argv[]) {
ALUMNO* arreglo;
int entradas;
printf("%s\n","Ingrese el numero de Entradas");
scanf("%d",&entradas);
arreglo = malloc(sizeof(ALUMNO)*entradas);
for (int i = 0; i < entradas; i++) {
char separator[10];
char name[20];
int numUea , numPaises;
printf("%s\n","Se espera separador");
scanf("%s",separator);
printf("%s\n","Ingrese el nombre");
scanf("%s",name);
strcpy(arreglo[i].nombre,name);
printf("%s\n","Ingrese el numero de UEA");
scanf("%d",&numUea);
AllocUEA(&arreglo[i].uea,numUea);
for (int a = 0; a < numUea; a++) {
char name [15];
double cal;
scanf("%s %lf", name, &cal);
strcpy(arreglo[i].uea.nombre[a],name);
arreglo[i].uea.calificacion[a] = cal;
}
printf("%s\n","Ingrese Numero de paises");
scanf("%d",&numPaises);
PAIS nuvp;
arreglo[i].pais = &nuvp;
AllocPais(arreglo[i].pais,numPaises);
for (int b = 0; b < numPaises; b++) {
char names [15];
scanf("%s",names);
strcpy(arreglo[i].pais->nombre[b],names);
}
}
return 0;
}

Please note down below points and try them:
Avoid using strcpy/strcat etc. they do not protect against buffer overruns.
Use strlcpy/strlcat instead.
When using strncpy, make sure to NULL terminate the string buffer.

Related

Why when I try to access array of structures it returns random values? (C)

I have a function that returns pointer to array of structures. However, when I try to access any of the values of returned structure, it prints random symbols.
#include <stdio.h>
struct MY {
int i;
char string[30];
};
struct MY* myFunc() {
struct MY arrayOfStructs[3];
struct MY tempStruct;
struct MY* arrayOfStructsPtr = arrayOfStructs;
tempStruct.i = 1;
tempStruct.string[0] = 'H';
tempStruct.string[1] = 'i';
arrayOfStructs[0] = tempStruct;
tempStruct.i = 2;
tempStruct.string[0] = 'L';
tempStruct.string[1] = 'o';
arrayOfStructs[1] = tempStruct;
tempStruct.i = 3;
tempStruct.string[0] = 'M';
tempStruct.string[1] = 'Y';
arrayOfStructs[2] = tempStruct;
return arrayOfStructsPtr;
}
int main()
{
struct MY* arrayOfStructs = myFunc();
for(int i = 0; i < 3; i++) printf("%d\n", arrayOfStructs[i].i);
return 0;
}
You return a reference to the local array which stops to exist when function returns. It is Undefined Behaviour.
You need:
struct MY* myFunc(void) {
static struct MY arrayOfStructs[3];
or
struct MY* myFunc(void) {
struct MY *arrayOfStructs = malloc(3 * sizeof(*arrayOfStructs));
or pass the buffer allocated by the caller.
struct MY *myFunc(struct MY *arrayOfStructs) {
/* .... */
If you dynamically allocate memory you should free it after use
You return a pointer to a local variable which is out of scope when the function returns. Some alternatives:
The caller main() allocates variable and pass it to myFunc() for initialization.
#include <stdio.h>
#include <string.h>
#define N 3
struct MY {
int i;
char string[30];
};
void myFunc(struct MY arrayOfStructs[N]) {
char *strings[N] = { "Hi", "Lo", "MY" };
for(size_t i = 0; i < N; i++) {
arrayOfStructs[i].i = i + 1;
strcpy(arrayOfStructs[i].string, strings[i]);
}
}
int main() {
struct MY arrayOfStructs[N];
myFunc(arrayOfStructs);
for(int i = 0; i < N; i++)
printf("%d\n", arrayOfStructs[i].i);
}
As used here you don't really need to store i as it's just index of the struct + 1.
myFunc() dynamically allocate the variables with malloc() and return the pointer. Caller is responsible for free'ing the allocated memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 3
struct MY {
int i;
char string[30];
};
struct MY *myFunc() {
struct MY *arrayOfStructs = malloc(N * sizeof *arrayOfStructs);
if(!arrayOfStructs) return NULL; // malloc failed
char *strings[N] = { "Hi", "Lo", "MY" };
for(size_t i = 0; i < sizeof strings / sizeof *strings; i++) {
arrayOfStructs[i].i = i + 1;
strcpy(arrayOfStructs[i].string, strings[i]);
}
return arrayOfStructs;
}
int main() {
struct MY *arrayOfStructs = myFunc();
if(!arrayOfStructs) return 1;
for(int i = 0; i < N; i++)
printf("%d\n", arrayOfStructs[i].i);
free(arrayOfStructs);
}
myFunc(): make variables static (not recommended).

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++;
}
}
}

Why do I have to do ctrl+z twice to break end of file?

Basically I have a struct
typedef struct {
const char *nome;
const char *apelido;
int numero;
} Aluno;
I want to sort this by numero.
For example, Input:
jonhy_james_123
jack_china_111
Output :
jack_china_111
jonhy_james_123
I have sucessfully done this, but instead of one CTRL+Z to break end of file, I
somehow need to do it twice.
Here is the full code:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <string.h>
typedef struct {
const char *nome;
const char *apelido;
int numero;
} Aluno;
Aluno aluno(const char *nome, const char *apelido, int numero)
{
Aluno result;
result.nome = nome;
result.apelido = apelido;
result.numero = numero;
return result;
}
Aluno *Aluno_new (int n)
{
return (Aluno *) malloc (n * sizeof(Aluno));
}
char *str_dup(const char *s)
{
char *result = (char *) malloc(strlen(s) + 1);
strcpy(result, s);
return result;
}
int aluno_read(Aluno *a)
{
int result = 0;
char nome[50];
char apelido[50];
int numero;
while (scanf("%[^_]_%[^_]_%d\n", nome, apelido, &numero) != EOF) {
a[result++] = aluno(str_dup(nome), str_dup(apelido), numero);
}
return result;
}
void aluno_write(Aluno *a, int n)
{
printf("%s_%s_%d\n", a[0].nome, a[0].apelido, a[0].numero);
for (int i = 1; i < n; i++) {
printf("%s_%s_%d\n", a[i].nome, a[i].apelido, a[i].numero);
}
}
int qsort_cmp_numero(Aluno *x, Aluno *y)
{
return (x->numero - y->numero);
}
int cmp_B(Aluno *x, Aluno *y)
{
int result = qsort_cmp_numero(x,y);
return result;
}
int cmp_final2(const void *p, const void *q)
{
return cmp_B((Aluno *) p, (Aluno *) q);
}
void test_sort()
{
Aluno *aluno = Aluno_new(100001);
int n_aluno = aluno_read(aluno);
qsort(aluno, n_aluno, sizeof(Aluno), cmp_final2);
aluno_write(aluno, n_aluno);
}
int main()
{
test_sort();
return 0;
}
While behavior of Ctrl-Z in Windows has some peculiarities, this is secondary at the moment.
The primary problem is that you placed an \n character at the end of your scanf format. By doing so you asked scanf to wait for non-empty input after the "primary" portion of the input is complete.
This by itself will easily result "strange" behaviors of your scanf, like "ignoring" Enter key and such.
What is that \n doing there? Why did you include it in your format string?

Find if string exist in a vector of structs

Good afternoon,
I'm here with a doubt that i am not able to overcome and i've tried a number of ways. I'm doing a program that among other things the user has to enter data about a product where the serial number has to be unique and of type char. What is happening is that when i type the 1st product serial number the program returns that is already a product with this serial number despite being the 1st.
Here's the code I have:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char numeroserie;
char descricao;
float preco;
} stProduto;
/********************** Funcoes dos produtos *************************/
void inserirProduto(stProduto produtos[], int *contadorProdutos);
int procurarNumeroserie(stProduto produtos[], int contadorProdutos, char produtoAProcurar);
int main()
{
stProduto produtos[500];
int contadorProdutos=0;
inserirProduto(produtos,&contadorProdutos);
return 0;
}
void inserirProduto(stProduto produtos[], int *contadorProdutos)
{
char string1;
char posicao;
do
{
printf("Introduza o numero de serie do produto:");
scanf("%s",&string1);
posicao = procurarNumeroserie(produtos,*contadorProdutos, string1);
if (posicao == 0)
{
printf("Ja existe um produto com esse numero de serie!!!\n");
}
}
while(posicao == 0);
strcpy(produtos[*contadorProdutos].numeroserie,string1);
(*contadorProdutos)++;
}
int procurarNumeroserie(stProduto produtos[], int contadorProdutos, char produtoAProcurar)
{
int i;
char posicao;
posicao = 0;
for(i = 0 ; i < contadorProdutos ; i++)
{
if (strcmp(produtos[i].numeroserie, produtoAProcurar) == 0)
{
posicao=i;
i=contadorProdutos;
}
}
return posicao;
}
Someone help please !!I am already getting frustrated.
Thanks
You got it wrong, char is not a string type in c, it's an integer type.
A string is defined as a sequence of bytes non-nul that are followed by a nul byte.
They type char is 1 byte and hence a string can be an array of char, like the following
char string[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
/* ^ nul: it's mandatory
* for this to be a
* string
*/
The code you posted above seems to be Java originally with some fixes to make it compile, but if you enable compilation warnigs the compiler will really piss you off.
You can build a string from an array like I did above, or by using a pointer of char, in that case you need to point to an array or to dynamic memory allocated using malloc().
An example would be
char *hello;
hello = malloc(6);
if (hello == NULL)
return ERROR; /* or whatever is need but do not continue */
strcpy(hello, "Hello");
/* do whatever you want with hello */
free(hello);
I have managed to put i to work:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char numeroserie[9];
char descricao;
float preco;
} stProduto;
/********************** Funcoes dos produtos *************************/
void inserirProduto(stProduto produtos[], int *contadorProdutos);
int procurarNumeroserie(stProduto produtos[], int contadorProdutos, char produtoAProcurar[9]);
int main()
{
stProduto produtos[500];
int contadorProdutos=0;
inserirProduto(produtos,&contadorProdutos);
return 0;
}
void inserirProduto(stProduto produtos[], int *contadorProdutos)
{
char string1[9];
char posicao;
do
{
printf("Introduza o numero de serie do produto:");
scanf("%s",&string1);
posicao = procurarNumeroserie(produtos,*contadorProdutos, string1);
if (posicao == 0)
{
printf("Ja existe um produto com esse numero de serie!!!\n");
}
}
while(posicao == 0);
strcpy(produtos[*contadorProdutos].numeroserie,string1);
(*contadorProdutos)++;
}
int procurarNumeroserie(stProduto produtos[], int contadorProdutos, char produtoAProcurar[9])
{
int i;
char posicao;
posicao = 0;
for(i = 0 ; i < contadorProdutos ; i++)
{
if (strcmp(produtos[i].numeroserie, produtoAProcurar) == 0)
{
posicao=i;
i=contadorProdutos;
}
}
return posicao;
}
Putting numeroserie [8] i assure that the user just insert 8 characters ??
Thanks

Having trouble with struct pointers

I'm having trouble while trying to compile the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Aposta{
char apostador[100];
char time1[100];
char time2[100];
char time3[100];
}Apostas;
typedef struct Jogos{
char time1[100];
int gol1;
char time2[100];
int gol2;
int faltas;
int amarelo;
int vermelho;
}Jogo;
typedef struct Times{
char time[100];
}Time;
typedef struct Tbela{
char time[100];
int pontos;
int ngole;
int ngols;
}Tabela;
Tabela *ptTabela(Time *time, Jogo *jogo, int tamt, int tamj){
int i=0;
Tabela *tabela;
tabela = (Tabela *)malloc((tamt)*(sizeof(Tabela)));
while (i < tamt){
tabela[i].pontos = 0;
tabela[i].ngole = 0;
tabela[i].ngols = 0;
int l;
for (l=0; l < tamj; l++){
if(!(strcmp(time[i].time, jogo[l].time1 ))){
tabela[i].time = jogo[l].time1;
if(jogo[l].gol1 > jogo[l].gol2){
tabela[i].pontos = (tabela[i].pontos + 3);
}
if(jogo[l].gol1 = jogo[l].gol2){
tabela[i].pontos = (tabela[i].pontos + 1);
}
tabela[i].ngole = tabela[i].ngole + jogo[l].gol1;
tabela[i].ngols = tabela[i].ngols + jogo[l].gol2;
}
else if(!(strcmp(time[i].time, jogo[l].time2 ))){
tabela[i].time = jogo[l].time2;
if(jogo[l].gol2 > jogo[l].gol1){
tabela[i].pontos = (tabela[i].pontos + 3);
}
if(jogo[l].gol1 = jogo[l].gol2){
tabela[i].pontos = (tabela[i].pontos + 1);
}
tabela[i].ngole = tabela[i].ngole + jogo[l].gol2;
tabela[i].ngols = tabela[i].ngols + jogo[l].gol1;
}
else{
printf("Time %s not found.", time[i].time);
}
}
}
i++;
}
The compiler says:
I really don't know what is wrong with it, for me, it's just supposed to get the string that is inside jogo[l].time1 and copy it to tabela[i].time. And it looks like they are the exact same type.
I'm using netbeans 7.2 .
Thank you for your patience already. If something is not clear, please, let me know and I will correct it as fast as I can.
You need to do strdup or strcpy or strncpy... - otherwise you make the pointer (which had space allocated to it) point to a new location and that is probably not what you had in mind.
tabela[i].time = jogo[l].time1;
time is a char array. You are trying to assign a string literal to it which is incorrect. You should use strcpy to copy like,
strcpy(tabela[i].time, jogo[l].time1);

Resources