Variable size array in C++ - 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.

Related

Run-Time Check Failure #2 - Stack around the variable 'newRow' was corrupted

I've still getting an error of how the stack around newRow is tried using strncat() so that I can say how many new charters that where added to the string, but in the end I still have a corruption around newRow.
In terms of a variables being passed into this function, I think they are pretty straight forward. I also use sizeOfString as a custom made function because I'm not allowed to use the standard sizeof function.
char* makeRow(char elementOne[20], int elementNumber, int numCycles, int orginalData[40], float ctValues[7]){
char newRow[] = "";
int lookingAt;
int dataPoint;
char* elementPtr;
int charArrSize;
elementNumber = elementNumber--;
elementPtr = elementOne;
int lenOfElemnt = *(&elementOne + 1) - elementOne;
//charArrSize = sizeOfString(elementPtr);
charArrSize = sizeOfString(elementOne);
strncat(newRow, elementOne, charArrSize);
//strcpy(csvThirdRow, (",%s", elementOne));
for (int i = 1; i <= 5; i++)
{
lookingAt = (((i - 1) * 5) + 1 - 1);
int maxLookingAt = numCycles * 5;
dataPoint = orginalData[lookingAt];
char dataPointBuffer[100];
if (lookingAt < maxLookingAt)
{
sprintf(dataPointBuffer, ",%d", dataPoint);
charArrSize = sizeOfString(dataPointBuffer);
strncat(newRow, dataPointBuffer, charArrSize);
}
else
{
strncat(newRow, ",",1);
}
}
char ctBuffer[20];
float ctNumber = ctValues[elementNumber];
sprintf(ctBuffer, ",%.2f\n", ctNumber);
charArrSize = sizeOfString(ctBuffer);
strncat(newRow, ctBuffer, charArrSize);
return newRow;
}
If we omit the array dimension, compiler computes it for us based on the size of initialiser.
So, this
char newRow[] = "";
is same as this
char newRow[1] = "";
The size of newRow array is 1.
You are trying to copy more than 1 character to newRow array which is leading to undefined behaviour and resulting in corruption.
From strncat():
The behavior is undefined if the destination array does not have enough space for the contents of both dest and the first count characters of src, plus the terminating null character....
May you should try giving enough size to newRow array, like this
char newRow[1024] = {0};
There is another problem in your code -
You are returning the address of local variable newRow1) from makeRow() function. Note that a local(automatic) non-static variable lifetime is limited to its scope i.e. the block in which it has been declared. Any attempt to access it outside of its lifetime lead to undefined behaviour.
Couple of things that you can do to fix it:
Either make numRow array static or declare numRow as char * type and allocate memory dynamically to it and, in this case, make sure to free it once done with it.
1). An expression that has type array of type is converted to an expression with type pointer to type that points to the initial element of the array object [there are few exceptions to this rule].

Incompatible types in assignment of variables in C++

recently I have been trying to make a Neural Network with an arduino library and I came across a library, that was quite literally, called Neural Network by George Chousos. I stumbled apon a couple of errors that I managed to fix quite simply, but then I got caught on the error of
sketch_sep22b:24:43: error: incompatible types in assignment of 'float*' to 'float [4]' outputs = NN.FeedForward(inputs[i]);
This is all of my code:
#include <math.h> // Include Math Library
#include <NeuralNetwork.h> // Include Neural Network Framework
const unsigned int layers[] = {4, 9, 4}; // First Value (Inputs), Second Value (Neurons / Hidden Layers), Third Value (Outputs)
float outputs[4] = {}; //Outputs Float
const float* /* Pointer */ inputs[1] = {1};
const float expectedOutputs[1] = {1}; //Training Values
void setup()
{
Serial.begin(9600);
NeuralNetwork NN(layers, NumberOf(layers));
for (int i = 0; i < 3000; i++)
{
for (int j = 0; j < NumberOf(inputs); j++)
{
for (int i = 0; i < NumberOf(inputs) - 1; i++)
{
outputs = NN.FeedForward(inputs[i]);
Serial.println(outputs[0], 7);
}
NN.print();
}
}
}
Edit:
The declaration for FeedForward is:
float *FeedForward(const float *inputs); // Moves Calculated outputs as inputs to next layer.
Okay, I looked at the link and the declaration. The first problem, and the one that's leading to the compiler error is the return type. The declaration is expecting output to be a pointer, not an array. So, changing the declaration of output to:
float* outputs; //Outputs Float
should fix the compiler error. I haven't tried it, but that looks to be the issue the compiler is catching. This will likely return a pointer to an array of 4 floats which you will need to deallocate later (using either free or delete[] depending on how the library allocated the memory) once you're done with it or it will create a memory leak.
As others have noted, your current declaration of input is attempting to access a fixed memory location (1) which leads to undefined behavior, so, you still need to address this as well. Since the library appears to be expecting an input with 4 float values, you should either give it an array with 4 float values declared at compile time, or you could dynamically allocate an array with 4 values at run time.
The first option looks like this:
const float inputs[4] = {1.0, 2.0, 3.0, 4.0};
The second option looks like:
float* input;
...
input = new float[4];
input[0] = 1.0;
input[1] = 2.0;
input[2] = 3.0;
input[3] = 4.0;
...
output = NN.FeedForward(input);
...
delete[] input;

