i'm learnig how to code in C.
i have to create a record for a person, with an birthday and a ID number
the code is composed of 3 files
the fist is a header
// definição do tipo
typedef int vetor[10];
typedef struct
{
char nome[50];
vetor nasceu;
vetor cpf;
} dados ;
void cadastro (dados*, char[50], vetor, vetor);
then there is the definitions of the header
#include <stdio.h>
#include <string.h>
#include "cadastro.h"
void cadastro (dados *usuario, char name[50], vetor ddn, vetor cpf)
{
int i;
strcpy(usuario->nome,name);
for (i = 0; i < 50; i++)
{
usuario->nasceu[i] = ddn[i];
}
for (i = 0; i < 10; i++)
{
usuario->cpf[i] = cpf[i];
}
}
and the last file uses the header to generate the record
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cadastro.h"
int preenche_cadastro (char a[],vetor b,vetor c)
{
int i;
printf ("inserir nome: ");
gets (a);
printf("inserir data de nascimento (campos separados por espaco): ");
for (i = 0; i < 3; i++)
{
scanf("%d",&b[i]);
}
printf ("inserir CPF (campos separados por espaco): ");
for (i = 0; i < 4; i++)
{
scanf("%d",&c[i]);
}
return (0);
}
int imprime_cadastro (dados usuario)
{
printf("\nnome: %s",usuario.nome);
printf("\ndata de nascimento: %d / %d / %d\n", usuario.nasceu[0],usuario.nasceu[1],usuario.nasceu[2]);
printf("CPF: %d . %d . %d - %d\n", usuario.cpf[0],usuario.cpf[1],usuario.cpf[2],usuario.cpf[3]);
return(0);
}
int main(void)
{
dados new_entry;
char name[50];
vetor born, cpf;
int i;
preenche_cadastro (name,born,cpf);
cadastro(&new_entry, name, born, cpf);
imprime_cadastro(new_entry);
return (0);
}
i don't really know how to debug, but as far as i could tell, the `Segmentation fault' occurs only at the line
return (0);
i'm going mad here, can anybody help me?
sorry for my english, it's not mother language
You invoked undefined behavior by accessing out-of-range of array in the line
usuario->nasceu[i] = ddn[i];
in function cadastro, and then the program happened to crash there.
Do not invoke undefined behavior. Instead of using magic number 10, you should define the number of elements in the array and use it.
Also note that using values of uninitialized variables having automatic storage duration, which are indeterminate, also invokes undefined behavior.
corrected header:
// definição do tipo
#define VETOR_NUM 10
typedef int vetor[VETOR_NUM];
typedef struct
{
char nome[50];
vetor nasceu;
vetor cpf;
} dados ;
void cadastro (dados*, char[50], vetor, vetor);
corrected implementation of cadastro:
#include <stdio.h>
#include <string.h>
#include "cadastro.h"
void cadastro (dados *usuario, char name[50], vetor ddn, vetor cpf)
{
int i;
strcpy(usuario->nome,name);
for (i = 0; i < VETOR_NUM; i++)
{
usuario->nasceu[i] = ddn[i];
}
for (i = 0; i < VETOR_NUM; i++)
{
usuario->cpf[i] = cpf[i];
}
}
corrected main() function:
int main(void)
{
dados new_entry;
char name[50];
vetor born = {0}, cpf = {0}; /* initialize arrays */
/* i is removed because it wasn't used */
preenche_cadastro (name,born,cpf);
cadastro(&new_entry, name, born, cpf);
imprime_cadastro(new_entry);
return (0);
}
One more note: You shouldn't use gets(), which has unavoidable risk of buffer overrun.
Your first loop should only copy 10 items rather than 50.
for (i = 0; i < 10; i++)
{
usuario->nasceu[i] = ddn[i];
}
This loop in your cadastro function:
for (i = 0; i < 50; i++)
{
usuario->nasceu[i] = ddn[i];
}
Seems to not be in line with the size of the nasceu arrary:
typedef int vetor[10];
typedef struct
{
char nome[50];
vetor nasceu;
vetor cpf;
} dados ;
Have you tried changing to:
for (i = 0; i < 10; i++)
{
usuario->nasceu[i] = ddn[i];
}
?
Related
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int id;
char name[50];
}box;
void fill_boxes(box *boxes, int length)
{
for (int i = 0; i < length; i++) {
printf("Enter box %d id: ", i+1);
scanf("%d",&boxes[i].id);
printf("Enter box %d name: ", i+1);
/* scanf("%s",boxes[i].name); */
scanf("%[^\n]",boxes[i].name);
}
}
void print_elements(box *boxes, int length)
{
for (int i = 0; i < length; i++) {
printf("\nbox %d \n\tid = %d\n\tname = %s",i+1,boxes[i].id, boxes[i].name);
}
printf("\n");
};
int main()
{
box *boxes = malloc(2 * sizeof(box));
fill_boxes(boxes, 2);
print_elements(boxes, 2);
free(boxes);
return 0;
}
I tried using scanf("%s",boxes[i].name) but it only accepts one word
and using fgets does not solve the problem either.
Actually it's a recurrent problem with my c programs so I'm surely missing some theory !
this is my first question on StackOverflow ! :)
To be honest I'm about to destroy my whole setup.
My code is making me crazy.
My problem is, I am not able to fill a dynamic array with the return of a function.
My goal here is, for each array box, fill it with a random value of 'randomizer'. I am not able to take the return of randomizer in the array box.
Here is the code:
main.c:
#include "functions.h"
#include "functions.c"
/* TP 3 - ESIEE-IT Rémy JARDIN */
int main() {
int saisie, i;
printf("Creation du Tableau. \nNombre de caractere du tableau : ");
scanf("%d", &saisie);
ArrayCreate(saisie);
// Affichage
return 0;
}
functions.h:
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
#include <stdio.h>
#include <stdlib.h>
int ArrayCreate(int saisie);
int randomizer();
int insereAIndice();
#endif
functions.c:
#include <stdio.h>
#include <stdlib.h>
int ArrayCreate(int saisie) {
int i;
int *Tab = (int *)malloc(saisie * sizeof(int));
if (Tab == NULL) {
printf("Not enough Memory");
exit (1);
}
for (i = 0; i < saisie; i++) {
Tab[i] = (randomizer + 1);
}
printf("\n Resultats : ");
for (i = 0; i < saisie; i++) {
printf("%d - ", *(Tab + i));
}
return 0;
}
int randomizer() {
//int x = rand() % (100 + 1);
return 1;
}
And the error is:
functions.c: In function 'ArrayCreate':
functions.c:12:8: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
Tab[i] = (randomizer+1);
Instead of Tab[i] = (randomizer + 1); you should write:
Tab[i] = randomizer();
Note also these remarks:
the function prototypes in functions.h should have an argument of void:
int randomizer(void);
int insereAIndice(void);
file functions.c should include functions.h to ensure consistency between function declarations and definitions.
Writing *(Tab + i) is much less readable than Tab[i]. If you wish to obfuscate the code, use i[Tab] which is equivalent :)
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include "functions.h"
int ArrayCreate(int saisie) {
int i;
int *Tab = (int *)malloc(saisie * sizeof(int));
if (Tab == NULL) {
fprintf(stderr, "Not enough Memory\n");
exit(1);
}
for (i = 0; i < saisie; i++) {
Tab[i] = randomizer();
}
printf("\n Resultats : ");
for (i = 0; i < saisie; i++) {
printf(" %d", Tab[i]);
}
printf("\n");
return 0;
}
int randomizer(void) {
// return a random integer in the range 1..100
return 1 + rand() % 100;
}
New picture from an external compiler.. the exit code is ok?
enter image description here
This is the full code. I'm having a trouble program blows away after printing the wanted output to the screen. I guess it's a problem with the way I allocated memory for the array of structs, and the .name field of each struct in a for loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define MAX_NAME_LEN 50
typedef struct stud
{
char *name;
int marks[4];
float avg;
}student;
student* Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void printExcellent(student*);
void main()
{
int size, i;
student *arr, *newArr;
printf("\nEnter the number of students: ");
scanf_s("%d", &size);
newArr = Create_Class(&size);
for (i = 0; i < size; i++)
{
printExcellent(newArr+i);
}
for (i=0;i<size;i++) free(newArr[i].name);
free(newArr);
_getch();
}
student* Create_Class(int size)
{
student *p;
char str[MAX_NAME_LEN];
int i, j;
p = (student*)calloc(size , sizeof(student));
if (!p)
{
printf("Memory allocation failure.");
exit(1);
}
for (i = 0; i < size; i++)
{
printf("Enter your name: ");
rewind(stdin);
gets(str);
p[i].name = (char*)calloc(strlen(str)+1,sizeof(char));
if (!(p[i].name))
{
printf("Memory allocation error!");
exit(1);
}
strcpy_s(p[i].name,50,str);
printf("Enter your marks: ");
for (j = 0; j < 4; j++)
{
scanf_s("%d", &p[i].marks[j]);
}
Avg_Mark(p + i);
}
return p;
}
void Avg_Mark(student* s)
{
int i, sum=0;
for (i = 0; i < 4; i++)
sum += s->marks[i];
s->avg = (float)sum / 4;
}
void Print_One(student* s)
{
printf("The average of %s is %.1f\n", s->name, s->avg);
}
void printExcellent(student* s)
{
if ((s->avg) > 85)
Print_One(s);
}
Gonna point out everything fishy I see for you:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define MAX_NAME_LEN 50
typedef struct stud
{
char *name;
int marks[4];
float avg;
}student;
student* Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void printExcellent(student*);
void main()
{
int size, i;
student *arr, *newArr;
printf("\nEnter the number of students: ");
scanf_s("%d", &size);
// This is wrong. Remove the &...
newArr = Create_Class(&size);
for (i = 0; i < size; i++)
{
printExcellent(newArr+i);
}
for (i=0;i<size;i++) free(newArr[i].name);
free(newArr);
_getch();
}
student* Create_Class(int size)
{
student *p;
char str[MAX_NAME_LEN];
int i, j;
// Consider checking size for a sane value.
// Ok, allocate an array of students.
p = (student*)calloc(size , sizeof(student));
if (!p)
{
printf("Memory allocation failure.");
exit(1);
}
for (i = 0; i < size; i++)
{
printf("Enter your name: ");
// These 2 lines scare the heck out of me. I'd really do this differently.
// gets is the devil and the see:
// https://stackoverflow.com/questions/20052657/reversing-stdin-in-c
// for why this may not work well.
rewind(stdin);
gets(str);
// What if str is not a terminated string? Then 1 char of 0? Guess this is ok. Hope it doesn't overflow on the copy below though (consider fixed max size and not using a temporary)
p[i].name = (char*)calloc(strlen(str)+1,sizeof(char));
if (!(p[i].name))
{
printf("Memory allocation error!");
exit(1);
}
// Do a fast copy of up to 50 chars. I'd really want to verify this output to be sure it works.
strcpy_s(p[i].name,50,str);
printf("Enter your marks: ");
for (j = 0; j < 4; j++)
{
// Hope this inputs the way you want.
scanf_s("%d", &p[i].marks[j]);
}
// This should work, but I prefer more explicit pointers.
Avg_Mark(p + i);
}
return p;
}
void Avg_Mark(student* s)
{
// What if s is Null?
int i, sum=0;
// 4 is a magic number. Make this a constant.
for (i = 0; i < 4; i++)
sum += s->marks[i];
// This won't be as accurate as you want. Consider an integer solution.
s->avg = (float)sum / 4;
}
void Print_One(student* s)
{
// What if s is Null? What about s->name?
printf("The average of %s is %.1f\n", s->name, s->avg);
}
void printExcellent(student* s)
{
// What if s is Null?
if ((s->avg) > 85)
Print_One(s);
}
Note: While going through this code, I did not see any "red flags" except for the & on the size and perhaps the gets/rewind calls. I'd still add null asserts to your functions and also walk through it with a debugger to be sure that everything is as you expect. Honestly, there is enough going on here that I'd prefer the debugger help to my quick trace of the code while I was writing comments.
Update
If I change all your scanf_s to scanf() calls, replace your gets() / rewind() calls to a simple scanf("%s", str) call, and change your funky strcpy_s() function to a simpler strcpy() or strncpy() call, your program does not seem to crash for me. My money is that the strcpy_s() call is corrupting RAM while doing its "fast" copy.
#include <string.h>
#include<stdio.h>
#include<stdlib.h>
typedef struct bank
{
char an;
char name;
char type;
int bal;
};
int main()
{
int i=0,n;
printf("Enter the number of accounts\n");
scanf("%d",&n);
struct bank a[n];
printf("Enter the details of the users\n");
for(i=0;i<n;i++)
{
scanf("%s%s%s%d",a[i].an,a[i].name,a[i].type,&a[i].bal);
}
printf("The details of the users are\n");
for(i=0;i<n;i++)
{printf("%s\n%s\n%s\n%d\n\n",a[i].an,a[i].name,a[i].type,a[i].bal);}
char atype[10];
printf("Enter the type of account you want to search\n");
scanf("%s",atype);
char typ[10];
char s[]="savings";
char c[]="current";
int result,res1,res2;
result = strcmp(atype,s);
if(result == 0)
{
for(i=0;i<n;i++)
{
typ[10] = a[i].type;
res1 = strcmp(typ,s);
if(res1 == 0)
{
printf("%s\n%s\n%s\n%d\n\n",
a[i].an,a[i].name,a[i].type,a[i].bal);
}
printf("\n");
}
} else
{
for(i=0;i<n;i++)
{
typ[10] = a[i].type;
res2 = strcmp(typ,c);
if(res2 == 0)
{
printf("%s\n%s\n%s\n%d\n\n",
a[i].an,a[i].name,a[i].type,a[i].bal);
}
printf("\n");
}
}
}
so basically ik its my homework but i did everythimg and i still cannot resolve the segmentation fault.please help
i think its something to do with strcmp() function but oh well
i checked all the sources but couldnt really find any fix.
any help would be appreciated.
For starters:
This
typ[10] = ...
accesses typ one past its valid memory. This invokes undefined behaviour, so anything can happen from then on.
In C array indexing is 0-based. So for char[10] the highest allowed index would be 9. Access the 1st element would be done by using 0.
You have made 2 mistakes here .
First your struct bank declaration was wrong. You forgot to declare name an and type as string. You declared it as just character(char).It should be like :-
struct bank
{
char an[100]; // assuming 100 is max size of input strings
char name[100];
char type[100];
int bal;
};
second you cannot do typ[10] = a[i].type; you should use strcpy() Something like this :-
strcpy(typ,a[i].type);
So this corrected code will work :-
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
struct bank // change made 1
{
char an[100];
char name[100];
char type[100];
int bal;
};
int main()
{
int i = 0, n;
printf("Enter the number of accounts\n");
scanf("%d", &n);
struct bank a[n];
printf("Enter the details of the users\n");
for (i = 0; i < n; i++)
{
scanf("%s%s%s%d", a[i].an, a[i].name, a[i].type, &a[i].bal);
}
printf("The details of the users are\n");
for (i = 0; i < n; i++)
{
printf("%s\n%s\n%s\n%d\n\n", a[i].an, a[i].name, a[i].type, a[i].bal);
}
char atype[10];
printf("Enter the type of account you want to search\n");
scanf("%s", atype);
char typ[10];
char s[] = "savings";
char c[] = "current";
int result, res1, res2;
result = strcmp(atype, s);
if (result == 0)
{
for (i = 0; i < n; i++)
{
strcpy(typ,a[i].type); // change made 2
res1 = strcmp(typ, s);
if (res1 == 0)
{
printf("%s\n%s\n%s\n%d\n\n",
a[i].an, a[i].name, a[i].type, a[i].bal);
}
printf("\n");
}
}
else
{
for (i = 0; i < n; i++)
{
strcpy(typ,a[i].type); // change made 3
res2 = strcmp(typ, c);
if (res2 == 0)
{
printf("%s\n%s\n%s\n%d\n\n",
a[i].an, a[i].name, a[i].type, a[i].bal);
}
printf("\n");
}
}
}
So your mistake was not with strcmp()
I'm writing a program that calculates the greatest common denominator of two numbers, but i'm getting problem with malloc function and pointers. Actually it's clear how the stack and the heap segments work in the memory and why. But yet i'm not yet able to understand when declaring a pointer and using malloc is functional or not, is necessary or not, in a program. here is the code :
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
int *calcolaDivisori(int);
int main(int argc, char** argv) {
int foundCounter = 0;
int i,j,s1,s2;
int n1,n2;
int mcd = 1,mcm;
int *pn1,*pn2;
int d1[100],d2[100];
// INPUT dei due interi
printf("Inserisci il primo numero :");
scanf(" %d", &n1);
printf("\nInserisci il secondo numero :");
scanf(" %d", &n2);
// calcolo divisori del primo e del secondo numero e li assegno ai relativi array
pn1 = calcolaDivisori(n1);
if (!pn1) return 1;
pn2 = calcolaDivisori(n2);
if (!pn2) return 1;
for (i=0;i<n1;i++) {
d1[i] = pn1[i];
}
for (i=0;i<n2;i++) {
d2[i] = pn2[i];
}
free(pn1);
free(pn2);
// confronto i divisori e calcolo il MCD
s1 = sizeof(d1) / sizeof(int);
s2 = sizeof(d2) / sizeof(int);
for(i=0; i<s1; i++) {
for (j=foundCounter; j<s2;j++) {
if (d1[i] == d2[j]) {
mcd*= d1[1];
foundCounter = j+1;
break;
}
}
}
printf("\n\nIl minimo comune divisore e' : %d", mcd);
return 0;
}
int *calcolaDivisori(int num) {
int i;
int *a = malloc(num * sizeof(int));
if (!a) return NULL;
for (i=2;i<num;i++) {
if (num%i == 0) {
num/=i;
a[i-2]=i;
}
}
return a;
}
I get the error in the title when is run the command :
int *a = malloc(sizeof(int));
You need to cast:
int *a = (int*)malloc(num * sizeof(int));
Because there's no implicit conversion from void* to type * in C++.
Note that this cast is not required in C and could potentially be dangerous to do so in C.
Except for #include <iostream>, nothing in your code is C++. So remove it and compile it with a C compiler and you wouldn't need this cast.