Malloc and Realloc doesn't work (C11 - CLion) - c

#include <stdio.h>
#include <stdlib.h>
typedef struct Ogrenciler {
int no;
char adi[50];
char soyadi[50];
double vize;
double final;
double notu;
} Ogr;
int ogrenciSayisi = 0;
void KayitEkle(Ogr *ogrenci) {
int simdikiOgr = ogrenciSayisi;
if (ogrenciSayisi == 0) {
ogrenciSayisi++;
ogrenci = (Ogr *) malloc(ogrenciSayisi*sizeof(Ogr));
} else {
ogrenciSayisi++;
ogrenci = (Ogr *) realloc(ogrenci, ogrenciSayisi * sizeof(Ogr));
}
printf("No:");
scanf("%d", &ogrenci[simdikiOgr].no);
printf("Adi:");
scanf("%s", ogrenci[simdikiOgr].adi);
printf("Soyadi:");
scanf("%s", ogrenci[simdikiOgr].soyadi);
printf("Vize:");
scanf("%lf", &ogrenci[simdikiOgr].vize);
printf("Final:");
scanf("%lf", &ogrenci[simdikiOgr].final);
ogrenci[simdikiOgr].notu = (ogrenci[simdikiOgr].vize * 0.4) + (ogrenci[simdikiOgr].final * 0.6);
printf("Notu: %lf", ogrenci[simdikiOgr].notu);
printf("\n\n");
printf("Adi: %s\nNo: %d\nVize: %lf\nFinal: %lfNotu: %lf\n",
ogrenci[simdikiOgr].adi, ogrenci[simdikiOgr].no, ogrenci[simdikiOgr].vize, ogrenci[simdikiOgr].final,
ogrenci[simdikiOgr].notu);
}
int main() {
int c;
while (c != 5) {
printf("\n1-\tYeni Kayit Ekle\n2-\tKayit Sil\n3-\tKayitlari Listele\n4-\tOrtalama Hesapla\n5-\tCikis\n");
scanf(" %d", &c);
Ogr *ogrenci;
switch (c) {
case 1:
KayitEkle(ogrenci);
break;
case 2:
KayitSil(ogrenci);
break;
case 3:
KayitListele(ogrenci);
break;
case 4:
OrtHesapla(ogrenci);
break;
case 5:
printf("Cikiliyor");
break;
default:
printf("Gecerli bir girdi yapiniz\n");
break;
}
}
return 0;
}
As u can see, I use malloc() and realloc() for my typedef struct and I'm able to enter only one entry. When I tried adding a new entry (switch case: 1) it doesn't work and crashes after this section:
printf("No:");
scanf("%d", &ogrenci[simdikiOgr].no);
At first, I tried I used calloc(ogrenciSayisi*10*sizeof(Ogr)) but it was created only one space. After that, in the debugger (CLion's) after realloc section, ogrenci pointer becomes a null pointer.
Edit:
I'm not trying to return a value. As I know (int a) equals (int a[ ]) so KayitEkle(ogrenci) and void KayitEkle (Ogr ogrenci) seems legit to me. And my ogrenci should be empty in the first place so (Ogr *ogrenci=NULL) is correct as you said right?
Edit2:
In malloc section 10 is a mistake. I fixed it. I was trying something and I forgot to delete it.

You pass ogrenci pointer by value to KayitEkle(), you modify it's value inside it, yet not return it's modified value to main(). You need to pass ogrenci value using a pointer (ie. KayitEkle(&ogrenci)) or return the new value to the called (ie. ogrenci = KayitEkle(ogrenci)). Example below is with the latter.
ogrenci pointer is inside the while loop, so it will be reinitialized every time the loop runs, probably you meant to put it outside of the loop so it's value is preserved.
Local variables have undefined (read: any) value without initialization, so you need to explicitly initialize ogrenci to NULL, if you need. See Initialization.
You don't need to check for ogrenciSayisi == 0 when ogrenci == NULL, because realloc(NULL, ...) is equal to malloc(...). See realloc.
#include <stdio.h>
#include <stdlib.h>
typedef struct Ogrenciler {
int no;
char adi[50];
char soyadi[50];
double vize;
double final;
double notu;
} Ogr;
int ogrenciSayisi = 0;
// or void KayitEkle(Ogr **ogrenci) and then use *ogrenci
Ogr *KayitEkle(Ogr *ogrenci) {
int simdikiOgr = ogrenciSayisi;
ogrenciSayisi++;
ogrenci = realloc(ogrenci, ogrenciSayisi*sizeof(Ogr));
printf("No:");
scanf("%d", &ogrenci[simdikiOgr].no);
printf("Adi:");
scanf("%s", ogrenci[simdikiOgr].adi);
printf("Soyadi:");
scanf("%s", ogrenci[simdikiOgr].soyadi);
printf("Vize:");
scanf("%lf", &ogrenci[simdikiOgr].vize);
printf("Final:");
scanf("%lf", &ogrenci[simdikiOgr].final);
ogrenci[simdikiOgr].notu = (ogrenci[simdikiOgr].vize * 0.4) + (ogrenci[simdikiOgr].final * 0.6);
printf("Notu: %lf", ogrenci[simdikiOgr].notu);
printf("\n\n");
printf("Adi: %s\nNo: %d\nVize: %lf\nFinal: %lfNotu: %lf\n",
ogrenci[simdikiOgr].adi, ogrenci[simdikiOgr].no, ogrenci[simdikiOgr].vize, ogrenci[simdikiOgr].final,
ogrenci[simdikiOgr].notu);
return ogrenci;
}
int main() {
int c = 0;
Ogr *ogrenci = NULL;
while (c != 5) {
printf("\n1-\tYeni Kayit Ekle\n2-\tKayit Sil\n3-\tKayitlari Listele\n4-\tOrtalama Hesapla\n5-\tCikis\n");
scanf(" %d", &c);
switch (c) {
case 1:
ogrenci = KayitEkle(ogrenci);
break;
case 2:
ogrenci = KayitSil(ogrenci);
break;
case 3:
ogrenci = KayitListele(ogrenci);
break;
case 4:
ogrenci = OrtHesapla(ogrenci);
break;
case 5:
printf("Cikiliyor");
break;
default:
printf("Gecerli bir girdi yapiniz\n");
break;
}
}
// it's nice to free things
free(ogrenci);
return 0;
}

There are many mistakes. If you want to dynamically allocate memory with your function. A pointer of pointer must be used e.g. The instructions on the realloc line are also not correct, because if your re-allocation fails, you overwrite the old memory address and the pointer takes the same value as NULL.
And without getting off topic. You should also take precautions with the scanf function if you enter anything other than what the format expects (e.g. characters instead of numbers or vice versa), it is sure that the program will behave indeterminately, so you should anticipate this scenario.

Related

Having problems displaying structure array content

I want to display structure members based on user input, but I don't know if I've stored the input properly.
When I try display all people, it just outputs random numbers.
These are the structures and function prototypes
#define MAX_NAME_LEN 15
#define MAX_NUM_PERSON 4
#define MAX_JOB_LENGTH 20
typedef struct birth_date
{
int month;
int day;
int year;
} person_birth_t;
typedef struct person
{
char pName[MAX_NAME_LEN];
char job[MAX_JOB_LENGTH];
person_birth_t birth_t;
} person_t[MAX_NUM_PERSON];
void print_menu (void);
void scanPerson(person_t p, int);
void displayPeople(person_t p);
This is the main code for the program, a menu is printed asking user to input a number, if a user enters 1 then it prompts them to add a person. Entering 2 displays all people entered.
int main(void)
{
/* TODO */
print_menu();
return 0;
}
void print_menu (void)
{
int choice;
person_t p;
static int index = 0;
int *indexP = NULL;
indexP = &index;
/*Print the menu*/
scanf("%d", &choice);
switch (choice)
{
case 1:
if (index < MAX_NUM_PERSON){
scanPerson(p, index);
++*indexP;
print_menu();
} else {
printf("Can't add more people - memory full \n");
print_menu();
}
break;
case 2:
displayPeople(p);
break;
case 3:
exit(0);
break;
default:
print_menu();
}
}
/*function called when add person is chosen from menu */
void scanFlight(person_t p, int index){
/*printf to enter name*/
scanf(" %s", p[index].pName);
/*printf to enter job*/
scanf("%s", p[index].job);
}
void displayPeople(person_t p){
for(int i = 0; i < MAX_NUM_PERSON; i++){
printf("%s %d-%d-%d %s \n",p[i].pName
,p[i].birth_t.month
,p[i].birth_t.day
,p[i].birth_t.year
,p[i].job);
}
}
I've tried other ways to take input and add it to a struct array, but I'm just not sure how to do it right.
person_t p;
Here, you use the local variable p (in print_menu function), so each recursion, you just print the parameters of the local variable that is not initialized.
To solve it, you can declare p as the global variable.
OT, in scanFlight function, to avoid overflow, you should change the scanf function to:
/*printf to enter name*/
scanf("%14s", p[index].pName);
/*printf to enter job*/
scanf("%20s", p[index].job);
And, rename scanPerson to scanFlight, because i do not see any implementation of scanPerson function in your code. I think it's typo, no ?
None of the methods were working, so instead of trying to figure it out, I scrapped the static index and indexP.
Instead, I initialized p with malloc:
person_t *p= malloc(MAX_NUM_PERSON * sizeof(person_t));
I changed the scan function to accommodate for the change and made index a pointer instead, and I made the display function pass the index.
When I ran it, the output was correct.

Passing and returning a struct from a function

I have a function with a book struct array, but when i try to return it to my main it does not return the values and store them in the array. If the addBook function has to be void how would i work around that so that i can access the array elements later.
void addBook(struct Book book[], int *size) {
if (*size == MAX_BOOKS) {
printf("The inventory is full\n");
}
else {
printf("ISBN:");
scanf("%d", &book[*size]._isbn);
printf("Title:");
scanf("%s", book[*size]._title);
getchar();
printf("Year:");
scanf("%d", &book[*size]._year);
printf("Price:");
scanf("%f", &book[*size]._price);
printf("Quantity:");
scanf("%d", &book[*size]._qty);
*size++;
printf("The book is successfully added to the inventory.\n");
}
return book;
}
int main(void) {
struct Book book[MAX_BOOKS];
int size = 0;
int i;
int option;
printf("Welcome to the Book Store\n");
printf("=========================\n");
do {
menu();
printf("Select: ");
scanf("%d", &option);
switch (option) {
case 0:
printf("Goodbye!\n");
break;
case 1:
displayInventory(book, size);
break;
case 2:
addBook(book, &size);
break;
case 3:
//checkPrice();
break;
default:
printf("Invalid input, try again:\n");
}
} while (option != 0);
}
Your return statement isn't going to do what you're intending as the addBook's function signature says it returns void. I'm surprised that the code as is actually compiled without an error about this.
Anyways, the book data can be returned from the same way it was passed in - as an input and output parameter.
Essentially your code could look like the following (which is only meant to be an example of code that compiles and works to save info entered in from standard input into the book):
#include <stdio.h>
struct Book {
int value;
};
#define MAX_BOOKS 2
void addBook(struct Book book[], int *size) {
if (*size == MAX_BOOKS) {
printf("The inventory is full\n");
}
else {
printf("Value:");
scanf("%d", &book[*size].value);
(*size)++;
printf("The book is successfully added to the inventory.\n");
}
}
int main(void) {
struct Book book[MAX_BOOKS];
int size = 0;
addBook(book, &size);
printf("Book 1: Value=%d\n", book[0].value);
}
And here's how this looks when run:
$ ./main
Value:9
The book is successfully added to the inventory.
Book 1: Value=9
Hope this answers your question.
I think your problem is in the line *size++;. You should use parenthesis, otherwise you are modifying the pointer to size, not the value. It should be (*size)++.
Also, the addBook function should not return anything, since it is void, and it is changing the content of the array book already.

Why can't I get string input?

I was trying to simulate stack concept, and this is my code, blasts errors everywhere, from
the very first scanf,
to everywhere referring char* variables,
and eventually the stack pointer (I named it towerIndicator) doesn't change at all.
And then every typed input is somehow screwed: if I type '+314' to add 314 to the stack, it eventually add 3144, if all the problem above were somehow prevented while compiling.
gcc doesn't inform me any usable error message so I don't get where to go at all. Desperately requiring help here.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
const int towerHeight = 32;
int tower[towerHeight];
int towerIndicator = 0;
/*
printf("%i개의 정수를 담을 수 있는 스택을 만들었습니다.\n", towerHeight);
printf("- '+'를 붙여서 정수를 담습니다.\n");
printf("- '-'를 입력해 정수를 빼냅니다.\n");
printf("- '?'를 입력해 스택을 확인합니다.\n");
printf("- '0'를 입력해 작업을 종료합니다.\n");
printf("명령을 입력해주세요.\n================================\n");
*/
char* command;
char* kindOfCommand[1];
char* actualCommand;
while(1) {
printf("> ");
scanf("%s", command);
printf("%s", command);
strncpy(*kindOfCommand, command, 1); kindOfCommand[1] = '\0';puts("#");
strncpy(actualCommand, command+1, strlen(command)-1);puts("$");
switch(**kindOfCommand) {
int i;
case '+':
if(towerIndicator<towerHeight) {
tower[towerIndicator] = atoi(actualCommand);
towerIndicator++;
printf("현재 %i개의 값이 있습니다.\n", towerIndicator);
} else printf("더 이상 넣을 곳이 없습니다.\n");
break;
case '-':
if(towerIndicator>0) {
towerIndicator--;
printf("%i\n", tower[towerIndicator]);
printf("현재 %i개의 값이 있습니다.\n", towerIndicator);
} else printf("더 이상 빼낼 값이 없습니다.\n");
break;
case '?':
default:
printf("[");
for(i=0; i<towerIndicator; i++) {
if(i==towerIndicator) printf("[%i]", tower[i]);
else printf("%i", tower[i]);
if(i!=towerIndicator-1) printf(" ");
}
printf("]\n");
break;
}
if(**kindOfCommand=='0') break;
}
}
There are quite a few modifications required here
loosely fixed may be in for a lot more fixes
// char* command; // <-- initialize this, failure in scanf other wise
char command[120] ;
assuming you are looking for a single character, don't complicate code
// char* kindOfCommand[1]; pointer not required
char kindOfCommand;
since you are using strncpy down somewhere
// char* actualCommand; // <-- initialize this
char actualCommand[126];
and the kindOfCommand code change
// strncpy(kindOfCommand, command, 1);
kindOfCommand = *command;// since you are taking single character
puts("#");
some more at switch
switch( kindOfCommand ) {
and while breaking
if( kindOfCommand == '0' ) break;
Also return before end
return 0;
I applied changes from kkk's answer, and getting input now works well.
char command[11];
char kindOfCommand;
char actualCommand[10];
while(1) {
printf("> ");
scanf("%s", command);
kindOfCommand = *command;
memset(actualCommand,0,sizeof(actualCommand));
strncpy(actualCommand, command+1, strlen(command)-1);
switch(kindOfCommand) { ... }
...
if(kindOfCommand=='0') break;
}
return 0;
}
I needed to solve the input getting screwed. It was because when actualCommand receives a new string from command and it's shorter than previous received string, the last few characters of the string was still remaining in actualCommand. So I put a memset to reset the variable every time the while loop loops. It's not a pointer, so sizeof() could do the work. Otherwise I should've to use strlen() to tell memset the length.