How can I use a search function on a dynamic array?

I'm trying to use a linear search function on a dynamic array I created but then the teaching assistant for my computer science class told us that most search functions use const arrays.
Is there any way I can edit my dynamic array to become contant? Or is it also possible to make a search function that uses a dynamic array (and would not give errors?).
I'll give a brief insight into my code:
I dynamically create an array using the rows I read in from a file and then dynamically allocate each row to an array of columns.
char ** domain[] = new char * [rows];
for(int i = 0; i < rows; i++)
{
*domain = new char[columns];
domain++;
}
The type of function that we were taught for searching is:``
char searchArray( const char list[], char letter, int maxSize)
{
>code goes here
}
Is there any other method of using a search function that takes in dynamic multidimensional arrays?
In response to the comments, I can't use vectors. This is an assignment for us to use normal arrays. I haven't been taught how to to use vectors yet.
In the line
char ** domain[] = new char * [rows];
char ** domain[] tries to make an array of char **. If the compiler didn't complain about not having a valid array size in the [] and you would have a 3D structure. You want just plain old char ** for a 2D structure, so
char ** domain = new char * [rows];
The loop filling out the inner dimension is correct except it loses track of the starting point of domain
for(int i = 0; i < rows; i++)
{
*domain = new char[columns];
domain++;
}
Should be something like
char ** temp = domain;
for(int i = 0; i < rows; i++)
{
*temp = new char[columns];
temp++;
}
To preserve the starting point, but for this case array notation is probably the smarter and easier-to-read option.
for(int i = 0; i < rows; i++)
{
domain[i] = new char[columns];
}
On to searchArray. It needs to know it's getting two dimensions, (const char **) and that there are two max sizes (maxRow and maxColumn). It will look something like
char searchArray(const char ** list,
char letter,
int maxRow,
int maxColumn)
{
>code goes here
}
Code goes here is your problem, but will probably be two nested for loops iterating to maxRow and maxColumn and returning when letter is found.
But... Why return a char? Returning the location in the array is much more useful. We could use std::pair, but if std::vector is off limits, pair probably is as well. Consider something like the following instead:
struct coord
{
int row;
int column;
};
coord searchArray(const char ** list,
char letter,
int maxRow,
int maxColumn)
{
coord location;
>code goes here
return location;
}
If the item is not found, set row and column to something impossible to get like -1 so you can easily test for the not found case.
Stop here unless you want to <expletive deleted> with your teacher's brain.
The above doesn't build a 2D array. You can't get a dynamically allocated 2D array in C++. What you have is an array of arrays. There are a couple downsides to this, look at all the work that goes into stitching one together and computers love it when things go in straight lines. Array of arrays doesn't. Every different allocation can be somewhere completely different in memory forcing the program to hop around, waiting on and loading different chunks of memory. Sometimes The program will spend more time sitting around waiting for stuff to be found and loaded than it'll spend doing the actual work. This sucks.
The solution is to make a 1D array and make it look like a 2D array. Here's an example of that from the C++ FAQ
You'll learn a lot of neat stuff from following this example, not the least of which being RAII and the Rule of Three, two concepts without which you cannot write non-trivial high quality C++ code.

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.

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]);
}