Seg fault when using scanf to define the size - arrays

I have a strange issue with my code :
I have a function generating a dynamic array of struct and only takes an int size as parameter.
It's work well until i try to add just a scanf("d";&size); to choose the size of my array, can't understand why i get a seg fault.
Note : There is no issue with compilation if i remove the line containing scanf
pokemon_t * createPkmDatabase( int taille){
printf("taille %d",taille);
pokemon_t *tableau=malloc(sizeof(pokemon_t)*taille);
...
...
}
int main(){
/*"taille" means size in french */
int taille=5;
printf("Saisir taille : ");
scanf("%d",&taille); /* <-- BREAKS EVERYTHING */
printf("valeur de taille : %d\n ",taille);
pokemon_t *database=createPkmDatabase(taille);
}
I don't get why changing the value of "taille" with a simple scanf change anything the value.
It doesn't even seems to enter in the function bc it doesn't even print the value of the size

There are no errors in the code shown.
Some remarks:
Use the correct type for sizes (size_t)
Always check the result of scanf and malloc
typedef struct {
int x,y,z;
}pokemon_t;
pokemon_t * createPkmDatabase(size_t taille){
printf("taille %d",taille);
pokemon_t *tableau=malloc(sizeof(*tableau)*taille);
return tableau;
}
int main(){
/*"taille" means size in french */
size_t taille;
printf("Saisir taille : ");
if(scanf("%zu",&taille) == 1)
{
printf("valeur de taille : %zu\n ",taille);
pokemon_t *database=createPkmDatabase(taille);
if(database)
{
printf("\nAllocation OK\n");
}
else
{
printf("\nAllocation FAILED\n");
}
free(database);
}
}
https://godbolt.org/z/ExjYe5G94

Related

Printing a matrix of structs and enums

