Program crash accessing dynamically allocated array from function in C - c

thanks for taking the time to read this.
I'm having my program crash as soon as i try to access an array which was previously dynamycally allocated in a function. Here's some code
//function to allocate my array, gives an array as return
Player* allocate(Player **a, int n) {
*a = (Player *) malloc(sizeof(Player)*(n));
return *a;
}
//populating my allocated array, return an array
Player* initializePlayers(Player *a, int n){
int i=0;
char tmp[MAXCHAR];
for(i=0; i<n; i++){
printf("Insert player name %d\n", i);
scanf("%s", tmp);
strcpy(a[i].playerName,tmp);
printf("Player %s assigned.\n", a[i].playerName);
a[i].playerNumber=i;
}
return a;
}
//setup function which includes both the above ones, called from main
void setup(Player *array, int *nPlayers){
int done=0;
while (done==0){
printf("How many players?\n");
scanf("%d", nPlayers);
if (*nPlayers <2 || *nPlayers>8){
printf("Choose between 2 and 8\n");
waitFor(2);
clear();
done=0;
}
else done=1;
}
allocate(&array, *nPlayers);
initializePlayers(array, *nPlayers);
}
from my main
Player * array=NULL;
//I'm passing nPlayers because i want the value to be saved and available on my main
setup(array, &nPlayers);
for (i=0; i<nPlayers; i++){
printf("It's %s 's turn\n", (array)[i].playerName);
dices=diceRoll(&same);
}
I'm fairly new to programming so I might be missing something that is actually pretty obvious, please don't take anything for granted

Modification to the copied argument array in the function setup() won't affect local variables in function main(). Dereferencing NULL will invoke undefined behavior and your program just happened to crash.
Your setup() should be like this:
void setup(Player **array, int *nPlayers){
/* ... */
allocate(array, *nPlayers);
initializePlayers(*array, *nPlayers);
}
and it should be called like this:
Player * array=NULL;
//I'm passing nPlayers because i want the value to be saved and available on my main
setup(&array, &nPlayers);

Related

Some problem in package function(Wrapper function )in C .How do i package a founction and let the callee founction return multipe values or structure

