How to determine 2D unsigned short pointers array length in c++ - c++

I am finding it difficult to determine the length of the columns in a 2D unsigned short pointer array. I have done memory allocation correctly as far as I know. and can print them correctly.
plz see the following code segment:
int number_of_array_index_required_for_pointer_abc=3;
char A[3][16];
strcpy(A[0],"Hello");
strcpy(A[1],"World");
strcpy(A[2],"Tumanicko");
cout<<number_of_array_index_required_for_pointer_abc*sizeof(unsigned short)<<endl;
unsigned short ** pqr=(unsigned short **)malloc(number_of_array_index_required_for_pointer_abc*sizeof(unsigned short));
for(int i=0;i<number_of_array_index_required_for_pointer_abc;i++)
{
int ajira = strlen(A[i])*sizeof(unsigned short);
cout<<i<<" = "<<ajira<<endl;
pqr[i]=(unsigned short *)malloc(ajira);
cout<<"alocated pqr[i]= "<<sizeof pqr<<endl;
int j=0;
for(j=0;j<strlen(A[i]);j++)
{
pqr[i][j]=(unsigned short)A[i][j];
}
pqr[i][j]='\0';
}
for(int i=0;i<number_of_array_index_required_for_pointer_abc;i++)
{
//ln= (sizeof pqr[i])/(sizeof pqr[0]);
//cout<<"Size of pqr["<<i<<"]= "<<ln<<endl;
// I want to know the size of the columns i.e. pqr[i]'s length instead of finding '\0'
for(int k=0;(char)pqr[i][k]!='\0';k++)
cout<<(char)pqr[i][k];
cout<<endl;
}

You're almost there. You have this loop:
for(int k=0;(char)pqr[i][k]!='\0';k++) ...
Once this loop is done, k will have the length of the row. So this will give you the length of pqr[i] (not including the null terminator):
int k;
for (k=0; pqr[i][k] != 0; k++)
;
cout<<"The length is "<< k <<endl;
Edit:
You now added that you want to know the size even if the null terminator is not there. There is no way to do that. You will need to either have some kind of terminator, or store the size somewhere. If you use vector<unsigned short>, it will store the size for you. Since it also handles allocation and deallocation, it's the recommended choice.
</Edit>
Note that you have two errors in your allocation:
pqr is an array of pointers, but you're allocating a size of C*sizeof(unsigned short). that should be C*sizeof(unsigned short *) instead.
You're not allocating memory for the null terminator at the end of each string: You should be allocating (strlen(A[i])+1) * sizeof(unsigned short) for each string.

You have a bug at this line:
pqr[i][j]='\0';
At this point j is equal to strlen(A[i]) - which is outside the bounds you setup for pqr:
int ajira = strlen(A[i])*sizeof(unsigned short);
pqr[i]=(unsigned short *)malloc(ajira);
pqr[i] goes from [0] to [strlen(A[i])-1] so writing to pqr[i][strlen(A[i])] overflows the array. The compiler won't pick up on this as you allocated the memory yourself.
The solution to that bug is to do malloc(ajira+sizeof(unsigned short))
Edited after comments

Related

Put an array in the end of another array C++

