Working with Arrays in C - 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]);
}

Related

Variable size array in C++

This is interesting. I want to make a 2D array where one of the dimensions is a variable. Here is my code:
int main(void) {
const int rows = numlines("health.txt");
float data[rows][5] = {0};
readIntoArray(data, 5, rows, "health.txt");
return 0;
}
Line 3 "rows" is underlined with an error. It says: "Expression must have a constant value." Apparently it works for other people to use const in these situations. But mine might work differently because my variable is defined by a function. Here is that function:
int numlines(string filename) {
int number_of_lines = 0;
ifstream fin(filename);
string line;
while (getline(fin, line)) {
++number_of_lines;
}
return number_of_lines;
}
I have tried following other suggestions and making my code follow this format:
(Replace lines 2 & 3 of the first code block with this.)
int rows = numlines("health.txt");
float **data;
data = new float*[rows]; //The height is defined by the function
for (int i = 0; i < rows; i++) {
data[i] = new float[5]; //The width is 5
}
But then that causes an error on "data" in line 4 of the first codeblock. The error is Argument of type "float**" is incompatible with parameter of type "float (*)[5]". Here is the first line of the relevant function:
void readIntoArray(float data[][MAXCOLUMNS], int arrayX, int arrayY, string filename)
MAXCOLUMNS is #defined as 5.
How do I pass the 2D array into the function without creating an error?
I am not the most experienced in c++, so I might be missing something obvious.
There is a difference between:
const int rows = numlines("health.txt");
and
const int rows = 20;
In both cases the value of the variable cannot modified once it is initialzed. The difference is that in the first case, the value won't be known until run time while in the second case, the value is known at compile time.
In C++, an array can be declared using a variable only if its value is known at compile time.
That explains why you cannot use:
const int rows = numlines("health.txt");
float data[rows][5] = {0};
but you can use:
const int rows = 20;
float data[rows][5] = {0};
You can easily get around that issue by using an std::vector of std::vectors.
const int rows = numlines("health.txt");
std::vector<std::vector<float>> data(rows, std::vector<float>(5));
Since you know the size of the inner array, you can also you std::array. It will make the declaration a little simpler.
std::vector<std::array<float, 5>> data(rows);
In C++,you can use "std::vector< T >" to save your data as a variable size array.
Just learn how to use STL,it would simplify your works.
You can use alloca to implement the equivalent of a variable length array:
float (*data)[5] = (float (*)[5]) _alloca(rows * 5 * sizeof(float));
This will allocate local (stack) space and set data to point to the first row (with 5 columns) of a matrix of floats. The 5 can be replaced with a constant. You can then use data like a normal local matrix, data[ i ][ j ] ... . Depending on the compiler, the name may be alloca() instead of _alloca(), and the cast (float (*)[5]) may not be needed.
Since this is a local allocation, it's automatically freed when the function exits.

Is it possible to make an array of arrays?

I am writing a program to simulate a cache in c++ and am trying to copy addresses that are given in a file into an array. I am struggling to figure out how to copy an array into another array so that I can have an array of memory address arrays. I have read in the addresses into an array called "address" and I want my simulated cache to be an array called "L1_Cache". h is a counter that I am incrementing after I put an address into the L1_Cache. Also, cache size is going to be how many lines of addresses are available in my L1_Cache array, which will be decided by the user of the program. Below is the snippet where I am trying to put the array into the other array.
if(sizeof(L1_Cache) < cachesize)
strcpy(L1_Cache[][h], address);
they are defined as:
const char* address[10];
char* L1_Cache;
If anyone has any suggestions on how to copy one array into another array to make an array of arrays, let me know. I am not sure if anything I am doing is correct, but I am struggling to figure this out.
I want to compare new addresses that I am given to old addresses that are already in the L1_Cache array.
Yes, it is possible to make an array of arrays.
int a[3][3]; // a is an array of integer arrays
You have
a[0]; // this refers to the first integer array
a[1]; // this refers to the second array
Is the following what you are looking for?
#include <iostream>
#include <cstring>
int main()
{
char p[2][256];
strncpy(p[0], "This is my first address", 256);
strncpy(p[1], "This is my second address", 256);
std::cout << p[0] << std::endl << p[1];
return 0;
}
Yes. They are called multidimensional arrays.
They can have any number of dimensions.
For example:
int foo[3][3]; // initialize the 2 dimensional array of integers
foo[0][0] = 1; // change a value
foo[0][1] = 2; // change a value
foo[0][2] = 3; // change a value
foo[1][0] = 4; // change a value
foo[1][1] = 5; // change a value
foo[1][2] = 6; // change a value
foo[2][0] = 7; // change a value
foo[2][1] = 8; // change a value
foo[2][2] = 9; // change a value
for(int i=0;i<3;++i){ // display the 2d array
for(int j=0;j<3;++j){
cout<<foo[i][j];
}
cout<<endl;
}
What's happening:
Values are being assigned in a chart.
Think of it like writing a value on each point of a piece of paper.

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;