this is my first post here so if i make any mistake please tell me.
So i'm making this mini game for my class and i need to create a matrix of n size (from input) that is filled with a struct of enums, the function that does that is crea_scacchiera.
when i want to print the matrix i pass to another function (stampa_scacchiera), i tried everything but i cant find a solution to print the matrix without a segmentation fault.
the minigame is divided in 3 files : main.c that only prints a menu, gamelib.h that defines the enums and structts, and gamelib.c where there is the function that creates and print the matrix.
i think the matrix is filled right, i just cant find a way to print it in the other function.
//gamelib.h
extern void crea_mappa();
extern void gioca();
extern void termina_gioco();
enum Tipo_pericolo {nessun_pericolo, trappola, alieno} pericolo;
enum Stato_giocatore {vulnerabile, scudo_vita, solo_vita, solo_scudo};
enum Tipo_oggetto {nessun_oggetto, medikit, pozione, materiale, colpi_lanciarazzi} oggetto;
struct Giocatore
{
enum Stato_giocatore stato;
int Posizione_x;
int Posizione_y;
int zaino[4];
int alieni_uccisi;
};
struct Cella
{
enum Tipo_pericolo pericolo;
enum Tipo_oggetto oggetto;
};
//gamelib.c
#include "gamelib.h"
#include <stdio.h>
#include <stdlib.h>
//penso ci vadano anche dichiarazioni di variabili
int n;
void crea_scacchiera();
void stampa_scacchiera(struct Cella *scacchiera);
struct Cella *scacchiera= NULL;
static struct Giocatore Ninja;
static struct Giocatore Ciccio;
void crea_mappa()
{
int choice;
do {
printf(" \n");
printf("Sceglia cosa fare\n");
printf("1} crea scacchiera\n");
printf("2} stampa scacchiera\n");
printf("3} termina creazione\n");
printf(" \n");
scanf("%d",&choice );
switch (choice) {
case 1 :
crea_scacchiera();
break;
case 2 :
printf("stampa della scacchiera in corso\n");
stampa_scacchiera(scacchiera);
break;
case 3 :
printf("ritorno al menu della mappa\n");
system("clear");
break;
}
}
while (choice!=3);
}
void gioca()
{
printf("prova funzione, gioca\n");
}
void termina_gioco()
{
printf("prova funzione, termina gioco\n" );
}
void crea_scacchiera()
{
// enum Tipo_oggetto oggetto;
//enum Tipo_pericolo pericolo;
int i,j,rows,cols;
extern int n;
//static int perc1,perc2,perc3,perc4,perc5,perc6,perc7,perc8;
printf(" \n ");
printf("inserisci la grandezza della scacchiera\n ");
scanf("%d",&n);\
rows=n;
cols=n;
scacchiera = (struct Cella *)malloc(rows* cols* sizeof(struct Cella));
//int offset = i * cols + j;
for (i=0; i<n; i++){
for (j=0; j<n; j++){
scacchiera[i*cols+j].pericolo= trappola;
scacchiera[i*cols+j].oggetto= pozione;
}
}
Ninja.stato = solo_vita;
Ninja.Posizione_x= rand()%n+1;
Ninja.Posizione_y= rand()%n+1;
Ciccio.stato = solo_vita;
Ciccio.Posizione_x= rand()%n+1;
Ciccio.Posizione_y= rand()%n+1;
printf("%d\n",n );
}
void stampa_scacchiera(struct Cella *scacchiera) //FuncB
{
int i,j,cols;
cols = n;
extern int n;
cols=n;
for (i=0; i<n; i++){
for (j=0; j<n; j++){
printf("oggetto scacchiera [%d] [%d] : %d\n",i,j,(scacchiera[i*cols+j]).oggetto );
printf("pericolo scacchiera [%d] [%d] : %d\n",i,j,(scacchiera[i*cols+j]).pericolo );
}
}
}
I have modified the program now and this are the errors that is giving me
gamelib.c:154:39: error: declaration of ‘scacchiera’ shadows a global declaration [-Werror=shadow]
void stampa_scacchiera(struct Cella *scacchiera) //FuncB
^~~~~~~~~~
gamelib.c:11:15: note: shadowed declaration is here
struct Cella *scacchiera= NULL;
^~~~~~~~~~
Your program has majorly serious issues:
never use your original language in code. Always write in english (variable names, function names and so on). Otherwise almost noone will bother.
don't use shortcut names like crea_. How much time did it save you not to type those two missing letters? While everyone else will look at this and wonder what crea is. Yea, sure, "everyone" knows, its shortcut from create. But not everyone is you, not everyone is master of english and even then it will take them additional time of their live to decipher your "style" (read: mess).
formatting matters. Otherwise once again almost noone will bother.
Try this:
scacchiera = (struct Cella *)malloc(rows* cols* sizeof(struct Cella));
instead of
int *scacchiera = (int *)malloc(rows* cols* sizeof(struct Cella));
You forgot to initialize your global variable.
After trying to assign to global variable your compiler barks on you, because types don't match. Try this:
scacchiera = (struct Cella*)malloc(rows* cols* sizeof(struct Cella));
You also pass invalid value to printf (probably). Try this instead (removal of & operator). Otherwise you'll print address of a variable instead of it's value.
printf("oggetto scacchiera [%d] [%d] : %d\n",i,j,(scacchiera[i*cols+j]).oggetto );
printf("pericolo scacchiera [%d] [%d] : %d\n",i,j,(scacchiera[i*cols+j]).pericolo );

Dynamic memory in C with struct