can anyone find why is ths program to solve postfix expression giving runtime error

I was trying to solve a postfix expression but i don't understand why is it giving runtime error.
code:
#include<stdio.h>
#include<stdlib.h>
#include<stdlib.h>
struct stack
{
int top;
int n[100];
}s;
void push(int a)
{
s.n[s.top+1]=a;
s.top++;
}
void pop(char a)
{
int c,b;
b=s.n[s.top];
c=s.n[s.top-1];
s.top--;
switch(a)
{
case '+':
s.n[s.top]=b+c;
break;
case '-':
s.n[s.top]=b-c;
break;
case '*':
s.n[s.top]=b*c;
break;
case '/':
s.n[s.top]=b/c;
break;
}
}
int main()
{
s.top=-1;
int m,i,k;
char a[100],c[100];
scanf("%d",&m);
for(i=0;i<m;i++)
{
int j=0;
while(1)
{
scanf("%c",a[j]);
if(a[j]=='?')
break;
else if(a[j]==' ')
{
push(atoi(a));
}
else if(a[j]=='+'||'-'||'*'||'/')
{
pop(a[j]);
}
else
{
j++;
}
}
printf("%d",s.n[s.top]);
}
}
You code is hardly readble, still, I think, you need to change
scanf("%c",a[j]);
to
scanf(" %c",&a[j]); //note the space before %c, and scanf() expects pointer
for
& because as per the scanf() signature, it needs the address to store the scanned result.
leading space [] to stop scanning the previously pressed ENTER [\n] key.
Kindly Check the man page of scanf() for more details.
Also, as mentioned in Mr. #LPs 's answer, usage of push(atoi(a)); is very dangerous, in case a is not null-terminated.
Chnage scanf("%c",a[j]); to scanf("%c",&a[j]);. You need to pass the address to store the value of char. Also, you would further need to discard the extra character after each input from stdin.
I think that instruction push(atoi(a));is not safe, because of the array is not zero initialized, than atoi can fall into undefined behaviour.
Another thing is that with scanf with %c you can accept all chars (eg a, b,c) that make atoi fail.