Large out-of-range numbers appear in C++ rand()

Need to have an array full of random numbers within range. Code:
void fillArray(int *arr){
for(int i=0;i<(sizeof arr);i++){
arr[i] = rand() % 2 - 2;
}
}
int *arrPoint(int *arr, int max){
for (int i=0;i<max;i++){
printf("%d is %d\n",i,arr[i]);
}
return arr;
}
int main(int argc, char *argv[]){
srand ( time(NULL) );
int arr_f[15];
fillArray(arr_s);
arrPoint(arr_s, 15);
system("PAUSE");
return EXIT_SUCCESS;
}
Output:
0 is -2
1 is -1
2 is -2
3 is -1
4 is 0
5 is 0
6 is 4633240
7 is 2686652
8 is 1973724226
9 is 1974338216
10 is 2686716
11 is 1973744850
12 is 8
13 is 1973752206
14 is 1973752162
Press any key to continue . . .
What the hell? Putting rand() % 2 into brackets doesn't help either. What these numbers are and how do I get rid of them?
P.S. Tried this in crappy Dev-C++ and Code::Blocks with the same result. Need the program to be small sized (putting it to dropbox), so no, I can't use 100mb boost lib.
void fillArray(int *arr){
for(int i=0;i<(sizeof arr);i++){
Since arr is a pointer to an integer, sizeof arr is equivalent to sizeof (int *), which is apparently 4 (32-bits) on your platform. That's clearly not what you want. You only pass fillArray a pointer to the first element of the array.
If you need the number of elements in the array a pointer points to, you need to pass that information. The C and C++ languages provides no way to tell how many bytes a pointer points to given just the pointer.
You do it correctly in arrPoint. Do it that way in fillArray.
Arrays don't work like you think. You cannot use sizeof to get the array size magically. Arrays decay to pointers to their first element when passed as a function argument, and you must provide the size information separately:
int main()
{
int * arr = new int[20];
the_function(arr, 20);
//...
delete[] arr;
}
void (int * arr, std::size_t size)
{
for (std::size_t i = 0; i != size; ++i)
{
// something with arr[i]
}
}
Much better yet, use std::vector<int> to spare yourself all this headache, and tons of further headache that you may not even have thought about.
(There is an exception to my statement: For an automatic array in the local scope, int b[10], sizeof(b) will indeed return 10 * sizeof(int). But that is only because the compiler knows the array size. The size information is not passed around, and it is not available at runtime.)
In fillArray (sizeof arr) is the size of a pointer, not the size of your array.
Your problem is the sizeof operator. arr is a pointer to an int, which is usually 4 or 8 bytes long. You must pass the length of the array (not the size in bytes) as an additional parameter to the function.
Try using _countof(arr) instead of sizeof(arr)._countof returns size of array, not pointers-be aware of this.

Using pointer for crossing over all elements in INTEGER array

Is there a way to cross over all elements in integer array using pointer ( similiar to using pointer to cross over string elements).I know that integer array is not NULL terminated so when I try to cross over array using pointer it overflows.So I added NULL as a last element of an array and it worked just fine.
int array[7]={1,12,41,45,58,68,NULL};
int *i;
for(i=array;*i;i++)
printf("%d ",*i);
But what if one of the elements in array is 0 ,that will behave just as NULL.Is there any other way that will implement pointer in crossing over all elements in integer array?
In general, no unless you pick a sentinel value that's not part of the valid range of the data. For example, the valid range might be positive numbers, so you can use a negative number like -1 as a sentinel value that indicates the end of the array. This how C-style strings work; the NULL terminator is used because it's outside of the valid range of integers that could represent a character.
However, it's usually better to somehow pair up the array pointer with another variable that indicates the size of the array, or another pointer that points one-past-the-end of the array.
In your specific case, you can do something like this:
// Note that you don't have to specify the length of the array.
int array[] = {1,12,41,45,58,68};
// Let the compiler count the number of elements for us.
int arraySize = sizeof(array)/sizeof(int);
// or int arraySize = sizeof(array)/sizeof(array[0]);
int main()
{
int* i;
for(i = array; i != array + arraySize; i++)
printf("%d ",*i);
}
You can also do this:
int arrayBegin[] = {1,12,41,45,58,68};
int* arrayEnd = arrayBegin + sizeof(arrayBegin)/sizeof(arrayBegin[0]);
int main()
{
int* i;
for(i = arrayBegin; i != arrayEnd; i++)
printf("%d ",*i);
}
But given only a pointer, no you can't know how long the array it points to is. In fact, you can't even tell if the pointer points to an array or a single object! (At least not portably.)
If you have functions that must accept an array, either have your function require:
the pointer and the size of the array pointed by the pointer,
or two pointers with one pointing to the first element of the array and one pointing one-past-the-end of the array.
I'd like to give some additional advice: Never use some kind of sentinel/termination value in arrays for determining their bounds. This makes your programs prone to error and is often the cause for security issues. You should always store the length of arrays to limit all operations to their bounds and test against that value.
In C++ you have the STL and its containers.
In C you'll effectively end up using structures like
typedef struct t_int_array
{
size_t length;
int data[1]; /* note the 1 (one) */
} int_array;
and a set of manipulation functions like this
int_array * new_int_array(size_t length)
{
int_array * array;
/* we're allocating the size of basic t_int_array
(which already contains space for one int)
and additional space for length-1 ints */
array = malloc( sizeof(t_int_array) + sizeof(int) * (length - 1) );
if(!array)
return 0;
array->length = length;
return array;
}
int_array * concat_int_arrays(int_array const * const A, int_array const * const B);
int_array * int_array_push_back(int_array const * const A, int const value);
/* and so on */
This method will make the compiler align the t_int_array struct in a way, that it's optimal for the targeted architecture (also with malloc allocation), and just allocating more space in quantities of element sizes of the data array element will keep it that way.
The reason that you can iterate across a C-style string using pointers is that of the 256 different character values, one has been specifically reserved to be interpreted as "this is the end of the string." Because of this, C-style strings can't store null characters anywhere in them.
When you're trying to use a similar trick for integer arrays, you're noticing the same problem. If you want to be able to stop at some point, you'll have to pick some integer and reserve it to mean "this is not an integer; it's really the end of the sequence of integers." So no, there is no general way to take an array of integers and demarcate the end by a special value unless you're willing to pick some value that can't normally appear in the string.
C++ opted for a different approach than C to delineate sequences. Instead of storing the elements with some sort of null terminator, C++-style ranges (like you'd find in a vector, string, or list) store two iterators, begin() and end(), that indicate the first element and first element past the end. You can iterate over these ranges by writing
for (iterator itr = begin; itr != end; ++itr)
/* ... visit *itr here ... */
This approach is much more flexible than the C-string approach to defining ranges as it doesn't rely on specific properties of any values in the range. I would suggest opting to use something like this if you want to iterate over a range of integer values. It's more explicit about the bounds of the range and doesn't run into weird issues where certain values can't be stored in the range.
Apart from the usual suggestion that you should go and use the STL, you can find the length of a fixed array like this:
int array[6]={1,12,41,45,58,68};
for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
{ }
If you use a templated function, you can implicitly derive the length like this:
template<size_t len> void func(int (&array)[len])
{
for (int i = 0; i < len; ++i) { }
}
int array[6]={1,12,41,45,58,68};
func(array);
If 0 is a value that may occur in a normal array of integers, you can specify a different value:
const int END_OF_ARRAY = 0x80000000;
int array[8]={0,1,12,41,45,58,68,END_OF_ARRAY};
for (int i = 0; array[i] != END_OF_ARRAY; ++i)
{ }
If every value is a possibility, or if none of the other approaches will work (for example, a dynamic array) then you have to manage the length separately. This is how strings that allow embedded null characters work (such as BSTR).
In your example you are using (or rather abusing) the NULL macro as a sentinel value; this is the function of the NUL('\0') character in a C string, but in the case of a C string NUL is not a valid character anywhere other than as the terminal (or sentinel) value .
The NULL macro is intended to represent an invalid pointer not an integer value (although in C++ when implicitly or explicitly cast to an int, its value is guaranteed to be zero, and in C this is also almost invariably the case). In this case if you want to use zero as the sentinel value you should use a literal zero not NULL. The problem is of course that if in this application zero is a valid data value it is not suitable for use as a sentinel.
So for example the following might suit:
static const int SENTINEL_VALUE = -1 ;
int array[7] = { 1, 12, 41, 45, 58, 68, SENTINEL_VALUE } ;
int* i ;
for( i = array; *i != SENTINEL_VALUE; i++ )
{
printf( "%d ", *i ) ;
}
If all integer values are are valid data values then you will not be able to use a sentinel value at all, and will have to use either a container class (which knows its length) or iterate for the known length of the array (from sizeof()).
Just to pedanticize and expand a little on a previous answer: in dealing with integer arrays in C, it's vanishingly rare to rely on a sentinel value in the array itself. No(1) sane programmer does that. Why not? Because by definition an integer can hold any value within predefined negative/positive limits, or (for the nowadays-not-unusual 32-bit integer) 0 to 0xffffff. It's not a good thing to redefine the notion of "integer" by stealing one of its possible values for a sentinel.
Instead, one always(1) must(1) rely on a controlling up-to-date count of integers that are in the array. Suppose we are to write a C function
that returns an int pointer to the first array member whose value is greater than the function's argument or, if there's no such member, returns NULL (all code is untested):`
int my_int_array[10]; // maximum of 10 integers in my_int_array[], which must be static
int member_count = 0; // varies from 0 to 10, always holds number of ints in my_int_array[]
int *
first_greater_than ( int val ) {
int i;
int *p;
for ( i = 0, p = my_int_array; i < member_count; ++i, ++p ) {
if ( *p > val ) {
return p;
}
}
return NULL;
}
Even better is also to limit the value of i to never count past the last possible member of my_int_array[], i.e., it never gets bigger than 9, and p never points at my_int_array[10] and beyond:
int my_int_array[10]; // maximum of 10 integers in my_int_array[], which must be static
int member_count = 0; // varies from 0 to 10, always holds number of ints in my_int_array[]
int *
first_greater_than ( int val ) {
#define MAX_COUNT sizeof(my_int_array)/sizeof(int)
int i;
int* p;
for ( i = 0, p = my_int_array; i < member_count && i < MAX_COUNT; ++i, ++p ) {
if ( *p > val ) {
return p;
}
}
return NULL;
}
HTH and I apologize if this is just too, too elementary.
--pete
Not strictly true but believe it for now
In ANSI C it's very easy and shorter than solution before:
int array[]={1,12,41,45,58,68}, *i=array;
size_t numelems = sizeof array/sizeof*array;
while( numelems-- )
printf("%d ",*i++);
Another way is to manage array of pointers to int:
#include <stdlib.h>
#include <stdio.h>
#define MAX_ELEMENTS 10
int main() {
int * array[MAX_ELEMENTS];
int ** i;
int k;
// initialize MAX_ELEMENTS,1 matrix
for (k=0;k<MAX_ELEMENTS;k++) {
array[k] = malloc(sizeof(int*));
// last element of array will be NULL pointer
if (k==MAX_ELEMENTS-1)
array[k] = NULL;
else
array[k][0] = k;
}
// now loop until you get NULL pointer
for (i=array;*i;i++) {
printf("value %i\n",**i);
}
// free memory
for (k=0;k<MAX_ELEMENTS;k++) {
free(array[k]);
}
return 0;
}
In this way loop condition is totally independent from the values of integers. But... for this to work you must use 2D array (matrix) instead of ordinary 1D array. Hope that helps.