Passing and Returning structs C - c

So I have had this problem where I keep getting error codes only in my main that (1) The struct has already been defined when I keep my struct in a header file and (2) I am using incompatible pointer types.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "functDefs.h"
#include "writeToFile.c"
#include "readFile.c"
#include "inputContactInfo.c"
#include "contactInfoStruct.h"
int main(void) {
int i = 0;
char *ynAns;
struct contactId *contactInfo;
contactInfo = malloc(sizeof(struct contactId));
do {
if(ynAns != NULL) {
free(ynAns);
}
ynAns = malloc(sizeof(char) * 5);
printf("\nDo you wish to enter a new contact (Yes or No)?: ");
fgets(ynAns, 5, stdin);
ynAns[(strlen(ynAns) - 1)] = '\0';
if (strcmp(ynAns, "Yes") == 0) {
printf("\n");
contactInfo = realloc(contactInfo, sizeof(struct contactId) * (i + 1));
contactInfo[i] = inputContactInfo();
i++;
}
} while(strcmp(ynAns, "No") != 0);
writeToFile(contactInfo, i);
readFile(i);
free(contactInfo);
return 0;
}
Then here are my function definitions:
void writeToFile(struct contactId *contInfo, int numContacts);
struct contactId *inputContactInfo();
void readFile(int numContacts);
And this is the struct header file:
struct contactId {
char firstName[20];
char lastName[20];
char companyName[50];
char phoneNumber[15];
char email[50];
};
I get errors like:
IOlist.c: In function ‘main’:
IOlist.c:28:40: error: incompatible types when assigning to type ‘struct contactId’ from type ‘struct contactId *’
contactInfo[i] = inputContactInfo();
^
IOlist.c:34:21: warning: passing argument 1 of ‘writeToFile’ from incompatible pointer type
writeToFile(contactInfo, i);
^
In file included from IOlist.c:5:0:
writeToFile.c:7:6: note: expected ‘struct contactId *’ but argument is of type ‘struct contactId *’
void writeToFile(struct contactId *contInfo, int numContacts) {
^
And these errors as well:
In file included from IOlist.c:5:0:
writeToFile.c:7:6: error: conflicting types for ‘writeToFile’
void writeToFile(struct contactId *contInfo, int numContacts) {
^
In file included from IOlist.c:4:0:
functDefs.h:1:6: note: previous declaration of ‘writeToFile’ was here
void writeToFile(struct contactId *contInfo, int numContacts);
^
In file included from readFile.c:4:0,
from IOlist.c:6:
contactStruct.h:1:8: error: redefinition of ‘struct contact’
struct contact {
^
In file included from writeToFile.c:4:0,
from IOlist.c:5:
contactStruct.h:1:8: note: originally defined here
struct contact {
^

Your function inputContactInfo() returns a pointer to struct. But the place where it tries to returnn pointer is a struct. You need declare struct contactId **contactInfo, allocate memory for each element, and then you can correctly assign your pointer to contactInfo[i].

Related

How to output a big structure to another module in c?

Is there a best practice for ouput function parameters of big structures that should not be changed? return pointer to struct or return whole structure?
Example:
I have a big data structure in file A that i will call from file B: (typedef struct is in header)
.h
typedef struct
{
int x1;
int x2;
int x3;
int x4;
...
} myStruct;
.c
static myStruct data = {...};
errorType myfunction1(mystruct *outData)
{
*outData = data; //copy data to output
...
}
errorType myfunction2(mystruct **outData)
{
*outData = &data; //just return pointer to structure
...
}
myfunction1 copies the whole structure, so the stack size will rise if i will call this function a lot and the processing time is rising, but the advantage is that the original data could not be changed outside of this file like with myfunction2.
Is there a best practice what of the both to use?
I would use the const keyword for the parameter in myfunction2 so that
Case 1: At compilation any changes on a struct used in the caller would definitely make an error if the argument is also a const struct ;
Case 2: And at least a warning if the argument of the caller is not a const.
Case 1:
foo.h
#ifndef FOO_H
#define FOO_H
typedef struct fooStruct
{
int a;
int b;
int c;
}t_fooStruct;
void cpy_foo(const t_fooStruct ** structToCpy);
#endif
foo.c
#include <stdio.h>
#include <stdlib.h>
#include "foo.h"
t_fooStruct myData = {0,1,2};
void cpy_foo(const t_fooStruct ** structToCpy){
*structToCpy = &myData;
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include "foo.h"
int main(){
const t_fooStruct * mainData;
cpy_foo(&mainData);
printf("After cpy print %d %d %d\n", mainData->a, mainData->b, mainData->c);
mainData->a = 10;
mainData->b = 20;
mainData->c = 30;
printf("After changes print %d %d %d\n\n", mainData->a, mainData->b, mainData->c);
return 0;
}
At compilation this gives:
main.c: In function 'main':
main.c:12:15: error: assignment of member 'a' in read-only object
12 | mainData->a = 10;
| ^
main.c:13:15: error: assignment of member 'b' in read-only object
13 | mainData->b = 20;
| ^
main.c:14:15: error: assignment of member 'c' in read-only object
14 | mainData->c = 30;
|
Case 2:
And if the structure is not a const in the main :
main.c (version without the const)
int main(){
t_fooStruct * mainData;
cpy_foo(&mainData);
[...]
At compilation this outputs:
9 | cpy_foo(&mainData);
| ^~~~~~~~~
| |
| t_fooStruct ** {aka struct fooStruct **}
In file included from main.c:3:
foo.h:12:35: note: expected 'const t_fooStruct **' {aka 'const struct fooStruct **'} but argument is of type 't_fooStruct **' {aka 'struct fooStruct **'}
12 | void cpy_foo(const t_fooStruct ** structToCpy);

Setting array of pointers

i'm doing a small exercise to load an array of pointers (double pointer) to a struct. I have the following definition in the header file:
#include <stdio.h>
#define LEN (5)
typedef struct sample_s {
int num;
char *name;
}sample_t;
typedef struct new_sample_s {
char *string;
sample_t **sample_arr;
}new_sample_t;
sample_t table[LEN] = {
{0, "eel"},
{1, "salmon"},
{2, "cod"},
{3, "tuna"},
{4, "catfish"}
};
and using the definitions int this .c file:
#include "test.h"
void print_new_sample_array(sample_t **sample_arr) {
int len = sizeof(table)/sizeof(new_sample_t);
for(int i = 0; i < len; i++){
printf("The array element is: %s\n", sample_arr[i]->name);
}
}
int main() {
new_sample_t new_sample;
new_sample.sample_arr = table;
print_new_sample_array(new_sample.sample_arr);
return 0;
}
I have two questions:
First I'm not sure how to correctly load the table to the new_sample.sample_arr
Error message here:
test.c: In function ‘main’:
test.c:13:27: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
new_sample.sample_arr = table;
^
Second, I'm not sure how I can refer to the properties of each element in the sample_arr. For example, when I do the following, the program errored out:
for(int i = 0; i < LEN; i++){
printf("This is the elem in the array: %s", new_sample[i]->name);
}
I'm trying to learn more about the double pointer concept and why I did it wrong. I would really appreciate the answer keeps the sample_arr as double pointer
Thank you!
In this assignment statement
new_sample.sample_arr = table;
the right operand (after implicit conversion of the array to pointer to its first element) has the type sample_t * while the left operand has the type sample_t ** due to the declaration of the data member
sample_t **sample_arr;
There is no implicit conversion from the type sample_t * to the type sample_t **. So the compiler issued a message.
You should declare the data member like
sample_t *sample_arr;
and correspondingly the function declaration will look like
void print_new_sample_array(sample_t *sample_arr);
And within the function the call of printf will look like
printf("The array element is: %s\n", sample_arr[i].name);

How to list info about processes using c in freebsd?

I want to list all processes in FreeBSD and I have this code below, which uses kvm, but it does not know what KVM_NO_FILES is, and I can't figure how to fix it. If there is another way of doing it, please do share.
#include <stdio.h>
#include <kvm.h>
#include <limits.h>
#include <sys/param.h>
#include <sys/sysctl.h>
int
main(void)
{
char errbuf[_POSIX2_LINE_MAX];
kvm_t *kernel = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
int nentries = 0;
struct kinfo_proc *kinfo = kvm_getprocs(kernel, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &nentries);
int i;
for (i = 0; i < nentries; ++i) {
printf("%s\n", kinfo[i].p_comm);
}
return 0;
}
And I get this error:
root#freebsd:- # cc -lkvm main.c
main.c:11:53: error: use of undeclared identifier 'KVM_NO_FILES'
kvm_t *kernel = kvm_openfiles(NULL. NULL. NULL, HVM_NO_FILES, errbuf):
main.c:13:71: error: invalid application of 'sizeof' to an incomplete type
'struct kinfo_proc'
...= kvm_getprocs(kernel, HERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &nen...
/usr/include/kvM.h:72:8: note: forward declaration of 'struct kinfo_proc'
struct kinfo_proc;
main.c:18:29: error: subscript of pointer to incomplete type 'struct kinfo_proc'
printf("Xs\n", kinfolil.p_comm):
/usr/include/kvM.h:72:8: note: forward declaration of 'struct kinfo_proc'
struct kinfo_proc;
3 errors generated.

Error while implementing a complex construct in C < char (*(*f())[]) () >

Error while implementing a complex construct in C.
Here is the piece of snippet I had tried.
'Where f is a function returning a pointer to an array of
pointers pointing to a function returning character.'
#include <stdio.h>
int main()
{
char (*(*f())[]) ();
char s ()
{
return 'y';
}
char (*g[1])();
g[0] = s;
printf("%c\n",g[0]());
// here it's throwing error how to fix it?**strong text**
(char (*(*)[])()) func()
{
return g;
}
f = func;
printf("%c\n",(f())[0]());
return 0;
}
Error:
enter code heremain.c: In function ‘main’:
main.c:27:19: warning: implicit declaration of function ‘func’ [-Wimplicit-function-declaration]
(char (*(*)[])()) func()
^~~~
main.c:27:1: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
(char (*(*)[])()) func()
^
main.c:28:1: error: expected ‘;’ before ‘{’ token
{
^
main.c:33:1: error: invalid use of array with unspecified bounds
printf("%c\n",(f())[0]());
^~~~~~
main.c:33:16: error: called object is not a function or function pointer
printf("%c\n",(f())[0]());
Use typedefs to help:
#include <stdio.h>
typedef char (*functionPtr)(void);
typedef char (**arrayOfFunctionPtr)(void);
// OR THIS
// typedef functionPtr* arrayOfFunctionPtr;
typedef arrayOfFunctionPtr (*functionReturningArrayOfFunctionPointers)(void);
int main()
{
functionReturningArrayOfFunctionPointers f;
char s()
{
return 'y';
}
char (*g[1])();
g[0] = s;
printf("%c\n",g[0]());
arrayOfFunctionPtr func()
{
return g;
}
f = func;
printf("%c\n",(f())[0]());
return 0;
}

incompatible types when assigning to type struct * from struct

I can't understand why i get this error : The error is : "incompatible types when assigning to type 'PERSOANA * {aka struct *}' from type 'PERSOANA {aka struct }' "
Can you please explain me where is the mistake ?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char name[20];
char name2[20];
char cnp[15];
} PERSON;
PERSON read_array(int n);
int main()
{
int n;
printf("n = ");
scanf("%d", &n);
PERSON *v;
v = read_array(n); //here i get the error
return 0;
}
PERSON read_array(int n) {
PERSON *v;
v = malloc(n * sizeof(PERSON));
for(int i = 0; i < n; i++) {
printf("name=");
gets(v[i].name);
//more instr
}
return v; // and also here
}
Return a pointer to PERSON, not the object PERSON.
// PERSON read_array(int n);
PERSON *read_array(int n);
// ^
// PERSON read_array(int n) {
// v
PERSON *read_array(int n) {
I can't understand why i get this error : Incompatible types when assigning to type PERSON from type PERSON.
I am reasonably confident that you do not get that error, but if you actually do then you should switch to a better compiler. I speculate that the error you get is instead
Incompatible types when assigning to type PERSON * from type PERSON
, because that's in fact what you are trying to do, given your declaration of function read_array().
From implementation and use, it appears that you want that function to return a pointer to a structure rather than a copy of the structure. That would be
PERSON *read_array(int n);
... and the same in the function definition.

Resources