#include<iostream>
#include<string>
using namespace std;
int main(void) {
struct STRCT {
int num;
string str1,
arrStr1[],
str2,
arrStr2[];
};
int a;
string b[2],
c[3],
d,
e;
a = 10;
b[0] = "hello";
b[1] = "world";
c[0] = "stack";
c[1] = "over";
c[2] = "flow";
d = "random";
e = "text";
//how do i intialize the arrays (arrStr1[] and arrStr2[]) in aStruct along with the rest of items?
//is it like this?
//i want aStruct[] to be an array and i want its size to be declared from the start to later be filled with vals
STRCT aStruct[2];
//then later in the program i want to assign aStruct[] vals
aStruct[0] = {a, //int
d, //string
{b}, //string[]
e, //string
{c}}; //string[]
}
so basically i want to make a struct array with arrays inside then get the proper vals and then assign the proper vals to the arrays inside the struct array. thank you very much in advance for the help
Array declarations in your struct are simply illegal. C++ does not support size-less array declarations as class members. And even if some C++ compiler supports a C99-style "struct hack" declaration, only one size-less array is allowed and the array must be the last member of the struct.
You want to have arrays inside your struct - you have to give them specific compile-time sizes. Without specific compile time size you'll have to use pointers or std::vector.
In your example b has size 2 and c has size 3. You can declare your struct with the same sizes
struct STRCT {
int num;
string str1, arrStr1[2], str2, arrStr2[3];
};
and then initialize it as follows
STRCT aStruct[2] =
{
{
a,
d,
{ b[0], b[1] },
e,
{ c[0], c[1], c[2] }
}
// The rest of the array is value-initialized
};
That's just as far as you can get with ordinary arrays. It you want something more flexible, embedding arrays straight into the struct won't help you here. Either construct the necessary memory structures manually or use std::vector.
In C++ this is illegal
string arr[2] = {"This","is"};
string arr1[2];
arr1 = arr;
There is nothing like "copy an entire array into another array". The array elements must be copied individually.
Second you cant declare arrays of unknown size
You can modify your struct declaration by declaring string array of fixed size and do this
for(int i =0; i< 2; i++)
{
aStruct[i].num = a;
aStruct[i].str1= d;
for(int j=0;j<2;j++)
{
arrStr1[i] = b[i];
}
aStruct[i].str2= e;
for(int k=0;k<3;k++)
{
arrStr2[i] = c[i];
}
}
I suggest instead of string arrStr1[] ,string arrStr2[] , b[2] and c[2] make use of std::vector. That will help you in avoid hard coding the conditions in for loop.
Related
Morning,
I hope somebody is here
suppose I have the following structure or even better an array of structures
struct foo {
int a;
char b[10];
char c;
};
struct foo* bar;
bar = (struct foo*) malloc(sizeof(struct foo)*10);
memset(bar, -1, sizeof(struct foo)*10);
instead of
for (counter = 0; counter < 10; ++counter)
memset(bar[counter],0,sizeof(char)*10);
how to a set b member to 0 in all array of char / b member in all array?
basically my question is a bit similar to this one
I'd like to suggest that rather than using a C-style array of int b[10]; that you use std::array<char,10> b; instead.
Then you can fill it with zeros this way: b.fill(0);.
If you need to pass the address of the storage to a C-style function you can do that using b.data().
And of course, you can still access its content using b[i], but if you want more safety, use b.at(i).
http://en.cppreference.com/w/cpp/container/array
You can set the b member of each array element to zero by setting the b member of each array element to zero. You were almost there, but:
You only wanted to zero the b member.
The thing you're zeroing isn't 8 bytes long.
for (counter = 0; counter < 10; ++counter)
memset(bar[counter].b, 0, sizeof bar[counter].b);
I was wondering if it was okay to pass around/return structs holding statically allocated arrays in C++. For example:
typedef struct t{
char name[32];
int id;
}t;
t foo(char name[]){
t my_t = {name, 0};
return my_t;
}
int main(){
t main_t = foo("a struct");
printf("%s", main_t.name); //is this safe to access?
return 0;
}
When it returns the struct by value, I guess it doesn't copy the array name, only the pointer to it.
Edit: Just to clear up some things. I do know that char *var is equal to char var[] in function arguments. I wrote this code up really quickly without even testing it. I know it is definitely not the best code in the world and I wouldn't advice anybody to use it in real life.
Ideally I would allocate the struct dynamically and pass around a pointer, however, I am teaching a person to program in C/C++. It is for a national exam which doesn't require a person to know dynamic allocation or pointers for that matter, that is why * are not really used at all.
The question is really about whether it is okay to return a struct holding a statically allocated array.
Shall we use this piece of code instead:
#include <iostream>
struct t{
char name[32];
int id;
};
t foo(int id){
t my_t;
my_t.id = id;
for(char i = 0; i < 31; i++){
my_t.name[i] = 'a';
}
my_t.name[31] = '\0';
return my_t;
}
int main(){
t main_t = foo(0);
std::cout << main_t.name; //is this safe to access?
return 0;
}
It can be done.
But it shouldn't be done: alternatives are std::string and std::array. You get your copy, allocation, deallocation etc... for free!
struct t {
std::string name;
int id;
std::array<int, 10> integers;
};
...
t main_t = {"a struct"};
main_t.integers[5] = 5;
t copy = main_t;
assert( copy.name == "a struct" );
assert( copy.id == 0 );
assert( copy.integers[5] == 5 );
There is no static array in your code.
When you return a t instance by value, it will copy the contents of the array.
The problem is with how you're initializing the t instance, not with how you're returning it.
Change this:
t my_t = {name,0};
To this:
t my_t = {0};
strncpy(my_t.name,name,sizeof(my_t.name)-1);
Or to this, if you want to avoid the use of library functions:
int i;
t my_t;
for (i=0; i<sizeof(my_t.name)-1 && name[i]!=0; i++)
my_t.name[i] = name[i];
my_t.name[i] = 0;
my_t.id = 0;
You've an error in your program; you're trying to copy a pointer to an array, instead you should copy the contents pointed to by the pointer into the array. It should be like this
#include <algorithm>
#include <cstring>
struct t
{
char name[32];
int id;
};
t foo(const char *name)
{
t my_t = {};
const size_t len = std::strlen(name);
const size_t max_len = sizeof(t::name) / sizeof(t::name[0]) - 1u;
std::copy(name, name + std::min(len, max_len), my_t.name);
return my_t;
}
int main()
{
t main_t = foo("a struct");
printf("%s", main_t.name);
}
As for your question
I was wondering if it was okay to pass around/return structs holding static arrays in C++
Yes, it's ok, the whole struct will get copied (or moved, depending on the type) to the variable at the calling end.
It's OK to pass around structs that contain arrays. However, this line doesn't do what you think it does:
t my_t = {name, 0};
Using designated initializer syntax, it would be equivalent to:
t my_t = { .name[0] = name; .name[1] = 0; };
The first member of t is an array with 32 elements, so the first 32 initializers are applied to those 32 chars. Unless you use some more braces, but you still need one initializer per element, there's no magic way to get a strcpy out of brace-enclosed initializers.
You should get a compiler error about initializing a char with a pointer.
I want to do something like this below:
int main() {
int a[10];
int *d = generateArrayOfSize(10) // This generates an array of size 10 on the heap
a = d;
print(a); // Prints the first 10 elements of array.
}
However above code gives compilation error (incompatible types in assignment of ‘int*’ to ‘int [10]’).
What can I do to make the above code to work?
Arrays are non-assignable and non-copyable, so you'd have to copy each element by hand (in a loop), or using std::copy.
If you're using C++, then use C++ arrays rather than C style arrays and pointers. Here's an example
#include <array>
#include <iostream>
template<size_t N>
std::array<int, N> generateArrayOfSize(void)
{
std::array<int, N> a;
for (int n=0; n<N; ++n)
a[n] = n;
return a;
}
template<size_t N>
void print(std::array<int, N> const &a)
{
for (auto num : a)
std::cout << num << " ";
}
int main() {
std::array<int, 10> a;
std::array<int, 10> d = generateArrayOfSize<10>();
a = d;
print(a); // Prints the first 10 elements of array.
}
which outputs 0 1 2 3 4 5 6 7 8 9
Arrays are not pointers.
You can't do :
int a[10];
int *d;
a = d;
Change it to :
int *a;
int *d;
a = d;
Main differences between arrays and pointers in C programming :
Pointer | Array
-------------------------------------------|-------------------------------------------
A pointer is a place in memory that keeps | An array is a single, pre allocated chunk
address of another place inside | of contiguous elements (all of the same
| type), fixed in size and location.
-------------------------------------------|-------------------------------------------
A pointer can point to a dynamically | They are static in nature. Once memory is
allocated memory. In this case, the memory | allocated , it cannot be resized or freed
allocation can be resized or freed later. | dynamically.
-------------------------------------------|-------------------------------------------
You have a quite good explanation here : https://stackoverflow.com/a/7725410/1394283
An array is not a pointer (although a name of an array often decays to a pointer to its first element).
To make the above code to work, you can declare a as a pointer: int *a;. The print function takes an int* (or a decayed array) anyway.
If you really want to have two arrays and copy contents from one array to another, you should copy the data in a loop.
This will print in this way when you assign a string reference to a pointer you have to use *ptr to print the value of a pointer otherwise in your case print(d) that is like cout< in c++ it will only print the location of the d[0].
int ary[5]={1,2,3,4,5};
int *d;
d=ary;
for(int i=0;i<5;i++)
cout<<*(d+i);
Because array names are non-modifiable. So you can't do
a = d;
Declare it as a pointer like this:
int *a;
Little rusty with my C++ but try something like this.
int main() {
int *a;
int *d = generateArrayOfSize(10) // This generates an array of size 10 on the heap
a = d;
print(a); // Prints the first 10 elements of array.
}
In C, it was always true when Thing X[10]; was declared, X was the constant address of the first element(i.e. &X[0]). So you could then say:
Thing *Y = X; // Equivalent to (Thing *Y = &X[0];)
But in C++, the compiler "remembers" that the Thing array X has 10 elements, and some C++ imposed type checking rules break. Imagine we add Thing Z[20]; to the discussion.
Thing *Y = X; and Thing *Y = Z; if both allowed, would imply that a single variable could be set to Thing Arrays of length 10 and 20, which are very different (ahem) "things", as a quick look at a 2D array will reveal. This sort of justifies why the C language assumed equivalent of X and &X[0] is broken in C++.
Well, at least for some versions of C++. So best not to assume it, and use
Thing *Y = &x[0]; and Thing *Y = &Z[0] instead;
This approach has two advantages. It does what is wanted, and it actually compiles. :-)
Currently I have a several classes with an array defined as 'float myIDs'. I want to move the variable into my parent class and change it to a pointer ('float * myIDs').
Currently I'm declaring its values like this:
float myIDs[] = {
//Variables
};
As its now a pointer, I thought that it would be roughly the same:
myIDs = new float[] = {
};
but that doesnt seem to be working. I'm not sure how to solve this as I've never had to declare a pointer array like this before.
Can anyone help me please?
Thanks
Note that you're not allocating an array of pointer but just an array of float, so basically you two array would have the same type, they just won't be stored in the same memory space.
Only a statically allocated array can be initialized this way, a dynamically allocated one cannot be initialized to anything other than zero.
myIDs = new float[]();
But if you know the elements to put in the array, you don't need to allocate it dynamically.
If you want to allocate an array of pointer, you have to do this :
float* myIDs[size]; // statically
float** myIDs = new float*[size]; // dynamically
But only the statically allocated one (the first one) can be initialized the way you describe and of course, it must be initialized with pointers.
If you want to declare array in a dynamic way, you can do it like this:
float *array = new float[size];
array[0] = first_value;
array[1] = second_value;
etc;
Just remember to free memory when you no longer need it (e.g. in a class destructor)
delete [] array;
If you want a dynamically allocated array you should use the following format (what you did seems more like C# not C++)
//The declaration of the object in the class
float *myIDs;
//The allocation it self (you must know which size you want to allocate at this point)
myIDs = new float[size];//bring change "size" to whatever you need is.
Consider the following snippet,
#include<iostream>
#include<stdlib.h>
int main(void)
{
int a[] = {1,2};
a =new int[2];
delete(a);
return 0;
}
This gives an error error: incompatible types in assignment of ‘int*’ to ‘int [2]’.
I am statically creating an array of int . a is a pointer(it is of type int[2]) but it can't be used to point to other dynamically allocated arrays because they return pointer of type int*.
If you want to create an array dynamically you have to assign its address to a float*
float * a = new float[10] ;
Refer this too.
The easiest way is:
float *myArray[size];
Example
#include <iostream>
using namespace std;
float* findMax (float* myArray[], int size) {
float max = 0;
int index = 0;
for (int i = 0; i < size; i++) {
if ( *myArray[i] > max) {
max = *myArray[i];
index = i;
}
}
return myArray[index];
}
int main()
{
float a = 1.25;
float b = 2.47;
float c = 3.92;
float d = 4.67;
float e = 5.89;
float f = 6.01;
float *myArray[6];
int len = *(&myArray + 1) - myArray;
myArray[0] = &a;
myArray[1] = &b;
myArray[2] = &c;
myArray[3] = &d;
myArray[4] = &e;
myArray[5] = &f;
cout << "Number of even values are : " << findMax(myArray, len) << endl;
return 0;
}
If you want an array of pointers to float, you must declare it as such. You declared just an array of floats. The name of the array is a pointer of course, but in the C sytnax it is treated the same and just a convenience.
float *myIDs[] = {
//Variables
};
myIDs = new *float[n] = {
};
Alternatively you can use
float **myIDs;
myIDs = new **float;
And access it the same way like an array:
float *x = myIDs[i];
I am having problem handling string array in C++.I tried below two methods.Still
not able to resolve the problem...Here it goes :
When I use :
string* fun(string* a,string*b)
{
string c[];
return c; /* c is string array type*/
}
it returns first string stored in string array c.I want whole string array to be returned.
When I used:
vector<string> fun(vector<string> a,vector<string> b){
vector<string> c;
return c;
}
still,i got some errors.
can you help me know where is the problem in both cases.
What modifications are required to obtain the desired result..
How can I handle string array in C++.
Thanx in advance !!
In the first version, you are returning a pointer to a local variable (your array), which will not exists any longer when you leave the scope. You need to create your array on the heap, e.g. with malloc or new. If you allocate it manually, don't forget to deallocate it.
In the second version, you are returning a copy of the vector declared in your function (if you modify the strings in the returned vector, they'll not be modified in a et b). You are creating an empty vector and not adding anything in it, so it'll not contains any string, though.
If you've got to return an object more complex than string you should pass to your function a link to vector (in your code) and fill it with values. That's a fast and right method.
vector<string> fun(vector<string> a,vector<string> b, vector<string>& result){
res.push_back("one");
res.push_back("two");
res.push_back("three");
}
In C/C++ while returning a string from function a local buffer if returned will not work.
The returned pointer should be a static buffer(like static string c[]) or pointer to a buffer passed in by the caller function (like string *fun(string *a, string *b, string *c) ) or pointer to a memory obtained using malloc/new but not local array.
In your first snippet, you could try initializing with new to allocate the space yourself.
string* func() {
string* c = new string[3];
c[0] = "Hello";
c[1] = "World";
c[2] = "<3";
return c;
}
in main:
m = func();
for(int i = 0; i < 3; i++)
{
cout << m[i] << endl;
}
That should prevent it from losing scope once the function ends. Don't forget to deallocate the space. Note you are returning a pointer to an array, not an array. Also, I had no problem running your second snippet of code. Please always share the errors you are getting.
You can't return arrays directly in C++(it inherits this from C). The way around it is to stuff it into a struct.
struct returned_array
{
string result[100];
};
returned_array fun()
{
returned_array result;
result.result[0] = "whatever";
return result;
}
I just picked an arbitrary size 100 for the example. If you want to base the return size on the size of an array that gets passed in, you can add a template parameter:
template<int N>
struct returned_array
{
string result[N];
};
template<int N>
returned_array<N> fun(string (&)[N])
{
returned_array<N> result;
result.result[0] = "whatever";
return result;
}