Exception Being Thrown When Accessing Struct Array - c

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.

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) {...

Error while printing the given inputs

This code:
#include<stdio.h>
struct my_structure {
char name[20];
int number;
int rank;
};
int main()
{
int n,i;
scanf("%d",&n);
struct my_structure variable[n];
struct my_structure *ptr;
ptr = &variable;
for(i=0; i<n; i++)
{
scanf("%s",ptr->name);
scanf("%d",&ptr->number);
scanf("%d",&ptr->rank);
}
for(i=0; i<n; i++)
{
printf("NAME: %s\n", ptr->name);
printf("NUMBER: %d\n", ptr->number);
printf("RANK: %d", ptr->rank);
}
return 0;
}
It is not printing correctly. I want to print the 1st input first and then the second. But I'm getting the output like printing only the second input two times.
Two changes you need to do:-
ptr = variable ;
Then you can increase ptr in loop.(The use of scanf is not robust - how to do it better is shown in the end of the answer).
for(i=0;i<n;i++)
{
scanf("%s",ptr->name);
scanf("%d",&ptr->number);
...
ptr++;
}
After that again do the assignment ptr = variable;.
You can also do this (Illustration on the users code)
..
scanf("%s",ptr[i].name);
scanf("%d",&ptr[i].number);
...
printf("%s",ptr[i].name);
printf("%d",ptr[i].number);
Earlier you have type mismatch in assignment. You were assigning a struct my_structure (*)[n] to struct my_structure*. Check the return value of scanf and also check the value n (n>1).
You can do it on your way also:(Illustration on the users code)
struct my_structure (*ptr)[n] = &variable;
for(i=0;i<n;i++)
{
scanf("%s",(*ptr)[i].name);
scanf("%d",&((*ptr)[i].number));
scanf("%d",&((*ptr)[i].rank));
}
...
printf("%s",(*ptr)[i].name);
printf("%d",((*ptr)[i].number));
Correct way to use scanf would be:-(Notice that here 19 is used - otherwise there is a chance of buffer overrun - and this is being checked using this.This is one less than the size of the array because of the \0 character ) (Correct way)
if(scanf("%19s",ptr[i].name) != 1){
/* error in input */
fprintf(stderr,"Error in input\n");
exit(EXIT_FAILURE);
}
Compile your program with all warnings enabled. gcc -Wall -Werror progname.c.
Clearly you don't even need to use this pointer - why would you do that? You can simply use the array itself in the scanf or printf.

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");
}

Program crash accessing dynamically allocated array from function in 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);

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);

Resources