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);
Related
So, i was doing some harcker rank exercisies, and i found this exercise.
In short it is an Interval Schedulling problem, but my doubt is about pointers and data structure.
This code below is a simple version of my doubt.
My doubt is in the initialize function. When the program finishes it the ptr pointer variable has only one instance of arrayOfA, the first entry only and i wanted to have the size of N.
So what i did get wrong about this data structure and it`s pointers?
I don't want to use another lib as vector and stuff because i think there is no need of it.
#include <iostream>
struct A
{
unsigned int startTime;
unsigned int duration;
unsigned int endTime;
};
struct B
{
int size;
A* arrayOfA = new A[size];
};
B* initialize(int start_time[], int duration[], int n)
{
B* pointer = new B();
pointer->size = n;
for (int i = 0; i < n; i++)
{
pointer->arrayOfA[i].startTime = start_time[i];
pointer->arrayOfA[i].duration = duration[i];
pointer->arrayOfA[i].endTime = start_time[i] + duration[i];
}
return pointer;
}
int main()
{
//initialization
int n = 6;
int arrayOfStart[] = { 1, 3, 0, 5, 5, 8 };
int arrayOfDuration[] = { 1, 1, 6, 2, 4, 1 };
B* ptr;
ptr = initialize(arrayOfStart, arrayOfDuration, n);
for (int i = 0; i < n; i++)
{
std::cout << ptr->arrayOfA[i].startTime << std::endl;
}
}
I don't want to use another lib as vector and stuff because i think there is no need of it
The fact that you got this simple example wrong - and that this simple example is actually not that simple to implement correctly - is solid evidence that you are wrong.
The whole point of having standard libraries is that there is rarely a good reason to implement these things by hand, and it's easy to get them wrong. And std::vector is not "another lib", it is provided by the standard library for a reason.
the ptr pointer variable has only one instance of arrayOfA
it's only supposed to have one array. You mean, presumably, that the array is the wrong size? How did you tell? What happened when you tried to read all 6 elements?
Anyway, the immediate problem is
A* arrayOfA = new A[size];
... this should go in a constructor. You have to defer evaluation until after you know the value of size.
Then you should also write a destructor, and then you should write the copy constructor, copy assignment operator, and move equivalents.
But if you learned, and used, std::vector instead - you would have finished the problem in the time it took to debug your array handling code.
The whole point of providing libraries of common tools is that you can learn them once and re-use your knowledge. If you write your own bare array code in every hackerrank problem, you can easily encounter different bugs in each one, and you're not accumulating any knowledge you can re-use in the next.
Given this struct:
struct B
{
int size;
A* arrayOfA = new A[size];
};
a default B will have a pointer pointing to an array of size elements. Since size is not initialized, this invokes undefined behavior.
Instead, you can do:
struct B
{
int size;
A* arrayOfA;
};
and after you set the size member, you can allocate the appropriate memory:
pointer->size = n;
pointer->arrayOfA = new A[pointer->size];
Also, don't forget to delete this memory when it's no longer needed by the program.
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. :-)
#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.
Why this is not allowed?
#include <cstdio>
struct Foo {
int fooId;
char arr[ ];
} fooList[] =
{ {1, {'a', 'b'}},
{2, {'c', 'd'}}
};
int main()
{
for (int i = 0; i < 2; i++)
printf("%d %c\n", fooList[i].fooId, fooList[i].arr[0]);
}
whereas, this is allowed:
struct Foo {
int fooId;
char arr[2]; // this line modified
} fooList[] =
{ {1, {'a', 'b'}},
{2, {'c', 'd'}}
};
Only the last member of a C struct can be flexible as in arr[].
Shamelessly copying from paragraph 6.7.2.1, sub-paragraph 16 of the ISO C99 standard:
16 As a special case, the last element
of a structure with more than one
named member may have an incomplete
array type; this is called a flexible
array member. With two exceptions,
the flexible array member is ignored.
First, the size of the structure shall
be equal to the offset of the last
element of an otherwise identical
structure that replaces the flexible
array member with an array of
unspecified length.106)...
EDIT:
As for C++, see this. Bottom-line: flexible array members are not allowed in C++ at all - at least for the time being.
In C++ all members of an user defined type must have complete types, and the member arr does not have a complete type unless you give it a size.
In C, the struct definition would compile, but you might not get what you want. The problem is that an array without size is allowed at the end of a struct to be used as a proxy to access the contiguous block of memory after the instance. This allows a dumb vector implementation as:
typedef struct vector {
int size;
char buffer[];
} vector;
vector* create_vector( int size ) {
vector* p = (vector*) malloc( sizeof *p + size ); // manually allocate "size" extra
p->size = size;
};
int main() {
vector* v = create_vector(10);
for ( int i = 0; i < v->size; ++i )
printf("%d\n", v->buffer[i] );
free(v);
}
But the language does not allow you to initialize with the curly braces as the compiler does not know how much memory has to be held (in general, in some circumstances it can know). The size-less member of the struct is only a way of accessing beyond the end of the object, it does not hold memory in itself:
printf( "sizeof(vector)=%d\n", sizeof(vector) ); // == sizeof(int)
In C++03, this is not allowed in struct or class!
Comeau C++ compiler gives this error:
"ComeauTest.c", line 3: error:
incomplete type is not allowed
char arr[ ];
^
Exactly simlar question yesterday : Difference between int* and int[] in C++
I happened to ask myself a question about arrays in c++.
Well, we all know that arrays are fixed collections of something, I say fixed because it is necessary to declare array length when defining arrays.
Well, let's consider an example:
char myarray[10] = {'\0'};
int sz = sizeof(myarray); // It is supposed to be 10
Well, it is correct, 10 is the number returned by sizeof. This can be done by the compiler because he knows how much space it placed for that variable.
Now consider what happens in this situation:
void dosome(mystruct* arr) {
int elements = sizeof(arr)/sizeof(mystruct);
for (int i = 0; i < elements; i++) {
// Do something hoping no overflow will ever occur
}
}
Nice... but I suppose it can be overflow prone. If I pass to this function an array I created in a "normal" way, everything should be fine:
mystruct array[20];
dosome(array);
No problem. But if I do this:
mystruct* array = (mystruct*)malloc(80*sizeof(mystruct));
dosome(array);
WHAT HAPPENS???????????????????
I would like to understand how sizeof behaves, this function is evaluated at compile time right??? ok, what happens when I use not an array, but something very cumbersome like a block of data like that one? furthermore, I could realloc it woth another call to malloc and ask to dosome to process that datablock again. Will it work?
I could try it physically, but I would get some exact answer about the behavioir of sizeof.
Thank you.
it's wrong starting from the mystruct array[20] example. Because the function receives a pointer type, and not an array type, it cannot deduce the number of elements in the array. you are actually getting the size of a mystruct* when you perform sizeof(arr).
You can use templates to write functions which take arrays as parameters, but the suggested way in C++ is to use vectors, if I am not wrong.
The "way" to receive arrays as parameters would be to write something like:
template <int N> void somefunction(int (&v)[N]);
EDIT corrected the function declaration. oops.
void dosome(mystruct* arr) {
int elements = sizeof(arr)/sizeof(mystruct);
for (int i = 0; i < elements; i++) {
// Do something hoping no overflow will ever occur
}
}
What type does arr have in this example? mystruct*! And it's size is most likely 4 or 8. If you want to pass statically/automatically allocated arrays (not new'd) to functions preserving the size so that your trick works, pass by REFERENCE!
template <int N>
void dosome(mystruct (& arr) [N]) {
for (int i = 0; i < N; i++) {
// Do something . No overflow will occur
}
}
Also note this
int a[20];
sizof a; //equals to 20*sizeof(int)
int* b = new int [20];
sizeof b; //equals to sizeof pointer, most likely 4
sizeof is a compile-time operator. And here it computes only the size of a pointer.