I've got this code, but it doesnt work, what's wrong?
I try to make massive of struct with dynamic size(C language)
after the second use of add_sala(); in main function Windows close programm.
Please help to solve this problem! Thanks!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
char trash[50];
int dyn_sala_id=1;
typedef struct
{
int id;
char number[6];
int persons;
char tech_inf[256];
} sala;
sala *sala_;
int add_sala()
{
int persons;
char number[6], tech_inf[256];
sala_ = (sala*)realloc(sala_,dyn_sala_id * sizeof(sala));
printf("Wpisz numer sali(max. 5 znakow): ");
fgets(number,6,stdin);
if(strlen(number)>5)
{
printf("Numer musi byc nie wiecej, niz 5 znakow!\n");
fflush(stdin);
add_sala();
return 0;
}
printf("Wpisz ilosc osob, ktora wmiesci sie w sale(max. 1000 osob): ");
scanf("%d", &persons);
if(persons==0 || persons>1000)
{
printf("Nie wolno wprowadzic litery oraz max. ilosc osob to 1000\n");
fflush(stdin);
add_sala();
return 0;
}
printf("Wpisz info o wyposazeniu sali(max. 255 znakow): ");
fgets(trash,50,stdin);
fgets(tech_inf,256,stdin);
if(strlen(tech_inf)>255)
{
printf("Info musi byc nie wiecej, niz 255 znakow!\n");
fflush(stdin);
add_sala();
return 0;
}
sala_[dyn_sala_id].id = dyn_sala_id;
strncpy(sala_[dyn_sala_id].number, number, 6);
sala_[dyn_sala_id].persons = persons;
strncpy(sala_[dyn_sala_id].tech_inf, tech_inf, 256);
printf("\nSala zostala dodana!\n\n");
printf("%d, %d, %s, %s",dyn_sala_id, persons, number, tech_inf);
dyn_sala_id+=1;
return 0;
}
int main()
{
add_sala();
printf("%s",sala_[1].number);
add_sala();
printf("'%s'",sala_[1].number);
printf("'%s'",sala_[2].number);
return 0;
}
Arrays in C are indexed from 0, so in main() the array indexing is off by 1.
add_sala();
printf("%s",sala_[1].number);
add_sala();
printf("'%s'",sala_[1].number);
printf("'%s'",sala_[2].number);
Also in the function add_sala() it is clear that the first time it is called you have the global
int dyn_sala_id=1;
which you use to allocate memory for one record with
sala_ = (sala*)realloc(sala_,dyn_sala_id * sizeof(sala));
but a bit further down, the indexing is again off by 1, where there is plainly only one array element
sala_[dyn_sala_id].id = dyn_sala_id;
Then, in that same function (although I can't read the error messages) it seems strange that after an apparent bad input, you recurse the function. Also, you have undefined behaviour with
fflush(stdin);
and I have not looked further, because the code will not work.

When one and when two asterixes (indirection operators) when passing arguments to functions in C

I will be thankful for a very simple explanation why in the examples below I pass the pointer to the object using sometimes one and sometimes two asterixes (indirection operators).
In both examples I dedicate memory to the variable / object in the external function, not in main. Can both examples be changed so they work with one/two asterixes when passing arguments? I tried I failed to do so. One example only works as it is, the other as it is. Cannot modify them.
So can I pass a pointer to a structure to the external function with two indirection operators and allocate memory there for this structure?
And one more question, if the fuction returns something to main, does it make a copy of its argument, allocates new memory and returns the copy to main? Is the only way not to allocate new memory to variables to use functions returning nothing to main (void function(...))?
Two asterixes (indirection operators) in this example:
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
void funkcja(char ** w){ //adres adresu znaku
char bufor[256];
scanf("%s", bufor);
int l;
l=strlen(bufor); //pamiętać, że nie liczy 0 na końcu
*w=(char*)malloc((l+1)*sizeof(char));
if(*w==0) exit(1);
strcpy(*w,bufor);
}
int main(){
char * twsk[5];
int i;
for(i=0;i<5;i++){
funkcja(&twsk[i]); //adres i-tego elementu tej tablicy ktorym jest wsk
}
for(i=0;i<5;i++){
printf("%s\n",twsk[i]);
}
return 0;
}
One asterix (indirection operator) here.
#include <stdio.h>
#include <stdlib.h>
typedef struct Diament{
float **kamienie; //tablica brylantów i kolczykow
int count;
}diamenty;
diamenty * WprowadzanieCenBrylantow(diamenty * oferta);
void ObliczCeny(diamenty * oferta);
int Informacja(diamenty * oferta);
void Pokaz(diamenty * oferta);
int main(){
diamenty * oferta;
oferta = WprowadzanieCenBrylantow(oferta);
Pokaz(oferta);
ObliczCeny(oferta);
/*Pokaz(oferta);*/
Informacja(oferta);
return 0;
}
//------------------------------------------------------------------------------
diamenty * WprowadzanieCenBrylantow(diamenty * oferta){
int count=0;
int i;
printf("Podaj ilosc brylantów jakie chcesz wpisać -> ");
scanf( "%d", &count );
oferta = malloc(sizeof(diamenty)); //alokacja pamięci na całą strukturę
oferta->kamienie = malloc(sizeof(float*)*count); //alokacja pamięci na tablicę cen, na odpowiednią liczbę wierszy
for(i=1;i<count+1;i++){
oferta->kamienie[i]=malloc(sizeof(float)*(count-i+1)); //alokacja pamięci na daną tablicę dodatkowy element na cenę kamienia, na kolumny
}
oferta->count=count;
printf("Podaj ceny diamentów \n");
for(i=1;i<count+1;i++){
printf("Diament numer %d podaj jego cenę -> ",i);
scanf("%f", &oferta->kamienie[i][0]); //kolumna 0 zawiera ceny pojedynczych brylantów i je tu wpisuję
printf("Wpisana cena to -> %f \n", oferta->kamienie[i][0]);
}
return oferta;
}
//-----------------------------------------------------------------------------
void ObliczCeny(diamenty * oferta){
int liczba = oferta->count;
int i,j;
for(i=1;i<liczba+1;i++){ //przesuwam się po numerach wszystkich kamieni
for(j=1;j<liczba-i+1;j++){ //przesuwam się jeszcze raz po kamieniach ale tylko tyle aby dostać macierz trójkątną
oferta->kamienie[i][j]=oferta->kamienie[i][0]+oferta->kamienie[liczba-j+1][0];
/*printf("Kombinacja diament %d i diament %d , czyli kamienie[%d][%d] -> łączna cena wynosi %f\n", i, (oferta->count-j+1), i, j, (oferta->kamienie[i][j])); */
}
}
}
//***********************************************************
void Pokaz(diamenty * oferta){
int i,j;
int liczba=oferta->count;
printf("\n");
/*for(i=1;i<liczba+1;i++){
printf("Cena wynosi -> %f \n", oferta->kamienie[i][0]);
} */
for (i=1;i<liczba+1;i++){
for(j=1;j<liczba-i+1;j++){
if(j==1){printf("Cena brylantu %d wynosi -> %f \n", i, oferta->kamienie[i][0]);}
printf("%d %d %f \n -> ", i, liczba-j+1, oferta-> kamienie[i][liczba-j+1]);
}
}
}
//***********************************************************
int Informacja(diamenty * oferta){
int kamien1, kamien2, temp;
int liczba=oferta->count;
char odpowiedz[256];
do{
printf("Podaj numery brylantów, które mają stworzyć kolczyki. \n Na początek podaj numer diamentu numer 1 -> ");
scanf("%d",&kamien1);
printf("Teraz podaj numer drugiego brylantu -> ");
scanf("%d",&kamien2);
if (kamien1>kamien2){
temp=kamien1;
kamien1=kamien2;
kamien2=temp;}
if (kamien1==kamien2) {printf("Nie można kupić dwa razy takiego samego kamienia\n"); return 0;}
if (kamien1<=0 ||kamien2<=0) return 0;
if(kamien1<=liczba && kamien2<=liczba)
printf("Cena: %f\n",oferta->kamienie[kamien1][oferta->count-kamien2+1]);
printf("Czy chcesz sprawdzić ceny innej pary kolczyków? Wpisz T albo N");
scanf("%s", odpowiedz);
}while((strcmp(odpowiedz,"N")!=0)&&(strcmp(odpowiedz,"n")!=0));
return 0;
}
** is a pointer to a pointer. It's used here because the function that takes it as an argument needs to change the pointer itself, not what it is pointing to.
First Case: you pass a pointer to pointer, since you pass the address of the pointer it will be modified inside the function, and you can reassing the pointer inside the function as in
*w = (char*)malloc((l+1)*sizeof(char))
in this case after the function returns, the one star pointer in your main function now points to newly allocated (and in this case initialized) memory.
Second Case: you just pass a pointer, although you can modify the content of the memory it points to, if you assign it to a different pointer, the effect will be local to the function.
Note: it is discouraged to cast the result of malloc in the c language, it's the most popular c question in SO, look it up.

The terminal crash on my little program

When i try to execute this little program on the while my terminal crash and i don't know why! Somebody can help me? =) The problem is in the while. My colpiler (code:blocks) doesn't say anything O_o just one warning, but no errors.
#include<stdio.h>
#include<stdlib.h>
#define mxl 30
typedef struct inc{
int ora;
char desc[mxl];
} incluso;
typedef struct dati {
char data[mxl];
int n_a;
incluso *a;
} agenda;
int main(){
FILE *f;
agenda *p;
int i,orai,oraf;
char c, datar[mxl],nomefile[mxl],datapp[mxl];
printf("Inserisci il nome del file: ");
scanf("%s",&nomefile);
f=fopen(nomefile,"r");
if(f==NULL){
printf("Impossibile aprire il file!");
exit(1);
}
else{
printf("Inserisci data, ora inizio ed ora fine nel formato gg/mm hh hh: ");
scanf("%s %d %d",datar, orai,oraf);
while((c=getc(f))!=EOF){
if(fscanf(f,"%s",&datapp)==datar){
fscanf(f,"%s",&p->data);
fscanf(f,"%d",&p->n_a);
p->a=(incluso*)malloc(p->n_a*sizeof(incluso));
for(i=0;i<p->n_a;i++){
fscanf(f,"%d",&p->a[i].ora);
fscanf(f,"%s",&p->a[i].desc);
}
}
}
for(i<0;i<p->n_a;i++){
if(p->a[i].ora>orai && p->a[i].ora<oraf )
printf("%s %d %s", p->data, p->a[i].ora, p->a[i].desc);
}
free(p->a);
fclose(f);
}
}
In addition to what BLUEPIXY already mentioned:
scanf("%s",&nomefile);
should be
scanf("%s",nomefile);
because nomefile is an array and is reduced to a pointer already.
if(fscanf(f,"%s",&datapp)==datar){
Same here. It should be:
if(fscanf(f,"%s",datapp)==datar){
Also what do you want to compare here? The left side is an int and the right side a char*. If you want to compare the strings you have to do it in an extra line and with strcmp: (You also need to #include <string.h> for this)
fscanf(f,"%s",datapp);
if(strcmp(datapp, datar) == 0){
The same problem again:
fscanf(f,"%s",&p->a[i].desc);
should be
fscanf(f,"%s",p->a[i].desc);
Here you probably have a typo:
for(i<0;i<p->n_a;i++){
should be
for(i=0;i<p->n_a;i++){
With all warnings activated (-Wall -Wextra) gcc warned me for each of these.
Also (but there is no warning for this) you are repeatedly allocating for p->a. This should be done only once before the loop. Don't forget to free p either.
Problems as follows my noticed...
change
scanf("%s %d %d",datar, orai,oraf);
to
scanf("%s %d %d",datar, &orai, &oraf);
and
fscanf(f,"%s",&p->data);
to
p = malloc(sizeof(*p));
...
fscanf(f,"%s", p->data);
ADD
if(fscanf(f,"%s",&datapp)==datar){
Probably
if(fscanf(f, "%s", datapp)==1){

C program keep crashing

well i have this simple code, it asks the user how many numbers he wants to save, then it asks for the numbers, each time the user write the number the program prints the numbers that he has written already and it sort numbers from lowest to highest.
The problem is when the user tell the program to save more than 9 numbers, the programs just stops, if the user choose to save 8 or less number it works perfect. i don't know whats happening, I'll appreciate your help
The variables and other terms are based in my language, spanish, here are some translations:
function guardaNum: saves the number in the array
function ordena: sort array's numbers
function imprime: prints the array
contador: is a counter
cant: is the amount of number the users wants to save
thanks for your help!
#include <stdio.h>
int guardaNum(int *pnum,int lista[],int *pcontador);
int ordena(int lista[],int *pcontador);
void imprime(int lista[],int *pcant);
int main(void)
{
int cant, num, *pnum, lista[cant], i,contador,*pcontador ;
printf("Ingrese la cantidad de numeros que desea agregar a la lista: \n");
scanf("%d", &cant);
for(i=0;i<cant;i++)
{
lista[i]=-99;
}
for(i=0;i<cant;i++)
{
printf("Ingrese un Numero: ");
scanf("%d",&num);
pnum=&num;
contador=i;
pcontador=&contador;
guardaNum(pnum,lista,pcontador);
ordena(lista,pcontador);
imprime(lista,pcontador);
}
}
int guardaNum(int *pnum,int lista[],int *pcontador)
{
lista[*pcontador]=*pnum;
return 0;
}
int ordena(int lista[], int *pcontador)
{
int i,j, temp;
for(j=0;j<*pcontador;j++)
{
for(i=0;i<*pcontador;i++)
{
if(lista[i]>lista[i+1])
{
temp=lista[i+1];
lista[i+1]=lista[i];
lista[i]=temp;
}
}
}
}
void imprime(int lista[],int *pcontador)
{
int i;
for(i=0;i<=*pcontador;i++)
{
printf("%d\n",lista[i]);
}
}
do this:
int main(void)
{
int cant, num, *pnum, i,contador,*pcontador ;
int *lista;
printf("Ingrese la cantidad de numeros que desea agregar a la lista: \n");
scanf("%d", &cant);
lista = malloc(sizeof(int)*cant);
if(!lista){
perror("error on malloc");
exit(1);
}
//continue with your code
free(lista);
}
The problem with your code, is cant is uninitialized so the compiler doesn't know how much space is required for your array.
or you can do it this way:
scanf("%d", &cant);
int lista[cant]
//continue with your code
In this line:
int cant, num, *pnum, lista[cant], i,contador,*pcontador ;
You are using cant while it is uninitialized. You'll have to move your declaration of lista to be after you have input the size.
Note that you define the array with "cant" as size before you actually take it as an input.
You'll either need a max possible array size (and better check your input against it), or if you know how - allocate the array dynamically

Resources