how to display the name of a struct variable in c? [duplicate] - c

This question already has answers here:
Get list of C structure members
(6 answers)
Closed 7 years ago.
I have two variables called x and y in a structure called mystruct, when I have the program I want to be able to display the variable names with its value like this.
mystruct.x --> 3, mystruct.y --> 5
Is there a way to do this without just putting mystruct.x in the printf like a string in c?

you can't extract the name of the struct in a smart and clean way.
the possibility to call the type of a variable or a struct is called "Reflection" - the application ability to reflect upon itself (either in compile or runtime) and extract data like the type, typename, inner variables etc.
this is not supported at all in C. thinking about it , C doesn't care- a struct is basically a row in the memory (like any other variable in C, actually).
you can however , make a not-so-smart implementation that stores the typename equivilant to the memory address :
struct memory_address_to_type_name{
char type_name [20],
void* memory_address
} name_memory_address_map[50];
char* get_name (void* variable){
int i;
for (i=0;i<50;i++){
if (variable == name_memory_address_map[i].memory_address)){
return name_memory_address_map[i].type_name;
}
}
return "not found";
}
int push_name (void* variable , char* type_name){
int i;
for (i=0;i<50;i++){
if (strcmp(name_memory_address_map[i].type_name,"") == 0){
name_memory_address_map[i].memory_address = variable;
strcpy(name_memory_address_map[i].type_name,type_name);
}
return 1;
}
return 0;
}
}
int main (void){
myStruct x;
push_name (&x,"myStruct");
//other code
printf("%s --> %d",get_name(x),x.my_member);
}
of course , this is not a complete example. you do want to use a linked list instead of a ad-hoc bounded array , do much more protecting against overflows and out of arrays errors , etc. this is only the idea.
as a side note (and I might get downvoted for this), as a C++ developer, your problem could be much more easily solved in C++ by using a typeid(x).name() (if the implementation does return normal string , like VC++ implementation) , or reproduce the solution above with std::map and std::string . but this is a side note only.

do you mean something like this: http://ideone.com/3UeJHv:
#include <stdio.h>
#define PRINT_INT(X) printf(#X"-->%d\n",X)
#define PRINT_STUDENT(X) printf(#X".x-->%d " #X".y-->%d\n" ,X.x ,X.y)
struct student
{
int x;
int y;
};
int main()
{
int c = 10;
PRINT_INT(c);
struct student stud1 = {200 , 300};
struct student stud2 = {400 , 500};
PRINT_STUDENT(stud1);
PRINT_STUDENT(stud2);
return 0;
}
output:
c-->10 stud1.x-->200 stud1.y-->300 stud2.x-->400 stud2.y-->500

Related

How to Properly use Array of Structures of C

I'm recently started learning about structures in C Language. I tried out a sample program to extend my learning curve. But, here in this subject, I'm facing few errors. Shall anyone please figure out the errors in the following program.
#include<stdio.h>
main() {
int i;
struct elements {
int z; /* Atomic Number */
float m; /* Mass Number */
char *name;
char *symbol;
};
struct elements e[5];
e[0] = (struct elements){1,1.008,"Hydrogen","H"};
e[1] = (struct elements){2,4.0026,"Helium","He"};
e[2] = (struct elements){3,6.94,"Lithium","Li"};
clrscr();
for(i=0;i<3;i++) {
printf("Element Name: %s\n",e[i].name);
printf("Symbol: %s\n",e[i].symbol);
printf("Atomic Number: %d\n",e[i].z);
printf("Atomic Mass: %0.2f\n",e[i].m);
}
getch();
return 0;
}
This shows the following Error messages:
Despite the other comments, if this is what you have to work with, then you'll still be wanting a solution.
Try:
struct elements e[5] = {
{1,1.008,"Hydrogen","H"},
{2,4.0026,"Helium","He"},
{3,6.94,"Lithium","Li"}
};
What you had would work on later compilers (although some will want char const * in the struct for name and symbol to accept string literals), but its actually not very pretty to read, nor is it necessary when you are defining the entire array.
If you do it this way, you can omit the array size (change [5] to []) and it will size according to the number of elements provided.
You aren't using a standard C compiler so you can't write the code in the standard C language.
You'll have to resort to the 1989 version of the C language known as "C89"/"C90". It doesn't support the compound literal feature (struct elements){1,1.008,"Hydrogen","H"};, because that one was added to the C language 23 years ago.

Returning a tuple from a function in C