Normally it's a question about a buffer with a null-terminated string, but we can extrapolate it to a general case.
I have a big array of a fixed length, let's say 10:
char outputArray[10] = {'-','-','-','-','-','-','-','-','-','-'};
And I have some other (Edited: smaller) array (in my case it's a char buffer with null terminator) with a variable length. Let's say it's a buffer of 6 elements, but the actual length is indicated by another variable.
char inputArray[10] = {'h','i','/0',...some other values, i'm not interested in};
int arrLength = 2; // For my task it means a strlen(inputArray);
How to put a small array at the end of a big array, to get this:
outputArray = {'-','-','-','-','-','-','-','-','h','i'} // the null terminator isn't important, it's not about the strings, it's about arrays.
Constraints:
I can't use std, so only "native" solutions (it's for Arduino)
C++11
Code should be memory and time efficient (some elegant algorithm without too much loops and too much temporary variables or calculations please)
Thank you in advance
Edited:
Thank to #ThomasWeller for an answer. I have a small precision though. What if I need to clean all the elements before the inserted array?
For example I had some garbage
{'a','k','$','-','n','"','4','i','*','%'};
And I need to get
{'-','-','-','-','-','-','-','-','h','i'};
Do I need 2 loops? First to reset an array and the second one to set the actual result?
It can be done with a single for loop and a single variable:
for (char i=0; i<arrLength; i++)
{
outputArray[10-arrLength+i] = inputArray[i];
}
If you make arrLength a char instead of an int, this will even save you 2 bytes of memory ;-)
Use memset() to set all memory to an initial value and then memcpy() the contents at the end:
char output[10];
char input[10] = "hi\0------";
char arrLength = 2;
void setup() {
memset(output, '-', 10); // "----------"
memcpy(output+10-arrLength, input, arrLength);
Serial.begin(9600);
Serial.write(output, 10);
}
void loop() { }

Large Malloc Array data lost after successful assigning it to memory