Get an "EXC_BAD_ACCESS" error, and I have no clue why

Here's the code I've got. It compiles fine, and I simply can't see what might be going wrong:
// This program takes a quadratic from the user, and prints the solution(s) if they exist.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
//Make sign function for switch test - because in the switch expression itself, C refused to believe x/|x| is an integer...
int sign(float f){
printf("\n\nSIGN CALL OK\n\n");
int sign=f/cabs(f);
return sign;
}
// Define quadratic structure
typedef struct quadratic{
float a, b, c;
float discriminant;
float real_root_1;
float real_root_2;
float complex_root;
} Quadratic;
// 'Redefine' malloc to also check allocation of memory when called.
Quadratic* xmalloc(size_t n){
printf("\n\nXMALLOC CALL OK\n\n");
Quadratic* p = malloc(n);
if (p == NULL) {
printf("\n ERROR: Unable to allocate memory! \n");
exit(1);
}
return p;
}
// newquadratic lets the user define the quadratic to be solved, and returns the pointer to its structure.
Quadratic* newquadratic() {
Quadratic* q = xmalloc(sizeof *q);
printf("\n Please enter the coefficients of the quadratic separated by spaces: ");
scanf("%g, %g, %g", q->a, q->b, q->c);
printf("\n\nDATA ACCEPTED\n\n");
return q;
}
// solve takes the existing data from the quadratics structure and defines the remaining quantities, depending on which
// case we get for the 'sign of the discriminant'.
int solve(Quadratic eqn){
printf("\n\nSOLVE CALL OK\n\n");
eqn.discriminant = (eqn.b*eqn.b - 4*eqn.a*eqn.c);
switch (sign(eqn.discriminant)) {
case -1:
eqn.real_root_1 = (-eqn.b+sqrt(eqn.discriminant))/(2*eqn.a);
eqn.real_root_2 = (-eqn.b-sqrt(eqn.discriminant))/(2*eqn.a);
break;
case 0:
eqn.real_root_1 = (-eqn.b+sqrt(eqn.discriminant))/(2*eqn.a);
break;
case 1:
eqn.complex_root = (-eqn.b+sqrt(eqn.discriminant))/(2*eqn.a);
break;
}
return sign(eqn.discriminant);
}
//main also uses sign of the discriminant (as returned by solve) to decide how to behave appropriately for the case it receives.
int main () {
Quadratic* eqn=newquadratic();
printf("\n\n GET QUADRATIC OK\n\n");
switch (solve(*eqn)) {
case -1:
printf("\n\n We have two real solutions, %g and %g", eqn->real_root_1, eqn->real_root_2);
break;
case 0:
printf("\n\n We have one repeated real solution, %g", eqn->real_root_1);
break;
case 1:
printf("\n\n We have two complex solutions, %g%+gi and %g%-gi", creal(eqn->complex_root),cimag(eqn->complex_root),creal(eqn->complex_root),(-1)*cimag(eqn->complex_root));
break;
}
return 0;
}
xmalloc calls correctly, and we get to the stage where the user is to input the 3 coefficients. As soon as return is pushed we get the error.
The problem is in your function newquadratic.
The scanf function expects to be given the address of the variables into which it should put the results, while you've actually passed it the values that the variables hold.
To fix, pass the address of a, b and c like so: (add the & characters)
Quadratic* newquadratic()
{
Quadratic* q = xmalloc(sizeof *q);
printf("\n Please enter the coefficients of the quadratic separated by spaces: ");
scanf("%g, %g, %g", &q->a, &q->b, &q->c);
printf("\n\nDATA ACCEPTED\n\n");
return q;
}

Resources