I need some hint for implementing this algorithm in C. This is a maximum subarray problem. I have made the polynomial time program and also linear time program. I am new to C so I don't know how to return multiple values from a function as this algorithm requires it. For example this line in the algorithm (left-low,left-high,left-sum)=FIND-MAXIMUM-SUBARRAY(A,low,mid) where FIND-MAX-SUBARRAY(A,low,mid) is a recursive function call.
This is the algorithm from coremen:
Below I have set the global variables cross-low,cross-high,cross-sum . How can I do the same for left-low,left-high,left-sum and right-low,right-high,right-sum?
#include "max_subarray_common.h"
#define SENTINAL -3000
int left_low,left_high,left_sum;
int right_low,right_high,right_sum;
int cross_low,cross_high,cross_sum;
void max_crossing_subarray(int low,int mid,int high)
{
int left_sum=SENTINAL;
int sum=0;
int max_left=low,max_right=high;
for(int i=mid;i>=low;i--)
{
sum=sum+change[i];
if(sum>left_sum)
{
left_sum=sum;
max_left=i;
}
}
int right_sum=0;
sum=0;
for(int j=mid+1;j<=high;j++)
{
sum=sum+change[j];
if(sum>right_sum)
{
right_sum=sum;
max_right=j;
}
}
cross_low=max_left;
cross_high=max_right;
cross_sum=left_sum+right_sum;
}
This is my header file:
#ifndef max_subarray_h
#define max_subarray_h
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
extern int price[];
extern int n;
extern int change[];
extern int from;
extern int to;
extern int max;
void init_change();
void max_subarray_poly();
void max_subarray_crossing();
void max_subarray_rec();
void max_crossing_subarray();
#endif
change[] is the array for which the subarray is to be found. Also my output should look like this:
from=8
to=11
maximum profit=43
You can achieve the objective by defining a structure using the keyword 'struct' that will hold the three variables you intend to return. To do this, add structure definition at the Header section of your c program.
typedef struct left {
int left_low;
int left_high;
int left_sum;
}LEFT;
Define a variable of type LEFT in your main (or where you want to use it)
Note. Return type of your FIND-MAXIMUM-SUBARRAY will be LEFT. You also need to pass your variable 'stleft' to your FIND-MAXIMUM-SUBARRAY function.
LEFT stleft;
Allocate memory to stleft
stleft = malloc(sizeof(LEFT));
Assign values to be returned , to your variable "stleft"
stleft.left_low = max_left;
stleft.left_high = max_left;
stleft.left_sum = left_sum + right_sum;
Return your variable
return stleft;
Accessing left_low in stleft
int newvar1;
newvar1 = stleft.left_low;
For more help lookup C structures
The function computes 3 different indicators for the set of arguments, there are multiple ways to return multiple results:
add extra arguments, one for each result, as pointers to int or whatever type is more appropriate. Store the results indirectly into the variables whose addresses have been passed by the caller before returning a completion code.
add an extra argument to the function, pointer to a structure with one member per result, and populate this structure before return a success code to the caller.
return such a structure by value. This approach is less idiomatic in C because it was not part of the original pre-Ansi C specification. This was a long time ago, more than 30 years, but it is still frowned upon by many programmers. Another downside of this approach is that you cannot return a failure indication easily. As can be seen from the OP's own usage of this solution, it can lead to very ineffective coding practices.
allocate a structure for the results and return the pointer to the caller. You may indicate failure by returning NULL, but it is less informative than an error code. The life cycle of this structure is error prone: this pointer may get lost if the return value is not stored, care must be taken to free it at the appropriate time.
Returning such results via global variables is definitely not a good solution, for reasons explained in the other answers. The second option above is the one I would recommend.

C Struct typdef malloc assignment

I am trying to use struct called BankAccount it takes char array of name 50 letters long , int ID, and double balance. I am trying to use malloc() to put it to pointer but i get this
error : void can not be assigned to an entity of type BankAccount.
typedef struct
{
char name[50];
int ID;
double balance;
} BankAccount;
FILE *fp;
BankAccount *accounts = 0;
int accountSize = 0;
// I init like this in main function
accounts = malloc(accountSize * sizeof(*accounts));
void ReadAccountData(BankAccount *accounts, FILE *fp, int arraySize)
{
int i = 0;
while (!feof && i < arraySize) {
fread(&accounts, sizeof(accounts), i, fp);
i++;
}
}
If you are using C language, you need to use C compiler for your code. The compiler you are using now looks like C++ compiler, which requires casting void * to destined type. In C you shouldn't do this, as pointed out by #Olaf (Why you can't cast void * in C).
How to change compilator? It depends on IDE and operating system, that you are using, this needs to be specified before I can give any more details.
If you want to use C++ you have few options:
Use malloc, but cast return value:
accounts = static_cast<BankAccount *>(
malloc(accountSize * sizeof(BankAccount)));
Use dynamic allocation dedicated for C++ and treat BankAccount as C++ structure(you can add constructors, destructors, methods etc.):
accounts = new BankAccount[accountSize];
Should be like this:
accounts = (BankAccount *)malloc(accountSize * sizeof(BankAccount));