There are some problems thatconfuse me:
The callee function needs return a structure, but there is not a structure statment in caller function.
If i have to write the declaration in the calling function,it can not be called packaging function.
If i return a structure pointer by callee function, but the structure is in the stack of the called function and will be destroyed after the end, which is not safe. Sometimes i get some warning or even wrong!
I have a limited ideas but it not good. I put the structure into the heap by malloc and return the void*pointer. But this gave birth to a new problem :after each call to this function, in the caller, I cannot release the heap through the free() function,the complier can not identify variable name of structure pointer. I think it verey dangerous. I want when the callee function quit,it can be released by itself.
This is the first time I came to this website to ask questions and I just came into contact with c language,If there is something stupid please point it out.
I have to write the structure declaration outside. This program for judging prime number, and I want to package the founction "judging_number". I do not want to write the structure declaration when I want to call the founction "judging_number".
Please give me some help, I would be very grateful.
Sorry, this is my fault. I compiled it with clang++, I saved it as *.cpp, but I wrote c code in it.
What I mean is, can I put the declaration in the called function to realize the function modularization, how can I not declare a structure before calling the function? Is there any way I can not write a declaration. Like use founction in stdio.h.It is as convenient as using the functions of the standard library. Only need to write a line of function call and pass parameters, the called function can return multiple results.
#include <stdio.h>
struct boundary{
int L;
int R;
};boundary *range;
int *get_number()
{
int *nPtr = (int *)malloc(sizeof(int));
do
{
printf("Please enter a vaild number for judging prime number.Or enter the number 1 to quit.\r\n");
scanf("%d", nPtr);
if (*nPtr == 1)
{
exit(1);
}
} while (*nPtr < 1);
printf("The object is %d\r\n", *nPtr);
return nPtr;
}
int judg_number(int N,boundary range){
if (N%range.L==0&&N!=2){
printf("The number %d is a composite number.\r\n", N);
}
else{
printf("The number %d is a prime number.\r\n", N);
}
return 0;
}
boundary* get_range(int N){
boundary *Ptr = (boundary *)malloc(sizeof(boundary));
*Ptr = {2,N-1};
printf("The range is between %d and %d .\r\n", Ptr->L, Ptr->R);
return Ptr;
}
int main(int argc,char**argv,char**env){
int*N;
while(1){
N=get_number();
range=get_range(*N);
judg_number(*N, *range);
free(N);
free(range);
}
getchar();
getchar();
return 0;
}
You dont need dynamic memory allocation here. If you want to retun an int, retun an int. If you want to retun a stuct return a struct.
You probably want this:
#include <stdio.h>
#include <stdlib.h>
struct boundary {
int L;
int R;
};
struct boundary range;
int get_number()
{
int n;
do
{
printf("Please enter a vaild number for judging prime number.Or enter the number 1 to quit.\r\n");
scanf("%d", &n);
if (n == 1)
{
exit(1);
}
} while (n < 1);
printf("The object is %d\r\n", n);
return n;
}
int judg_number(int N, struct boundary range) {
if (N % range.L == 0 && N != 2) {
printf("The number %d is a composite number.\r\n", N);
}
else {
printf("The number %d is a prime number.\r\n", N);
}
return 0;
}
struct boundary get_range(int N) {
struct boundary b = { 2, N - 1 };
printf("The range is between %d and %d .\r\n", b.L, b.R);
return b;
}
int main(int argc, char** argv, char** env) {
int N;
while (1) {
N = get_number();
range = get_range(N);
judg_number(N, range);
}
getchar();
getchar();
return 0;
}
BTW:
boundary get_range(int N) {... is invalid in C but valid in C++. In C it should be struct boundary get_range(int N) {...

Exception Being Thrown When Accessing Struct Array

When I call the test() function, it prompts me to enter the bet for the first player in my struct array. It accepts my entry. On the second round in my for loop, when asking for the bet for the second person in my struct array, an exception is thrown after a value is entered:
Exception thrown at 0x00577F81 (ucrtbased.dll) in lottery.exe:
0xC0000005: Access violation writing location 0x7B7CC9FC.
If there is a handler for this exception, the program may be safely continued.
Here is my code:
void initNames(struct player *p, int size) {
int i;
for (i = 0; i < size; i++) {
printf("Enter player %d's name...\n", (i + 1));
scanf("%s", p[i].name);
}
return;
}
void initScore(struct player *p, int size) {
int i;
for (i = 0; i < size; i++) {
p[i].wins = 0;
p[i].losses = 0;
p[i].funds = 100.00;
}
return;
}
void test(struct player *p, int size) {
int i;
for (i = 0; i < size; i++) {
printf("%s, you have $%.2lf. Place your bet!\n", p[i].name, p[i].funds);
scanf("%lf", p[i].bet);
}
}
void main() {
int size;
struct player *playerPtr;
printf("How many players?");
scanf("%d", &size);
playerPtr = malloc(sizeof(struct player)*size);
initScore(&playerPtr, size);
initNames(&playerPtr, size);
test(&playerPtr, size);
free(playerPtr);
}
Thanks for any help or explanations!
There is a discrepancy between how you have declared the function initNames and how you are calling it in main.
It is declared as -
void initNames(struct player *p, int size);
Which means it expects a pointer to struct player as the first argument and an int as the second.
In main you are calling it as -
struct player *playerPtr;
initNames(&playerPtr, size);
Now the type of playerPtr is struct player* and thus the type of &playerPtr will be struct player**. Thus there is a type mismatch for the arguments. Your compiler should have warned you about this. Always compile with -Wall to see all the warnings and -Werror to treat warnings as errors.
Coming to the fix -
You are not going to modify playerPtr inside any of the functions. So you need not pass struct player**. So change the call to function as -
initNames(playerPtr, size);
Nothing needs to be changed inside the function because the prototype for the function hasn't been changed.
The exact same issues are with the functions initScore and test too. You can fix them in a similar way by changing the first argument to their call.
Now after fixing this too, the program won't be correct.
Look at the line -
scanf("%lf", p[i].bet);
I am assuming bet is declared with type double. You are now passing the double to scanf where a double* is expected. You need to pass the address of bet. So change the line to -
scanf("%lf", &p[i].bet);
I have fixed all the errors and the working version is at
Ideone.
I have assumed a definition for struct player.
To be more sure about the values being read you should always check the return value of scanf as -
int ret = scanf("%lf", p[i].bet);
if(ret == 0) {
// Print appropriate error message that the value entered in not a double and ask the user to retry
} else if (ret == EOF) {
// The input stream has been closed by the user without providing appropriate input, print appropriate error message and abort.
}
// If execution reaches this point, p[i].bet is safe to use.

Why am I getting garbage value after displaying the data

I am getting garbage value when I display the records.
I have to create a database of students in C using array of structures and without pointers.
Is there any other way of doing this?
How to use array of structures?
#include <stdio.h>
struct student {
char first_name[10],last_name[10];
int roll;
char address[20];
float marks;
};
void accept(struct student);
void display(struct student);
void main() {
struct student S[10];
int n, i;
printf("Enter the number of records to enter : ");
scanf("%d", &n);
for (i = 0; i < n; i++) {
accept(S[i]);
}
for (i = 0; i < n; i++) {
display(S[i]);
}
}
void accept(struct student S) {
scanf("%s", S.first_name);
scanf("%s", S.last_name);
scanf("%d", &S.roll);
scanf("%s", S.address);
scanf("%f", &S.marks);
}
void display(struct student S) {
printf("\n%s", S.first_name);
printf("\n%s", S.last_name);
printf("\n%d", S.roll);
printf("\n%s", S.address);
}
Everything in C is pass-by-value. Which means you are modifying variable copy in stack frame, while real variable passed as parameter remains untouched.
You have to pass an pointer to variable which you want to modify in function.
// Function declaration
void accept(struct student *);
// Call
accept(&S[i]);
// Usage in function via dereference operator
scanf("%s",S->first_name);
If you would like to enter unknown amount of records, you should use VLA (since c99) or dynamically allocate structures.
VLA
scanf("%d",&n);
struct student S[n];
Dynamic callocation
scanf("%d",&n);
struct student * S = malloc(sizeof(struct student) * n);
Because in your case, if user input more that 9 records you are touching outside of bounds, which has undefined behavior.
There are multiple issues in your code:
The standard prototype for main without arguments is int main(void)
You should allocate the array dynamically with calloc.
you should pass structure pointers to the accept and display functions instead of passing structures by value. Passing the destination structure by value is incorrect as the accept function cannot modify the structure in the main function, which remains uninitialized and causes garbage to be displayed. Note that it is actually undefined behavior to access uninitialized data so the program could behave in even worse ways.
You should provide scanf() with the maximum number of arguments to store into character arrays to avoid potential buffer overflows.
you should verify the return values of scanf() to avoid undefined behavior on invalid input.
you could use the %[^\n] scan set to allow embedded spaces in the address field.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
struct student {
char first_name[10], last_name[10];
int roll;
char address[20];
float marks;
};
void accept(struct student *sp);
void display(const struct student *sp);
int main(void) {
struct student *S;
int n, i, j;
printf("Enter the number of records to enter : ");
if (scanf("%d", &n) != 1)
return 1;
S = calloc(sizeof(*S), n);
if (S == NULL) {
return 1;
}
for (i = 0; i < n; i++) {
accept(&S[i]);
}
for (i = 0; i < n; i++) {
display(&S[i]);
}
free(S);
return 0;
}
void accept(struct student *sp) {
if (scanf("%9s%9s&d %19[^\n]%f",
sp->first_name, sp->last_name, &sp->roll,
sp->address, &sp->marks) != 5) {
printf("missing input\n");
exit(1);
}
}
void display(const struct student *sp) {
printf("%s\n", sp->first_name);
printf("%s\n", sp->last_name);
printf("%d\n", sp->roll);
printf("%s\n", sp->address);
printf("%f\n", sp->marks);
printf("\n");
}

Why am I not able to access values that were stored in another function?

Basically, why does it not just print the integers that are entered. Right now it just prints garbage value, but I do not know why it cannot access the values stored after it leaves the function. It only seems to get messed up after leaving the getIntegersFromUser function. If I run the for loop in the getIntegers function it does it properly, but why not in the main function?
Thanks in advance for your help.
#include <stdio.h>
#include <stdlib.h>
void getIntegersFromUser(int N, int *userAnswers)
{
int i;
userAnswers =(int *)malloc(N*sizeof(int));
if (userAnswers)
{ printf("Please enter %d integers\n", N);
for (i=0;i<N; i++)
scanf("%d", (userAnswers+i));
}
}
int main()
{
int i, M=5;
int *p;
getIntegersFromUser(M, p);
for (i=0;i<5;i++)
printf ("%d\n", p[i]);
return 0;
}
Also, this is a homework question, but it's a "Bonus Question", so I'm not trying to "cheat" I just want to make sure I understand all the course material, but if you could still try to give a fairly thorough explanation so that I can actually learn the stuff that would be awesome.
Pointers are passed by value. The function is using a copy of your pointer, which is discarded when the function ends. The caller never sees this copy.
To fix it, you could return the pointer.
int *getIntegersFromUser(int N)
{
int *userAnswers = malloc(...);
...
return userAnswers;
}
/* caller: */
int *p = getIntegersFromUser(M);
Or you could pass your pointer by reference so the function is acting on the same pointer, not a copy.
void getIntegersFromUser(int N, int **userAnswers)
{
*userAnswers = (int *) malloc(N*sizeof(int));
...
}
/* caller: */
int *p;
getIntegersFromUser(N, &p);

C - Call a function

I want to get a value from a function in other function i think i have to call a function in other function, then call it on main, but how?
void funcA(PEOPLE people[], int *total)
{
FILE *fp;
char line[100];
fp = fopen("example.txt", "r");
if (fp == NULL) {
exit(1);
}
else {
fgets(line, 100, fp); //get a number from the txt
total = atoi(line); //convert to int
}
}
void funcB(PEOPLE people[], int *total)
{
int i;
for (i = 0; i < total; i++) {
printf("%s\n", people[i].name);
}
funcA(people, &total);
}
void main()
{
PEOPLE people[100];
int *total;
funcB(people, &total);
}
What i'm doing wrong? I need the value from total to do cicle for;
First, you should call funcA from funcB like this:
funcA(people, total);
Then, if I understand you correctly, you want to return a value from your function(s). You can do it like this:
int funcA(PEOPLE people[], int *total){
int ret;
// set ret to desired value
return ret;
}
...
int value = funcA(people, total);
After sorting this out, you need to initialize your variables correctly, sort out the naming discrepancies (linha vs line, PEOPLE vs PERSON) and all other issues noted by others.
There are numerous problems here (total is a pointer, for loop on the pointer, never initialized to anything, etc etc).
To answer your question, functions have return types:
int foo(void) {
return 3;
}
int main(int argc, char**argv) {
printf("Foo returned %d\n", foo());
return 0;
}
In this case foo returns int. You return values with the return keyword.
You can also return data in pointers:
void foo(int* c) {
*c = 3;
}
int main(int argc, char**argv) {
int h;
foo(&h);
printf("Foo returned %d\n", h);
return 0;
}
This is helpful if you have multiple values to return.
Oh boy !
First what You are doing right or at least it seems so. You are drawing attention and get points for upvotes, despite the fact, that the code looks like typed in directly to the editor box on the Stackoverflow and never checked with any compiler. Good job :)
Now what's wrong. The list is long but some tips
void main()
{
PERSON person[100];
int *total;
funcB(people, &total);
}
void funcB(PEOPLE people[], int *total);
It would be nice if You showed us the definitions of (probably) structs PEOPLE and PERSON.
In the code we can see, there is no definition of people - the variable you pass to funcB.
You define a pointer to int - total and don't initialize it. Then You pass an address of that pointer to funcB which takes int* not int** as a second argument. Those types are not compatible.
void funcB(PEOPLE people[], int *total)
{
int i;
for (i = 0; i < total; i++) {
printf("%s\n", people[i].name);
}
funcA(people, &total);
}
void funcA(PEOPLE people[], int *total)
You use a pointer in the loop condition instead of the value pointed too. There is no value, because You didn't initialize the pointer in main, but here You have incompatible types in the condition. You pass an address of the pointer to funcA instead of the pointer, like in main.
void funcA(PEOPLE people[], int *total)
{
FILE *fp;
char line[100];
fp = fopen("example.txt", "r");
if (fp == NULL) {
exit(1);
}
else {
fgets(line, 100, fp); //get a number from the txt
total = atoi(linha); //convert to int
}
}
You use an undefined symbol 'linha' - I guess it's a misspelling of 'line'. Then You assign an int to a pointer instead of an int pointed to by that pointer.
Check these:
exit() function exited from your program, not only from function. You can use return; to return from the function.
total is not initialized when you use that. Use funcA(people, &total); line before the for loop in your function funcB.

Resources