This question already has answers here:
Concatenating Variable Names in C?
(5 answers)
Closed 8 years ago.
i create a structure in c like this
struct book {
char name;
int page;
} b2,b3,b4;
how can i print these using a for loop.
i mean
for(int i=2 ; i<5 ; ++i)
printf("%c %d", b{i}.name , b{i}.page); //bi.name will not work obviously
is there some kind of special operation that need to do this ?
and i sincerely apologize if it has been answered somewhere else on the site already. i don't know myself what i'm supposed to search for precisely.
I have a solution :
Store structure into an Array of pointer and loop through it
struct book **arr = malloc(sizeof(struct book *) * 4);
arr[0] = &b2;
arr[1] = &b3;
arr[2] = &b4;
arr[3] = NULL;
for (int i=0; i < 3; ++i)
{
printf("%c %d", arr[i]->name , arr[i]->page);
}
EDIT:
Or like other community gyus said, create at begining an array of structure (easier to manipulate)
Example :
struct book books[3];
Or
struct book *books = malloc(sizeof(struct book) * 3);
You could use arrays and macros:
struct book {
char name;
int page;
};
#ifndef __cplusplus
struct
#endif
book library[3];
#define b2 (library[0])
#define b3 (library[1])
#define b4 (library[2])
void initialize(void)
{
b2.name = 'a';
b2.page = 5;
b3.name = 'F';
b3.page = -85;
b4.name = '$';
b4.page = 65535;
}
void Print_Library(void)
{
unsigned int i = 0;
for (i = 0; i < 3; ++i)
{
printf("First character of book %d: %c\n", i, library[i].name);
printf("Page of book %d: %d\n", i, library.page);
printf("\n");
}
}
The name field is a single character not a string.
Note: I used the #if preprocessor directive because instances of structures are defined differently between C and C++ and you specified both.
Edit 1: Accessing variables by name during run-time.
Although I have never needed to access variables by name during run-time, one method is to map variables to their names.
struct book; // forward declaration, see above.
struct Variable_Name_Entry
{
#ifdef __cplusplus // Required since you tagged both languages
std::string name;
book * p_variable;
#else
char name[16];
struct book * p_variable;
#endif
};
#ifndef __cplusplus
struct
#endif
Variable_Name_Entry variable_names[] =
{
{"b2", &b2},
{"b3", &b3},
{"b4", &b4},
};
const unsigned int number_of_variable_names =
sizeof(variable_names) / sizeof(variable_names[0]);
#ifndef __cplusplus
struct
#endif
book * name_to_variable(const char * p_name)
{
unsigned int i = 0;
for (i = 0; i < number_of_variable_names; ++i)
{
#ifdef __cplusplus
if (variable_names[i].name == p_name)
#else
if (strcmp(variable_names[i].name, p_name) == 0)
#endif
{
return variable_names[i].p_variable;
}
}
return NULL;
}
Do you really need to access variable by names or is there a different design available?
You can collect pointers to the variables in an array, e.g. like this in C++11:
for( auto p : {&b2, &b3, &b4} )
{
cout << p->name << " " << p->page << endl;
}
I leave it to you to create similar C language solution, if you want that (the question was/is tagged both C++ and C).
In C the array has to be created more manually, so to speak.
Related
I'm currently learning how to create a C++ library to be referenced in other projects, and I am running into an issue with a "Debug Assertion Failed" error: is_block_type_valid(header-> _block_use). I followed the walkthrough shown here: Create and use your own Dynamic Link Library. Oddly, I am getting the expected answer if I just ignore the error.
My DLL currently only has one function:
cpp:
int calculate_crc(std::string msg)
{
std::vector<std::string> msg_vector = [](std::string& msg1) {
std::string next;
std::vector<std::string> result;
// for each char in string
for (std::string::const_iterator it = msg1.begin(); it != msg1.end(); it++)
{
// if we hit a terminal char
if (*it == ' ')
{
if (!next.empty())
{
// add them to the result vector
result.push_back(next);
next.clear();
}
}
else
{
next += *it;
}
}
if (!next.empty())
{
result.push_back(next);
}
return result;
} (msg);
int crcReg = 0xFFFF;
// iterate through each element in msgVector
for (auto&& element : msg_vector)
{
// step 2: xor operation performed on byte of msg and CRC register
crcReg ^= [](std::string hex) {
std::map<char, int> map;
map['0'] = 0;
map['1'] = 1;
map['2'] = 2;
map['3'] = 3;
map['4'] = 4;
map['5'] = 5;
map['6'] = 6;
map['7'] = 7;
map['8'] = 8;
map['9'] = 9;
map['a'] = 10;
map['b'] = 11;
map['c'] = 12;
map['d'] = 13;
map['e'] = 14;
map['f'] = 15;
return map[hex[1]] + (map[hex[0]] * 16);
} (element);
// step 3-5 are repeated until 8 bit shifts
for (int i = 0; i < 8; i++)
{
int crcCopy = crcReg;
crcReg >>= 1;
if ((crcCopy & 1) == 0)
continue;
else
crcReg ^= 0xA001;
}
}
return crcReg;
}
h:
#pragma once
#ifdef OMRONLIBRARY_EXPORTS
#define OMRONLIBRARY_API __declspec(dllexport)
#else
#define OMRONLIBRARY_API __declspec(dllimport)
#endif
#include <iostream>
extern "C" OMRONLIBRARY_API int calculate_crc(const std::string msg);
std::string is not a safe type to use in a DLL function parameter. Non-POD types should never be passed over a DLL boundary, unless they are type-erased (such as by using a void* pointer) and are only ever accessed directly by code on one side of the boundary and not the other side.
Assuming the caller is even using C++ at all (C-style DLLs can be used in non-C/C++ languages), it may be using a different std::string implementation. Or it may be using a different C++ compiler, or a different version of the same C++ compiler, or even just different settings for alignment, optimizations, etc. And even if all of that matches the DLL, it will likely be using a different instance of the memory manager that the DLL uses for its std::string implementation.
If you want to pass a string to a DLL function safely, use a C-style char* string instead. You can use std::string inside the DLL, if you want to, eg:
int calculate_crc(const char* msg)
{
use msg as-is ...
or
std::string s_msg = msg;
use s_msg as needed ...
}
extern "C" OMRONLIBRARY_API int calculate_crc(const char* msg);
This question already has an answer here:
How to sort an array of structs in C?
(1 answer)
Closed 6 years ago.
I have a C struct declared as below (just a simple example):
typedef struct
{
float score;
char* name;
}
person;
So, along the program, I changed the value of the person's score (i gave them an initial value). So, i plan to put all of the scores inside a vector and sort them. Then, I would like to print a list of the name of all the persons, starting from biggest score to smallest score. Any idea on this last part? I'm not sure how to code it. Thanks.
Similar to the C++ approach above, there is a library function in the C standard library called qsort. It is based upon a comparision function, that creates the ordering on the array members.
For your case a minimal example could look like this:
#include <stdlib.h>
#include <stdio.h>
// Definitiion of a person
typedef struct person
{
float score;
char *name;
} person;
// Some small epsilon
#define EPSILON 1.0e-3f
// Comaprision function. Returns <0 for a<b =0 for a=b and >0 for a>b
static int compare_people( const void *a, const void *b )
{
// Cast to the correct pointer type
const person *p1 = (const person*) a;
const person *p2 = (const person*) b;
// There are different ways of comparing floats to each other. In this case we use |a - b| < epsilon for some small epsilon
float difference = p2->score - p1->score;
if( difference <= -EPSILON )
{
return -1;
}
else if( difference >= +EPSILON )
{
return +1;
}
return 0;
}
int main()
{
// Initialize list of people
size_t num_people = 5;
person people[num_people];
people[0].score = 0.3f;
people[0].name = "Homer";
people[1].score = 1.4f;
people[1].name = "Marge";
people[2].score = 0.02f;
people[2].name = "Bart";
people[3].score = 13.2f;
people[3].name = "Lisa";
people[4].score = 1.0f;
people[4].name = "Maggie";
// Print unsorted
printf( "Unsorted:\n" );
for( size_t i = 0; i < num_people; ++i )
{
printf( " %s - %2.2f\n", people[i].name, people[i].score );
}
printf( "\n" );
// Sort
qsort( people, num_people, sizeof(person), &compare_people );
// Print sorted
printf( "Sorted:\n" ) ;
for( size_t i = 0; i < num_people; ++i )
{
printf( " %s - %2.2f\n", people[i].name, people[i].score );
}
printf( "\n" );
// Done
return EXIT_SUCCESS;
}
Note the comment about comparing floating point values.
If you are using Linux, you can investigate system calls and functions of the C standard library by looking up the corresponding man page, e.g.
man qsort
For example you ll have
vector<person> vec;
Now you want sort this using sort from STL
You first must create method for operator " < "
bool operator<(const person& a, const person& b){
return a.score<b.score;
}
I hope this helps you I m sorry for my bad grammar :)
Example of usage
sort(vec.begin(),vec.end(),[](const person& a, const person&b){return b<a});
Now your vector of person will be sorted upside - down order.
How do I initialize the variable-size C++ struct "StructB" that is declared below:
#include <iostream>
#include <string>
typedef struct {
char* a;
int b;
} StructA;
typedef struct {
StructA* pointers[];
int pcount;
int numbers[];
int ncount;
} StructB;
int main()
{
StructB *sb = new StructB; // I need 'sb' to be allocated in the heap
sb->pcount = 5;
sb->ncount = 3;
sb->pointers = new StructA*[sb->pcount];
sb->numbers = int[sb->ncount];
}
I got these compiler errors. What do these error means and how do I fix them? THank you.
In function 'int main()':
21:43: error: incompatible types in assignment of 'StructA**' to 'StructA* [0]'
22:19: error: expected primary-expression before 'int'
22:19: error: expected ';' before 'int'
listen this is not the good c++ way, you are doing C in a C++ environment
which is OK if it gives you some advantage (IO, typechecking, etc.) or for learning.
Dynamic allocation of memory in C style is entirely manual. So is deallocation.
Since you are using typedef, typedef can make things clearer for you and for the compiler.
Here is a tortured example which I think does what you want.
Notice that it is done "The Hard Way" which is actually the easy way in this case of
C style coding in C++;
#include <iostream>
#include <string>
typedef struct {
char* a;
int b;
} StructA;
typedef StructA* A_p; // A_p is "pointer to structA" (contains address of struct)
typedef A_p* A_p_Array; // A_p_Array is "pointer to A_p" (aka StructA**) contains address of A_p
typedef int* int_Array; // int_Array is "pointer to int" contains address of integer
typedef struct {
A_p_Array A_pointers;
int pcount;
int_Array numbers;
int ncount;
} StructB;
int main()
{
int i;
StructA *sa = new StructA;
StructB *sb = new StructB;
sb->pcount = 5;
sb->ncount = 3;
A_p_Array tmp_A_array;
A_p tmp;
for ( i = 0 ; i < sb->pcount; i++)
{
tmp_A_array = new A_p; // create a StructA pointer
tmp = new StructA; // create a StructA
tmp_A_array = &tmp; // put address of tmp in mp_A_array
tmp_A_array++; // increment array address
}
sb->A_pointers = tmp_A_array; // A_pointers now contains address of dynamically created array
tmp_A_array = NULL; // clear pointer but do NOT delete!
int_Array tmp_i_array;
for ( i = 0 ; i < sb->ncount; i++)
{
tmp_i_array = new int(0); // c++ can create ints with initial values
tmp_i_array++;
}
sb->numbers = tmp_i_array;
tmp_i_array = NULL; // clear pointer but do NOT delete!
/****** USE Structs A & B *****/
// clean up the heap
A_p Ap;
for ( i = 0 ; i < sb->pcount; i++)
{
Ap = sb->A_pointers[i];
delete Ap; // each struct released separately
}
int* ip;
for ( i = 0 ; i < sb->ncount; i++)
{
ip = & sb->numbers[i];
delete ip; //each int released separately
}
delete sb;
return 0;
} // main
There are better ways to do the above
which is one reason c++ and higher languages were invented.
When you get to classes it will be somewhat easier
but you can run in to the same types of problems there
so getting pointers and pointers-to-pointers down
now will serve you in good stead later.
I don't know any C++ at all but I am trying to make a very small update to a C++ library that my application is using. Before I start hacking away at this, I am hoping someone can tell me the proper syntax for the following:
I have the following lines of code:
#define A_NUMBER 100
#define ANOTHER_NUMBER 150
enum {
type1,
type2,
};
static int someMethod(int type)
{
char command[A_NUMBER];
//...more code
}
What I need to be able to do is based on the type argument (type1 or type2) I need to be able to set the size of the array to be either A_NUMBER or ANOTHER_NUMBER.
In pseudo code it would be something like:
if (type == type1) {
char command [A_NUMBER]
}
else if (type == type2) {
char command [ANOTHER_NUMBER]
}
Is there a way to dynamically define the size?
Yes, you can use an std::vector<char>:
if (type == type1) {
std::vector<char> x(A_NUMBER);
} else if (type == type2) {
std::vector<char> x(ANOTHER_NUMBER);
}
Remember to include the header with:
#include <vector>
While your example code matches the "pseudo code" in the question, I think part of the question is how to decide the size via type and then use the resulting storage unconditionally, i.e. outside the conditional blocks.
Then it gets as simple as:
std::vector<char> x;
if (type == type1) {
x.resize(A_NUMBER);
} else if (type == type2) {
x.resize(ANOTHER_NUMBER);
}
I believe this is what you want
std::vector<char> x; // x is empty, with size 0
if (type == type1) {
x.resize(A_NUMBER); // change size to A_NUMBER
} else if (type == type2) {
x.resize(ANOTHER_NUMBER); // change size to ANOTHER_NUMBER
}
Yes and no. In standard C++, you cannot keep the array on the stack and have its size determined in runtime.
However, you can turn the array into a dynamically-allocated one (i.e. on the heap). In C++, the standard way to do this is to use std::vector:
std::vector<char> command(A_NUMBER); // or ANOTHER_NUMBER
Indexing will work just as before: command[5]
However, if you need to pass the array to something which expects a C-style array (i.e. a char *), you'll have to use one of these:
command.data(); // if your compiler supports C++11
&command[0]; // if it does not
And of course, to use std::vector, you'll have to #include <vector>.
Here's an example that works in C and C++:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char *argv[])
{
char *opt;
if(argc == 2) {
opt = *++argv;
}
else {
printf("Usage: %s [small|large]\n", *argv);
return EXIT_FAILURE;
}
int *arr;
int arrlen = 0;
if (strcmp(opt, "small") == 0) {
arrlen = 3;
arr = (int *) malloc(arrlen*sizeof(int));
int i;
for(i = 0; i < arrlen; i++)
arr[i] = i+1;
}
else if (strcmp(opt, "large") == 0) {
arrlen = 5;
arr = (int *) malloc(arrlen*sizeof(int));
int i;
for(i = 0; i < arrlen; i++)
arr[i] = i+1;
}
if (arrlen > 0) {
int i;
for(i = 0; arr[i]; i++)
printf("%i, ", arr[i]);
printf("\n");
free(arr);
}
return EXIT_SUCCESS;
}
Example:
[gyeh#gyeh stackoverflow]$ ./dynarr
Usage: ./dynarr [small|large]
[gyeh#gyeh stackoverflow]$ ./dynarr small
1, 2, 3,
[gyeh#gyeh stackoverflow]$ ./dynarr large
1, 2, 3, 4, 5,
The raw C++ way is new and delete
char * command = new char[A_NUMBER];
// and later delete it like this
delete[] command;
Of course you'll have to manage the memory, and it is not recommended to use this approach because of many reasons you should be able to find online. So in conclusion... don't use this method if vector is an option
If using a big array the best way would be to use C++ vector, you could even consider other data structures like list based on your needs (for example a lot of insert, deletions operations on your array).
I am trying to write this C++ function in which I am trying to set each Sequence in the array of Sequences, however when I follow the code on debug I notice that the array is not changing. In particular:
compressed.data[compressedDataCounter].c = pic.data[i];
compressed.data[compressedDataCounter].times = counter+1;
don't seem to add any new variables to the array, just override the first one.
I am thinking that the root of the problem is the declaration:
CompressedPic compressed;
compressed.data = new Sequence[pic.height * pic.width];
This is the portion of the code:
struct Sequence
{
char c;
int times;
};
struct CompressedPic
{
int height;
int width;
Sequence* data;
};
struct Picture
{
int height;
int width;
char* data;
};
CompressedPic compressThePicture(Picture pic) {
CompressedPic compressed;
compressed.data = new Sequence[pic.height * pic.width];
compressed.height = pic.height;
compressed.width = pic.width;
int compressedDataCounter=0;
for(int i=0; i<(pic.height * pic.width)-1; i++)
{
int counter = 0;
while(pic.data[i] == pic.data[i+1])
{
i++;
counter++;
}
compressed.data[compressedDataCounter].c = pic.data[i];
compressed.data[compressedDataCounter].times = counter+1;
compressedDataCounter++;
}
compressed.data[compressedDataCounter].times = -1;
return compressed;
}
It would be great if someone could figure out why this is happening.
You might want to change:
compressed.data[compressedDataCounter].c = counter+1;
to:
compressed.data[compressedDataCounter].times = counter+1;
So you can change the .times member otherwise you will be overriding your .c member. Right now you are setting .c to 'a' for example. Then you set .c to 103 (counter+1). Which is an int and likely with your archetecture the high bytes are aligning with .c and setting it to 0 as well.
So .c is getting 0'd and .times is never set