using #define for defining struct objects

I came across this simple program somewhere
#include<stdio.h>
#include<stdlib.h>
char buffer[2];
struct globals {
int value;
char type;
long tup;
};
#define G (*(struct globals*)&buffer)
int main ()
{
G.value = 233;
G.type = '*';
G.tup = 1234123;
printf("\nValue = %d\n",G.value);
printf("\ntype = %c\n",G.type);
printf("\ntup = %ld\n",G.tup);
return 0;
}
It's compiling (using gcc) and executing well and I get the following output:
Value = 233
type = *
tup = 1234123
I am not sure how the #define G statement is working.
How G is defined as an object of type struct globals ?
First, this code has undefined behavior, because it re-interprets a two-byte array as a much larger struct. Therefore, it is writing past the end of the allocated space. You could make your program valid by using the size of the struct to declare the buffer array, like this:
struct globals {
int value;
char type;
long tup;
};
char buffer[sizeof(struct globals)];
The #define is working in its usual way - by providing textual substitutions of the token G, as if you ran a search-and-replace in your favorite text editor. Preprocessor, the first stage of the C compiler, finds every entry G, and replaces it with (*(struct globals*)&buffer).
Once the preprocessor is done, the compiler sees this code:
int main ()
{
(*(struct globals*)&buffer).value = 233;
(*(struct globals*)&buffer).type = '*';
(*(struct globals*)&buffer).tup = 1234123;
printf("\nValue = %d\n",(*(struct globals*)&buffer).value);
printf("\ntype = %c\n",(*(struct globals*)&buffer).type);
printf("\ntup = %ld\n",(*(struct globals*)&buffer).tup);
return 0;
}
The macro simply casts the address of the 2-character buffer buf into a pointer to the appropriate structure type, then de-references that to produce a struct-typed lvalue. That's why the dot (.) struct-access operator works on G.
No idea why anyone would do this. I would think it much cleaner to convert to/from the character array when that is needed (which is "never" in the example code, but presumably it's used somewhere in the larger original code base), or use a union to get rid of the macro.
union {
struct {
int value;
/* ... */
} s;
char c[2];
} G;
G.s.value = 233; /* and so on */
is both cleaner and clearer. Note that the char array is too small.

storing values in union in c

If we have a union with three variables int i, char c, float f; and we store a value in say the variable c now. and we forget what is the variable of the union that holds a value currently, after some time. for this is there any mechanism provided by the language using which we can find out whether it is i or c or f that currently holds a value.
It is not possible. The different members of a union all refer to the same memory adress, they are just different ways of seeing that memory. Modifiying a member of the union modifies all the other. You cannot distinguish one from another.
Well, the point of the union is that all of them will hold a value. The value you read might not make sense if you extract a different type than you put in, though.
You do have to keep track yourself of which type you put in if you intend to extract the same one. There is no language feature to track the situation for you.
#define VARIANT_FLOAT_TYPE 1
#define VARIANT_DOUBLE_TYPE 2
// and so on
struct variant_wb {
union {
float f;
double d;
int i;
char c;
};
int stored_type;
};
Then you could use it like this:
struct variant_wb var;
var.f = 1.23;
var.stored_type = VARIANT_FLOAT_TYPE;
You could also make inumerous functions to deal with this struct/union, or you could learn C++ and do it "properly", since that language has this type of feature. My C++ is not very great, maybe some guru could show how to do a similar solution but in the C++ way.
In C++/Qt/COM/DCOM there is the concept of a "Variant", that's roughly said a union which also stores how the union was accessed.
In C, you would have to provide something like this:
struct myCVariant
{
int variantType;
union
{
char v1;
int v2;
float v3;
} variantContent;
void initVariant()
{
variantType = 0;
}
void setChar(char a)
{
variantType = 1;
variantContent.v1 = a;
}
void setInt(int a)
{
variantType = 2;
variantContent.v2 = a;
}
// ... and so on
bool getChar(char* pa)
{
if (variantType == 1)
{
*pa = variantContent.v1;
return true;
}
return false; // Error reading a char where something else was stored
}
// ... and so on
};
You could copy some Variant implementation in some C++ source and port it to C. It's not completely the same, but it's similar. And it is somewhat typesafe (at least at runtime).
EDIT: hexa beat me by a second. And note, that I did not compile this, so my code might contain typos.
No.
C is a lower-level language. It's allowing you to write whatever you want to raw memory. In the end, whether it contains text, integers, or code, all memory contains bits. There is no really way to determine what those bits represent.
While all union members will "hold a value", there's no mechanism to determine what data type it was originally.
If you need to know this, then you should either store a flag that indicates the data type, or you should not be using a union.
It's OK if you forget because that is going to be written right there on the code and you can read it to find out.

Resources