C- Passing entire structure variable - c

Here is a simple C programs in structure but i dont quite get what am i doing wrong as the output is not what i desired ,
P1
#include<stdio.h>
struct book
{
char name[10];
char author[10];
int refno;
};
//passing whole structure variable
void display(struct book b)
{
printf("%s %s %d",b.name,b.author,b.refno);
}
int main()
{
struct book b1={"LET US C","YPK",25};
display(b1);
}
Here this one works completely fine with output:
LET US C YPK 25
--------------------------------
Process exited after 0.3952 seconds with return value 0
Press any key to continue . . .
BUT if i try
struct{
// element -1;
//element -2;
//element-3;
}b1;
/*then*/
int main()
{
b1={"LET US C","YPK",25};
display(b1);
It shows error messages:-
1:[Warning] extended initializer lists only available with -std=c++11 or -std=gnu++11
2:[Error] no match for 'operator=' (operand types are 'book' and '<brace-enclosed initializer list>')
3:[Note] candidate is:
4:[Note] book& book::operator=(const book&)
5:[Note] no known conversion for argument 1 from '<brace-enclosed initializer list>' to 'const book&'
The same messsages are shown if i try :
struct book
{
//elements declarations as p1
}b[10];
int main()
{
b[1]={"LET US C","YPK",25};
display(b[1]);
}
OR WITH
struct book
{
//elements declarations as p1
};
int main()
{
struct book b[10];
b[1]={"LET US C","YPK",25};
display(b[1]);
}
So whats the problem?
and actually my main objective was to define array of structure, as in second last and last
method but it does not seem to work so please help>

In C, the syntax {elem1, elem2, elem3, ...} is only valid if you are initializing a structure (or an array) not assigning one. That's why it doesn't work in your example.
When you write b[1]={"LET US C","YPK",25}; you are trying to assign a value not initializing one.
For short:
Initializing is when you give a value to a variable that you are creating at the moment
Assigning is when you give a value to a variable already created.
For you example to work you can write this
struct book
{
char name[10];
char author[10];
int refno;
};
int main()
{
struct book b[10];
b[1]=(struct book){"LET US C","YPK",25};
^^^^^^^^^^^^
display(b[1]);
}
Now, you can declare structure variable anywhere, either right after structure declaration or anywhere in the main function but the point to be noted is when you are defining/assigning any of the variable i have used
(struct book) on the right hand side of assignment operator which helps compiler to understand that b[1] variable belongs to struct book data type, which corrects the error present in the program.
This feature of C language is known as compound literal.

Related

Double linked list2

I did a lot of linked lists already,
but I didn't use them for a while and didn't really programm anything, therefore I am litterally lost.
The following is my Code:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int age;
int pers_num;
char name[100];
void *previous;
void *next;
}Person;
int main(){
Person first_element;
Person last_element;
first_element.next = (Person *)(&last_element);
last_element.age = 19;
printf("%d\n",(&last_element)->age);
printf("%d\n",(first_element.next)->age);
}
Could you explain to me why following error is thrown?
speicher.c: In function 'main':
speicher.c:22:39: warning: dereferencing 'void *' pointer
23 | printf("%d\n",(first_element.next)->age);
| ^~
speicher.c:23:39: error: request for member 'age' in something not a structure or union
As I understand it "first_element.next" should be the pointer which points at last_element.
therefore you should be able to use the -> to access the data inside last_element.
The line 22 Runs perfectly even thought it should have the same Output as line 23, where the error is thrown.
You can't dereference a void pointer because it's a pointer that references a void type :-) In other words, it doesn't really know what actual type it points at. The reason why the two lines behave differently are, keeping in mind that a->b is just syntactic sugar for (*a).b:
printf("%d\n",(&last)->age);
// This (&last)->age, which is actually the same
// as last.age. In both cases, the type being used
// to get the age field is Person, so no problem.
printf("%d\n",(first.next)->age);
// This (first.next)->age is the same as
// (*(first.next)).age. Because first.next is of type
// void *, it cannot be dereferenced.
What you are doing is akin to declaring a variable with void x, which is not valid (don't confuse that with void *x which is valid).
You would be better off (within the structure) pointing to the actual type you want, with something like:
typedef struct s_Person { // A
int age;
int pers_num;
char name[100];
struct s_Person *previous, *next;
} Person; // B
Note that you cannot use the Person type definition while you're creating it, since it does not yet exist. Simplistically, you can think of it coming into existence at the B point. The named structure s_Person comes into existence at A so it can be used within the structure.

Garbage value given as output

struct book{
char novel[20];
char author[20];
int pages;
float price;
};
void details(struct book b1){
printf("\nEnter the name of novel,author,no. of pages and price:");
scanf("%s",b1.novel);
scanf("%s",b1.author);
scanf("%d",&b1.pages);
scanf("%f",&b1.price);
}
int main(){
struct book b1;
details(b1);
printf("***NOVEL Details***\n");
printf("\n%s",b1.novel);
printf("\n%s",b1.author);
printf("\n%d",b1.pages);
printf("\n%.2f",b1.price);
return 0;
}
I've tried the same program with a structure of arrays and it works completely fine. Problem arises when a single structure is passed into function and it gives garbage value. I guess there is some problem when calling by value and not address. Please correct me if you find any error
You are correct that the problem is happening due to not passing by reference. Otherwise b1 in main isn't being set and you are just printing whatever values it was initialized with.
Try passing your struct as by reference instead of value for details function
from
void details(struct book b1)
to
void details(struct book * b1)
and changing b1.novel to b1->novel where it is appropriate (in the details() function). You use this syntax for struct pointers. b1->novel is just syntactic sugar for (*b1).novel which is dereferencing the pointer before access the value

Pass a string in a struct to a function and return it

I want to return the name of the smallest city population-wise, if it is the second city. (Please don't mind the if statement, I know it's bland), the missing return is what bothers me.
I assume I should declare a pointer inside the function rSmallestCity, like *rtrn but I guess the source variable is destroyed before it is used?
typedef struct Coordinate{
int x,y;
}Coordinate;
typedef struct city{
char name[20];
int population;
Coordinate coordinates;
}city;
char *rSmallestCity(city **cl, int n)
{
char *rtrn = NULL;
if(cl[n-2]->population>cl[n-1]->population)
{
rtrn = &cl[n-1]->name;
}
return rtrn;
}
int main()
{
city c1 ={.name="Mumbai", .population=310, .coordinates.x=3, .coordinates.y=4};
city c2 ={.name="Delhi", .population=300, .coordinates.x=3, .coordinates.y=2};
city *clist[2];
clist[0]=&c1;
clist[1]=&c2;
printf("\n%s is smallest\n",rSmallestCity(clist,2));
}
warning: assignment to 'char ' from incompatible pointer type 'char ()[20]' [-Wincompatible-pointer-types]|
I assume I should declare a pointer inside the function rSmallestCity, like *rtrn but I guess the source variable is destroyed before it is used?
A good question. And your assumption is correct. Creating a variable inside a function it's existence ends upon leaving the function. But in this case, because the struct member name is already a char * you do not need to create another variable. Just return c1.name. (see code example below.)
A few other suggestions:
In the struct declaration:
typedef struct Coordinate{
int x,y;
}Coordinate;
You've used the same symbol (Coordinate) for the struct name, and for it's typedef. This is not a good practice. If you need both a struct name and a typedef, pick different symbols. BTW, in this this example, only one or the other is needed. Say you pick the typedef, then the struct is completely defined by:
typedef struct {
int x,y;
}Coordinate;
That suggestion applies to both struct declarations in your example code.
The signatures for the main function do not include int main(){...} rather
int main(void){..., return 0;} and int main(int argc, char *argv[]){..., return 0;}
The following code example illustrates some of the other suggestions for improvements in comments under your post,
typedef struct {
int x,y;
}Coordinate;
typedef struct {
char name[20];
int population;
Coordinate coordinates;
}city;
//return char * rather than char to allow for full null terminated char array (string)
char * rSmallestCity(city c1[],int cityCount)//generisize function prototype to
{ //to easily accommodate bigger arrays if needed
long long size, sizeKeep = 8e9; //index and population. initialize larger than possible population
int indexKeep = 0;
//note you do not need to define a char *, the struct already contains one
for(int i=0; i<cityCount; i++)//use a loop rather than a single comparison, keep the smalles
{
size = c1[i].population;
sizeKeep = (size < sizeKeep) ? indexKeep = i, size : sizeKeep;
}
printf("\n%s\n",c1[indexKeep].name);
return c1[indexKeep].name;
};
int main(void)//use minimum signature for main, and call return before leaving.
{
//combining your original declarations and assignments for struct
//into a single declaration/definition.
city c1[] = {{.name="Mumbai", .population=310, .coordinates.x=3, .coordinates.y=4},
{.name="Delhi", .population=300, .coordinates.x=3, .coordinates.y=2}};
int cityCount = sizeof(c1)/sizeof(c1[0]);
printf("\n%s is smallest",rSmallestCity(c1, cityCount));
return 0;
};
The solution that I originally left in comment under OP (remove & in the line &cl[n-1]->name;) needs some explanations to avoid problems later.
(It is an educational answer not a full answer on pointers, array decay, ... And many examples can be found on stackoverflow. I tried to simplify)
Try this simple code.
int main()
{
char myString1[25]="Toulouse" ; // French City
printf("%p\n",myString1);
printf("%p\n",&myString1);
}
The output is the same, but an array name and the address of an array name are not the same. The array name is evaluated to the address of its first element. So it works in your case but a warning is issued during compilation and it is very important. Firstly, do not remove compilation warnings.
Now, try this code :
int main()
{
char myString1[25]="Toulouse" ; // French City
printf("%p\n",myString1+1);
printf("%p\n",&myString1+1);
}
The outputs are different. Because myString1 is evaluated to char* and &myString1 to char [25]. So +1, in the first, case adds one (sizeof char) to the pointer and in the other case, it adds 25.
Delete the "&" in the line:
rtrn = &cl[n-1]->name;
To extremely simplify, you assigned an "address of char[]" to a char*, but array syntax makes it work regardless.

C: Putting a function pointer in a structure where the function uses that structure as an argument

I seem to have run into a chicken and egg problem.
I want to have a structure that as one of its members is a function pointer. However this function pointer wants to use that same structure as it's argument. This creates an issue where I have to define the function pointer before I can include it as a member, but I can't properly define it until I've defined the structure.
I have found that if I simply leave the argument list for the function pointer blank it SEEMS to work, though what I have read is that this is potentially fraught with issues.
Below is what I currently have:
#include <stdio.h>
typedef void (*IO_fun_ptr_t)();
typedef struct IO_config_t{
int address;
IO_fun_ptr_t IO_fun_ptr; //pointer to the function to be used
} IO_config_t;
void print_address (IO_config_t *input){
printf("The address is %d \n", input->address);
printf("Push any key to continue:");
getchar();
}
void main()
{
IO_config_t input = {.address = 16,
.IO_fun_ptr = &print_address};
input.IO_fun_ptr(&input);
}
The result is:
The address is 16
Push any key to continue:
This works but I'm concerned about the potential implications of leaving that argument blank.
As a bit of an aside, I originally thought that I should be able to use void* as an argument as a placeholder for pointer to an unknown argument type, but I would get compile errors when doing so at the point where I assign the pointer to my function:
typedef void (*IO_fun_ptr_t)(void *);
(Error[Pe144]: a value of type "void (*)(IO_config_t *)" cannot be
used to initialize an entity of type "IO_fun_ptr_t")
Any advice on how to do this better and cleaner?
Use forward-declarations.
This is a way of stating that a structure exists, but without providing details of all the members of the structure until later.
#include <stdio.h>
// 1.) Forward declaration: Here is the name of the structure
// but member-details are omitted.
struct IO_config_t;
// 2.) typedef of the structure
// Still no details on the members.
typedef struct IO_config_t IO_config_t;
// 3.) The parameter to the function is listed, using the definition
// from step 2.) (note: Still no details on the members yet)
typedef void (*IO_fun_ptr_t)(IO_config_t* input);
// 4.) Now we actually detail the members of the structure
struct IO_config_t{
int address;
IO_fun_ptr_t IO_fun_ptr;
};
void print_address (IO_config_t *input){
printf("The address is %d \n", input->address);
printf("Push any key to continue:");
getchar();
}
void main()
{
IO_config_t input = {.address = 16,
.IO_fun_ptr = &print_address};
input.IO_fun_ptr(&input);
}
This is demonstrated in the short program: https://ideone.com/p3jBYt
So I had searched through stack exchange and couldn't find anything so humbled myself to asking a question. Just as I'm getting to the end of writing everything up, I glance over to the "Similar Questions" box to the right, and I happen to see the following question that I didn't come across before:
How to properly define a function pointer in struct, which takes struct as a pointer?
And in its answer I found my answer. I simply have to define the function pointer in the structure itself, not before hand. (I had tried, but forgot to include the struct keyword in the definition so it didn't work since the type def wasn't complete I am guessing).
Below is what compiles clean and seems to work:
#include <stdio.h>
typedef struct IO_config_t{
int address;
void (*IO_fun_ptr)(struct IO_config_t *); //pointer to the function to be used
} IO_config_t;
void print_address (IO_config_t *input){
printf("The address is %d \n", input->address);
printf("Push any key to continue:");
getchar();
}
void main()
{
IO_config_t input = {.address = 16,
.IO_fun_ptr = &print_address};
input.IO_fun_ptr(&input);
}

Struct within struct, using typedef and arrays

UPDATE: Code is correct and sensible, comments provide how to assign values to struct variables
I am writing a struct in C that contains 2 integer arrays and an array of custom-defined type 'info'. This 'info' type just contains several int variables. Here is the piece of code that I've come up with having done a bit of searching around the web:
typedef struct info {
int test_count;
int skip_count;
int prime_count;
} info;
struct myStruct {
int arr1[10];
int arr2[20];
info info[20];
};
This does not generate any compiler warnings or errors, but is it the most sensible implementation given what I'm trying to do?
Also– How would I assign values to the info variables and then access them through myStruct? I've tried various statements using the dot operator, but I cannot get them past the compiler.
Looks OK to me. Example usage struct myStruct x; x.info[3].skip_count = 4;
– M.M
And given: struct myStruct x; you should be able to use x.info[13].prime_count to access an element of that array.
– Jonathan Leffler

Resources