I am trying to store large amount of data into multiple malloc array
I have three malloc array, two 2d char array and one int array. In a test case the array name are defined as:
cres=12163;
catm=41241;
matm = (char**) malloc(catm*sizeof(char*));
for(i=0;i<catm;i++)
matm[i]=(char*) malloc(5*sizeof(char));
mres = (char**) malloc(cres*sizeof(char*));
for(i=0;i<cres;i++)
mres[i]=(char*) malloc(5*sizeof(char));
mrin = (int*) malloc(cres*sizeof(int));
I read the data from a file. The data stored in these array if printed as it is stored in the these array is in right format. But when I try to retrieve data from the character arrays, after assigning value to the int array the character; array change the column length to 14 and the value is set to 8.50000000E-01.
I am using Linux Opensuse and g++ comiler.
Any Solution or alternate method to store large amount of data.
Sorry for all the confusion the blunder was on my part i was assigning the file-handling line pointer to all the values.
So matm is an array of char* with length catm. You then assign to its elements arrays of char of length 5. Then you do the same for res instead of atm.
Finally, you allocate and store in mrin an array of cres integers.
Almost certainly you are overflowing one of these arrays. You can use valgrind to figure out which, most likely automatically, by simply running valgrind ./a.out or whatever your program is called. It will print stack traces where memory errors occur.
You may simply have strings longer than 4 characters (plus the terminating null). You don't show the code where you populate the arrays.
Since you're using a C++ compiler, you should consider using C++ containers like std::vector<char> and std::string instead of raw C arrays which are error-prone as you have discovered.
OK, so I am going to take a crack at this... in C!
What you are making are arrays of pointers to char.
So two arrays of pointer to char, each holding 41241 pointers to char
One array holding pointers to int ( although why I have no idea since just declaring an array of int of size 12163 would do the trick.
Further you are declaring each entry on the char pointer array to be 5 chars which will hold a C style string of 4 bytes plus the null terminator.
char* strArray1 [41241] ;
char* strArray2 [41241] ;
int* intArray [12163] ;
for( int x=0 ; int < 41241;x++){
strArray1[x] = malloc(5*sizeof(char)) ;
strcopy("fred",strArray1[x]);
}
for( int x=0 ; int < 41241;x++){
strArray2[x] = malloc(5*sizeof(char)) ;
strcopy("Tom",strArray2[x]);
}
for(x=0;x<12163;x++){
inArray[x*] = rand() % 50 ;
}
for( int x=0 ; int < 41241;x++){
printf(" This entry = %s \n",strArray1[x]) ;
}
for( int x=0 ; int < 41241;x++){
printf(" This entry = %s \n",strArray2[x]) ;
}
for( int x=0 ; int < 12163;x++){
printf(" This entry = %i \n",intArray[x*]) ;
}
DO NOT try and get cute with C as it will bite you in the ass every time.

Issue in initializer for char string array

I am an Arduino noob attempting to select a random name from this array:
char ns[ ][3] = {"Carlos Alberto Castronovo","Tom Erbaugh","Caterina De Giacco","Di Puglia Pugliese Filomena","Manishwar Dhillon","Mel Richards","Connie Hvidtfeldt","Amy Namehere","Tim Beck","Sanil Sethi","Christophe Lavault","Steven Grimes","Jessica Serra","Mariateresa Petrucci","Patricia Anderson","Felma Roberto Cinco","Mai Ahmed","Tobe Levy","Indah Suspriati Wibawa","Dain Turgeon Orbe","Li Wang","Ed Clark","Elodie da Silva","Jason Garcia","Allan Litswa","Pietro Zubani","Cyril Jeanpierre","Kate Denali Princess","Maria Pilar Gl","Jefferson Ricarte","Adam Reed","László Lipták","Thalia Dbl","Maria Jose Calle Salas","William Alexander","Nicole Richardson","Andrea Hescher","Ismail Sholeh","Simone Spacci","Jason Jankow"};
But I receive this error, and I am not sure about different data types and how to approach fixing this array:
error: initializer-string for array of chars is too long
Is there something basic that I am missing?
It is exactly what it is informing: your character strings are way too long to fit in your char array, so your compiler is telling you that it will not proceed any further.
You can make it work by enhancing the size of your arrays like this:
char ns[ ][30] = //... ;
The 30 here is just to represent your biggest char string; it needs to have the size of your largest predefined char string + 1 (so that the null terminating character \0 can be added). For example, if your biggest string were "apple", your array would need to be of, at least, length 6.
You can iterate through these strings by doing this, for example:
int array_items = sizeof(ns) / sizeof(*ns); // this will gives you the amount of items stored in your array
int i;
int j;
for (i = 0; i < array_items; ++i) {
size_t strSize = strlen(ns[i]); // strSize now contains, if ns[i] contained the example of apple, 5
for (j = 0; j < strSize; ++j) {
printf("%c", ns[i][j]);
}
printf("\n");
}
That [3] means each string is limited to a maximum of 3 characters. And since one has to be the null terminator, it really means two. Your strings are a lot longer than that. Choose a number that's big enough to accommodate all of them.
ETA: #JLF: are you my long lost brother? :)

Is it possible to pass char[][] to a function requesting char**?

I am trying to call a function that takes char** as a parameter. Its job is to fill an array of strings (i.e. an array of char*). I know the max length of the strings, and I can pass the max number to fill as another parameter, so I was hoping to stack allocate it like this:
fill_my_strings(char** arr_str, int max_str); // function prototype
char fill_these[max_strings][max_chars_per_string]; // allocating chars
fill_my_strings(fill_these, max_strings); // please fill them!
Of course, I get the "cannot convert char[max_strings][max_chars_per_string] to char**" error.
I know this is some subtle (or not-so-subtle) problem with my understanding of the difference between arrays and pointers. I'm just not sure why it's not possible to pass this block of memory to something wanting a char** and have it fill in my stack-allocated chars. Could somebody please explain if this is possible, or if not, why not?
Is it possible to call a function like this without calling malloc / new?
The simple answer to your question is no; a two dimensional array is different than a pointer-to pointer type. Arrays decay to pointers to their first element, but pointers actually are that value.
The difference between these types is clear, if you cast both to char*
int x;
char *arr_pp[] = {"foo", "bar", "baz"};
char arr_2d[][4] = {"foo", "bar", "baz"};
char *cp = (char*)arr_pp;
for(x=0; x<3; x++)
printf("%d ", cp[x]);
printf("\n");
cp = (char*)arr_2d;
for(x=0; x<3; x++)
printf("%d ", cp[x]);
printf("\n");
The output (on my computer) is:
-80 -123 4
102 111 111
Where the first row is gibberish formed by the fact that I'm printing an address cast into bytes, and the second row is the ascii values of "foo".
In a function taking a char ** the compiler can't know to decay array types, which don't actually contain pointers.
Suppose you have n pointers to strings of m-1 maximum characters (m characters including the NULL).
So, in pure C:
sizeof(char[n][m]) will return n*m.
sizeof(char**) will return the size of a pointer in your architecture, probably 32 (if x86) or 64 (if x86_64).
char[n][m] actually allocates the n*m byte contiguously. char** allocates a single pointer. This pointer references a memory stripe of *n bytes. Each of these n pointers points to a memory stripe of m characters.
So, considering that sizeof(char) == u, if you declare char a[n][m], when you use a[i][j], the compiler understands *(a + i*m*u + j*u).
So, considering that sizeof(char *) == w, if you declare char **a, when you use a[i][j], the compiler understands ((a + i*w) + j*w).
Completely different data management.
The closes thing you could do to handle your special case is to create a char** variable, and populate it with the addresses of your stack allocated matrix.
char **tmp = malloc(max_strings * sizeof(char *));
int i;
for(i = 0; i < max_strings; i++){
tmp[i] = &(fill_these[i][0]); //you probably can't reference a char[][] with a single index - not confirmed
}
I am not sure why fill_my_strings() need a char** parameter. From your example, caller have already allocated the memory from stack. So using a char* should be OK.
But if you want to use char** or you can't modify the fill_my_strings() function, try following example code:
void fill_my_strings(char** arr_str, int max_chars_per_string, int max_strings)
{
for(int i = 0; i < max_strings; ++i)
{
//Make sure you have enough space
memcpy(*arr_str, "ABCD", sizeof("ABCD"));
*arr_str += max_chars_per_string;
}
}
char fill_these[max_strings][max_chars_per_string];
char* pointer = (char*)fill_these;
fill_my_strings(&pointer, max_strings, max_chars_per_string);
The obvious thing to do is build an index
In c use something like:
char string_list[num_strings][str_length];
// ...
char**index = calloc( (num_strings+1), sizeof(*index) ); // calloc insures NULL termination
for (int i=0; i<num_strings; ++i) {
index[i] = string_list[i]
}
In c++ prefer new[] to calloc;

Working with Arrays in C

I am new to C and C++ and I need help with arrays. I have an array initialized to zero with 500 elements(myDataBinary). Now I have one more array ith values in it say 1,2,3....Now by reading the values (1,2,3...) from(my_data[10]) i want to make the corresponding elements in myDataBinary "1" and rest should be "0". I have written the below code to achieve this, but I am getting some segmentation fault and not able to see the proper results. Any help on this would be appreciated. Thanks in advance
int my_data[10] = {1,3,9,10};
int myDataBinary[500] = {0};
int index;
for(int i=0; i<sizeof(my_data);i++)
{
index = my_data[i];
myDataBinary[index] = 1;
printf("rec data %d = %d\n",index,myDataBinary[index]);
}
sizeof(my_data) returns the total size of the array in bytes, not the number of elements.
Since ints are (usually) 2 bytes wide, you're ending up outside the array.
Replace sizeof(my_data) in the for loop with sizeof(my_data)/sizeof(int) and try again.
sizeof operator gives the size of an object (or type) in bytes. The canonical way to determine the number of elements in an array x is:
sizeof x / sizeof x[0]
This does not depend upon knowing the type of the elements of x, and will work even if you change it. sizeof my_data / sizeof(int) doesn't have that property.
Note that my_data has to be an array, it cannot be a pointer. This is important because in many contexts (when passed to a function for example), the name of an array decays to a pointer, so the following "won't work":
void f(int *data)
{
printf("%zu\n", sizeof data);
}
int main(void)
{
int my_data[10] = {1,3,9,10};
printf("%zu\n", sizeof my_data);
f(my_data);
return 0;
}
The above program will print two different values (unless sizeof(int)*10 == sizeof(int *)).
Don't use sizeof(my_data) - this doesn't give you what you want. To find the number of the elements you can do int n = sizeof(my_data) / sizeof(int):
int my_data[10] = {1,3,9,10};
int myDataBinary[500] = {0};
int index;
int n = sizeof(my_data) / sizeof(int);
for(int i=0; i<n;i++)
{
index = my_data[i];
myDataBinary[index] = 1;
printf("rec data %d = %d\n",index,myDataBinary[index]);
}