Trouble Passing array of Structs using pointers - c

I'm having problems with a function that I use to write to an element of an array.
I think it might be because I'm not passing the array of struct correctly. I was wondering if someone can point out how to do this correctly. I've been screwing it up more than fixing it.
let's say I have a function menu.c
I declare my struct newPerson person[MAX_PERSONS];
I then run my function addPerson(person, &num);
which is the following
void addPerson(newPerson *pers, int *num){
pers[*num] = (newPerson) {
"Michelle", "Leo", "6136458798", STUDENT,
.data = {.s = {9, 1234.50, 3}}
};
*num = *num + 1;
}
It runs, but won't print out correctly, I'm guessing because it doesn't write where I want it to pers[num]. I tried calling the function this way also addPerson(&person, &num); instead of just addPerson(person, &num); but then I receive this error
warning: passing argument 1 of ‘addPerson’ from incompatible pointer type [enabled by default]
and
note: expected ‘struct newPerson ’ but argument is of type ‘struct newPerson ()[20]’
I've tried changing the function to void addPerson(newPerson *pers[], int *num){ as well but nothing there. Was wondering if anyone can point out what I'm doing wrong here and how I can fix my problem. Any help would be appreciated, thanks!
Forgot to mention that the addPerson function works in some places where I run it.
int menu(int num) {
newPerson person[MAX_PERSONS];
//printf("THE NUMBER START OF MENU IS %d\n", num); test counter
//addPerson(person, &num); <- WRITES AND READS PROPERLY IF DONE HERE
int option;
printf(
"\n\tPlease choose one of the following options to continue (0-9): ");
scanf("%d", &option);
if (option == 1) { //program will ask for name input
addPerson(person, &num); <- HOWEVER IT DOES NOT WRITE OR READ PROPERLY HERE
menu(num);
}
Both functions are called in menu.c
However when I call addPerson in the if statement, it does not write/read properly.
Just solved the problem by declaring the struct as static!
static newPerson person[MAX_PERSONS];
I'm not sure if this is taboo or anything, but it fixed my problem!

By making static you have made the code inefficient as the memory for
the data structure has been set aside regardless of whether it is
needed or not while the program is executing.(With a static data
structure, the size of the structure is fixed.)
Declare the function like
void addPerson(newPerson *pers[],int *num)
call the function like
void addPerson(newPerson *pers, int *num);
OR
void addPerson(newPerson pers[], int *num);

I was able to get it working by declaring the struct as static
static newPerson person[MAX_PERSONS];
Not sure if this is an actual fix or if it's just masking my problem though.

Related

I want to implement a stack but printf throws a segmentation fault

I want to implement a stack using structures in C. Unfortunately, printf throws a segmentation fault. Perhaps there is a problem with dynamic allocation. Does anyone know how to solve it?
I have been facing this issue for the last two days. Your help will be very helpful for my study.
Here is my code
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define SIZE 256
typedef int (*pf)();
typedef struct _stack{
int arr[SIZE];
int top;
pf push, pop, peek, isEmpty, size, clear, print;
} stack;
void *nstack(){
stack *pstack = (stack *)malloc(sizeof(stack));
void push(int data) {
if(pstack->top < SIZE-1) pstack->arr[++pstack->top]=data;
}
int pop() {
return (pstack->top >= 0)?pstack->arr[pstack->top--]:0;
}
int peek(){
return (pstack->top >= 0)?pstack->arr[pstack->top]:0;
}
bool isEmpty(){
return (pstack->top >= 0)?false:true;
}
int size(){
return pstack->top+1;
}
void clear(){
pstack->top = -1;
}
void print(){
if(!isEmpty()){
for(int i = 0; i <= pstack->top; i++) printf("%d", pstack->arr[i]);
printf("\n");
}
}
pstack->push=push;
pstack->pop=pop;
pstack->peek=peek;
pstack->isEmpty=isEmpty;
pstack->size=size;
pstack->clear=clear;
pstack->print=print;
pstack->top=-1;
return pstack;
}
void dstack(stack *pstack){
free(pstack);
}
void main() {
stack *A = nstack();
A->push(1);
A->push(4);
A->push(6);
printf("%d",A->pop());
printf("%d",A->pop());
dstack(A);
}
While the code compiles (with warning), it try to leverage GCC extensions for functions within functions. However, the internal functions must be called within a valid context - they try to access the local pstackof the nstack function - but it does not exists.
While this style work in many OO langauges (Java, and possibly C++), that support 'closures' or lambda, it does not work for C. Consider changing the interface for each of the function to take stack *, and change the calling sequence to pass it.
void push(stack *pstack, int data) {
if(pstack->top < SIZE-1) pstack->arr[++pstack->top]=data;
}
main() {
...
A->push(A, 1) ;
...
printf("%d", A->pop(A) ;
}
Really, you should edit your question and provide the exact errors but I've decided to do some of the legwork for you since you're probably pretty new to this.
So first thing I did was compile your code here with -Wall and look what I get:
SO_stack.c: In function ‘nstack’:
SO_stack.c:49:17: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
pstack->push=push;
^
SO_stack.c:52:20: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
pstack->isEmpty=isEmpty;
^
SO_stack.c:54:18: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
pstack->clear=clear;
^
SO_stack.c:55:18: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
pstack->print=print;
^
SO_stack.c: At top level:
SO_stack.c:66:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
void main() {
Let's look at the first error on line 49: pstack->push=push;
You've defined push function prototype as: void push(int data) but pstack->push is of type pf which is defined as int (*pf)(); See the problem here? You're trying to pass an argument to a function pointer that is not properly defined to handle the argument AND the return type is different. This is totally wrong. Your push(int data) implementation declares a return type of void and a parameter of int yet your pointer to this function declares a return type of int and a parameter of void. This is the case with push, isEmpty, clear, and print. You're going to have to decide if all of these functions need to have the same prototype or if you need to create several different function pointer types to handle them, etc...
So that's the first problem.
Second problem is that as the warning says, you have a void main() prototype for your main function. You should return int from main and specify a return code to the caller of main (likely the OS)... Commonly, successful execution returns 0 and failure returns -1 but this is specific to the platform so you can instead return EXIT_SUCCESS on success and return EXIT_FAILURE upon failure from main. For this macros to be defined, you need to have #include <stdlib.h> present, which you do.
Next issue is that as a commenter wrote, you should learn to use a debugger such as GDB, LLDB, or Windows Debugger so that you can figure out exactly where the program crashes.
I've not re-written your program because it has so many issues that I don't think it would be constructive to do so in this iteration, however, provide an exact error next time, and use the debugger to see if the crash happens inside of the actual printf() code as you implied, or it happens because you supplied corrupt memory to the printf function. My guess is that it is the latter... Meaning, it is in fact probably your code which is flawed and supplying an invalid char * to printf which is either out of bounds, nonexistent, etc... This is precisely what you will use a debugger to find out, by placing a breakpoint before the trouble code and watching the memory to see what's going on.
You need to either remove int data.
Work on this some more, and you will probably find the rest of the issues yourself, if there are any. You should compile with flag -Wall and consider compiling with flag -Werror to clear this kind of stuff up yourself in the future.

") expect on line 7" Error in c program when passing structure's data

Help me i'm getting ") expected on line" 7 and line 8 error in a C program
Code:
typedef struct {
int rollnum;
char name[20];
char pass[20];
}student;
void updateName(student s1.name); //Getting error here
void updatePass(student s1.pass); // and here
// and all other functions like these
int main()
{
//Some code here....
return 0;
}
rollnum,name,pass all are different arguments for the function, function copies whatever arguments you pass in its scope, and then executes
so you can solve this problem using pointer to your variables as function arguments(See FUNCTION CALL BY REFERANCE)
Or Just pass a single variable in one arguments
Your function parameters are wrong, basically wrong syntax. They should be
void updateName(char *name);
void updatePass(char *pass);
You probably want to also pass the pointer to the updated student structure, so you'll declare two parameters, e.g.
void updateName(student*stud, char*name);

How to use a function containing scanf() in the main function in C

The title describes what I'm trying to do, but I'm getting the error message that I never declared base1. I actually know this, but I'm not exactly sure how to actually fix the problem.
int getBase1(void);
int setBase1(double);
int main(void){
getBase1();
setBase1(base1);
}
int getBase1(void){
printf("Please enter the length of a base: ");
return;
}
int setBase1(double base1){
scanf("%lf", &base1);
}
You must use pointer, otherwise the variable inside the method will not point to the same memory adress. Using pointer you'll be putting the value inside the memory address of the variable that you pass in the function call.
One more thing, this way you will not need return values.
Try this way:
#include <stdio.h>
void getBase1(void);
void setBase1(double *base1);
int main(void){
double base1;
getBase1();
setBase1(&base1);
printf("%lf", base1);
}
void getBase1(void){
printf("Please enter the length of a base: ");
}
void setBase1(double *base1){
scanf("%lf", base1);
}
Seems like you're quite new to C programming. Here's a thing, you simply can't use scanf to modify a value of a main function variable without using pointers. If you read about scanf, you would find out that scanf requires the memory address of a variable; that's why scanf is able to read the format string and modify your variable. So what you're trying to achieve is pretty much similar to scanf, you have to pass the address of base1; first of all declare it! Since that's what compiler is crying about. Do the following things:
Declare and pass the address of the variable you want to modify. Pass the address of base1 like this:
double base1;
getBase1();
setBase1(&base1);
In the function getBase1 you're doing a void return, but your function signature tells the compiler that you would return an int. So your functions should look like this:
void getBase1(void);
void setBase1(double *);
Since your setBase1 is receiving an address, there is no need for an ampersand(&). Simply pass the pointer value received:
void setBase1(double *pBase) { scanf("%lf", pBase); }
You have many errors in your code, first int main(), should have the return type and your function doesn't return anything either. base1 is not declared.
error: ‘base1’ undeclared (first use in this function)
setBase1(base1);
^
where is the base1 in your main function?
Its basic your passing base1 as an argument to setBase1 but base1 is not declared.

Assigning a character array to a character array in a structure

I am working on a project that requires that I make an array of a certain structure type. The structure looks like this:
typedef struct
{
char array[30];
int num;
}structure
I have declared an array of these structures like this:
structure struct1[5];
I passed this structure array to a function which fills the first four elements with a string and a number. The fifth is left blank. Later in the program, I pass the array again and try to set the string in the structure to a user determined string using gets(). I am getting this error:
438:19: error: incompatible types when assigning to type 'char[30]' from type 'char *'
If I need to provide more clarification, please tell me.
Thanks!
EDIT: Here is what I am doing:
typedef struct
{
char array[30];
int num;
}structure;
void fillStructs(structure[]);
void userEditStructs(structure[]);
main()
{
structure myStructs[5];
fillStructs(myStructs);
userEditStructs(myStructs);
return 0;
}
void fillStructs(structure s[])
{
//code to fill myStructs elements 0-3.
}
void userEditStructs(structure s[])
{
char newArr[30];
int newNum;
printf("Please enter your string:\n\nEntry:\t");
gets(newArr);
printf("Please enter your number:\n\nEntry:\t");
scanf("%i", newNum);
s[5].array = newArr;
s[5].num = newNum;
}
you are doing something like this
char a[20];
a = "bla";
you cant do this.
do strcpy(a,"bla"); instead. ( #include <string.h> )
Without looking at the code you are probably trying to do something like:
struct[4].array = gets(<unknown>);
which won't work, as you can't assign the returned char* from gets to an array as the compiler says. You are also using gets, which is strongly discouraged as it performs no bounds checking. Instead, do the following:
fgets(struct[4].array, sizeof(struct[4].array), stdin);
which will do proper bounds checking.

De-Referencing a pointer passed from another function to main()

I'm trying to use a separate function to input data using scanf() (outside of main). This new function is supposed to print a line and then receive input from the user. However something appears to be going awry between the scanf in the function and the printf() function in the main that I am testing it with.
I believe that I am receiving a pointer from the function but certain compiler warning are making me wonder if my assumption about the pointer is even correct.
I am confused by the output of this code:
#include <stdio.h>
void set_Info(void);
int main()
{
int scanNum = 0;
set_Info();
printf("%d", &scanNum);
return 0;
}
void set_Info(void) /* start of function definition */
{
int scanNum;
printf("Scan test, enter a number");
scanf("%d",&scanNum);
}
If I provide a number, say 2, the result of the printf statement in the main() is:
2665560
Now, in so far as I am able to tell that output appears to me like a memory address so what i attempted to do to fix that is dereference the pointer in main like so :
int scanNum = 0;
int scanNumHolder;
set_Info();
scanNumHolder = *scanNum;
printf("%d", &scanNumHolder);
I believe that this code makes scanNum variable to become assigned to the dereferenced value of scanNum. However I get the same output as above when I do this. Which leads me to believe one of two things. Either that I am not correctly dereferencing scanNum, or that scanNum is not in fact a pointer at all in this situation.
The most common error I receive from the compiler is:
error: invalid type argument of unary ‘*’ (have ‘int’)
Which makes sense, I suppose, if I'm attempting to treat an int value as a pointer.
If it is the case that scanNum is not being dereferenced correctly, how can I achieve this?
Thank you for the help
*Update
Thanks for the help.
Just to recap
My set_info function needs to be passed an address parameter. The reason an address parameter has to be used is because the local memory of a function is erased after the function call ends. So in order to do work a variable declared in the main function, I pass the address of the variable in question so that when the function ends the changes are not lost.
Inside the main function, when set_info is called with &scanNum as the argument, it passes a reference tp the variable so that it can be assigned the value generated by the scanf statement in the function.
I realize that what I was doing wrong as correctly pointed out by the awesome people of SO, is that I am trying to call set_info like it returns a value but in fact changes the variable like I actually want.
Thanks again for the help!
This function:
void set_Info(void)
{
int scanNum;
scanf("%d", &scanNum);
}
reads the integral number from the standard input and stores it into scanNum variable, which is local variable with automatic storage duration that exists only within the scope of this function.
And the body of your main:
int scanNum = 0;
set_Info();
printf("%d", &scanNum);
defines a local variable called scanNum, then calls a set_Info() function which doesn't affect scanNum defined in main in any way and then it prints the address of scanNum variable.
This is what you are trying to do:
void set_Info(int* num)
{
// read an integer and store it into int that num points to:
scanf("%d", num);
}
int main()
{
int scanNum = 0;
// pass the address of scanNum to set_Info function so that
// changes to scanNum are visible in the body of main as well:
set_Info(&scanNum);
printf("%d", scanNum);
return 0;
}
I also recommend you spend more time reading some book with C basics before you'll continue programming :)
I would pass in the variable into your set_Info function, so that it knows where to save the data. This would then allow you to scan multiple values, and you would simple increment the pointer. Be sure to pass the variable address into set_Info() using &variableName, since that function expects a pointer
#include <stdio.h>
void set_Info(int *pScanNum);
int main()
{
int scanNum = 0;
set_Info(&scanNum);
printf("%d", scanNum);
return 0;
}
//Pass in the pointer to scanNum
void set_Info(int *pScanNum)
{
printf("Scan test, enter a number");
scanf("%d",pScanNum);
}
Get rid of your ampersand! Printf wants an integer not a pointer.
printf("%d", scanNum);
And as liho said, you need to return scanNum from set_info so you can get at it outside of the function.
int scanNum = set_Info();

Resources