Error using dynamic 2D array - c++

so recently I have been working on a truth table generator which generates an equation for a logic statement. So, I decided to use a 2D array to make things seem more clean and neat. However, as I run this code(Don't worry, int main and other functions exist too, I am posting only this part since it is the one that causes an error):
int calculate(size_t length) {
int dimensionX = length + 2;
int dimensionY = 5;
calcArray = new string *[dimensionX];
for (int i = 0; i < dimensionX; i++) {
calcArray[i] = new string[dimensionY];
}
for (int i = 0; i < dimensionX; i++) {
delete[] calcArray[i];
delete[] calcArray;
}
return 0;
}
int count(string phrase, string calcArray[][]) {
string statement(phrase);
size_t ve = count(statement.begin(), statement.end(), 'A');
size_t yada = count(statement.begin(), statement.end(), 'V');
size_t ozel_yada = count(statement.begin(), statement.end(), 'XV');
size_t ok = count(statement.begin(), statement.end(), '->');
size_t cift_ok = count(statement.begin(), statement.end(), '<->');
size_t complete = ve + yada + ozel_yada + ok + cift_ok;
size_t column_number = complete;
return complete;
for (int i = 3; i < complete; i++) {
int andNum = phrase.find('A');
if (count (phrase.substr(andNum-3,6).begin(), phrase.substr(andNum - 3, 6).end(),'(') == 0){
string calcArray[0][i] = phrase.substr(andNum - 1, 4);
}
}
}
I get errors saying that:
An array may not have elements of this type( int count(string phrase, string calcArray[][])
cannot allocate an array of constant size 0 (string calcArray[0][i] = phrase.substr(andNum - 1, 4);)
An expression did not evaluate a constant (string calcArray[0][i] = phrase.substr(andNum - 1, 4);)
I would appreciate any help or explanation. Thanks

string calcArray[][]
is not a valid declaration for a function parameter. When you use a multi-dimensional array, all dimensions except the first one must be specified. E.g.
string calcArray[][10]
string anotherArray[][10][2]
If the arrays are dynamic, you can use std::vector<std::vector<std::string>>.
std::vector<std::vector<std::string>>& calcArray

Related

C++ Big Int Class - How to make an Add Function that will add both objects together and return a new one

so I'm trying to make a big int class for an assignment and include an addition function but i am having trouble with it.
So in the class we are storing two variables, an array and its size:
class HugeInteger {
private:
//pointer array to store every digit of the large number
int* digits;
//stores the lenght of the array
int length;
I need to make an add function that will take another object that we are given by input and add it with the current object and return it as a new object using our string constructor.
HugeInteger HugeInteger::add(const HugeInteger& h) {
int carry = 0;
int maxSize = length;
std::string final = "";
if (h.length > length) {
maxSize = h.length;
}
int* result = new int[maxSize];
for (int i = 0; i < maxSize; i++) {
int a = (i < length) ? digits[i] : 0;
int b = (i < h.length) ? h.digits[i] : 0;
result[i] = (a + b + carry) % 10;
carry = (a + b + carry) / 10;
}
if (carry > 0) {
maxSize++;
int* temp = new int[sizeof(result)+1];
for (int i = 0; i < sizeof(result); i++) {
temp[i] = result[i];
}
temp[sizeof(result)] = carry;
result = temp;
}
for (int i = 0; i < maxSize; i++) {
final.push_back(result[i] + '0');
}
This is what i have so far but it does not work at all if the objects have arrays of different size or even with carries. I don't know what Im doing wrong.
At the end im converting the array to a string since the only constructor we are allowed to implement is one that converts strings into the object.
Any hint or help is appreciated. I don't really get how I'm supposed to fix this when Im adding numbers one by one so for example:
363+
10
Is resulting in 463 currently which makes no sense. I tried going from right to left in the array like when adding numbers in real life but I dont know how to handle going out of limit of the smaller array.

c++ Split char array without use of any library

I've been running into this weird issue where the split code returns correctly when I printf output inside the function, but will incorrectly return output upon calling it as an instance.
Question: How do I get the correct ouput when calling it as an instance?(see useage bellow)
Here is the code:
typedef struct SplitText
{
int splitLen;
char* splitTxt[100];
char* subTxt(char* text, int index, int len)
{
char subTxt_[1000];
int count = 0;
for (int i = 0; i < 1000; i++)
subTxt_[i] = '\0';
for (int i = index; i < index + len; i++)
subTxt_[count++] = text[i];
return subTxt_;
}
void split(char* text, char sep)
{
char separator[3] = { '<', sep, '>' };
int textLen = strlen(text);
int splitIndex = 0;
int splitCount = 0;
for (int t = 0; t < textLen; t++)
{
if (text[t] == separator[0] && text[t + 1] == separator[1] && text[t + 2] == separator[2])
{
if (splitIndex != 0)
splitIndex += 3;
splitTxt[splitCount] = subTxt(text, splitIndex, t - splitIndex);
splitIndex = t;
//correct output
printf(splitTxt[splitCount]);
printf("\n");
splitCount++;
}
}
splitLen = splitCount;
}
}SplitText;
Useage:
SplitText st;
st.split("testing<=>split<=>function<=>", '=');
for (int i = 0; i < st.splitLen; i++)
{
//incorrect output
printf(st.splitTxt[i]);
printf("\n");
}
printf("--------\n");
This:
char* subTxt(char* text, int index, int len)
{
char subTxt_[1000];
...
return subTxt_;
}
Is undefined behavior. Returning a pointer to a local stack variable (or local array var) is going to result in weird stuff like this happening.
The typical thing that corrupts the contens of that returned pointer is when another function is invoked, the memory occupied by subTxt_ is going to get overwritten with the stack variables of the next function invoked.
Better:
char* subTxt(char* text, int index, int len)
{
char *subTxt = new char[1000];
...
return subTxt_;
}
And then make sure whoever invokes subTxt remembers to delete [] on the returned pointer.
Or just use std::string and be done with it (unless this is an academic exercise).
Also, this is undefined behavior:
for (int t = 0; t < textLen; t++)
{
if (text[t] == separator[0] && text[t + 1] == separator[1] && text[t + 2] == separator[2])
when t == textLen-1, then referencing text[t+2] and text[t+1] is an out of bounds access. Change it to be:
for (int t = 2; t < textLen; t++)
{
if (text[t-2] == separator[0] && text[t -1] == separator[1] && text[t] == separator[2])
And do similar fixups with t within the block as well.
Well you can create a splitstring function instead of a struct/class.
Anyway your code still looks quite "C" like with its fixed size char arrays. This will limit the usability and stability (out-of-bound array bugs).
Strings in C++ are usually of type std::string.
and then C++ has string_view to make views on that string (so no data gets copied, but it also means your string_view is only valid for as long as the string it is viewing lives).
If you don't know the number of substrings in a string up-front, you should not use a fixed size array, but a std::vector (which can resize internally if needed)
This is what a split_string function would look like in current C++, note that the code also shows better what it is doing compared to "C" style programming that show more what you are doing.
std::vector<std::string_view> split_string(std::string_view string, std::string_view delimiters)
{
std::vector<std::string_view> substrings;
if(delimiters.size() == 0ul)
{
substrings.emplace_back(string);
return substrings;
}
auto start_pos = string.find_first_not_of(delimiters);
auto end_pos = start_pos;
auto max_length = string.length();
while(start_pos < max_length)
{
end_pos = std::min(max_length, string.find_first_of(delimiters, start_pos));
if(end_pos != start_pos)
{
substrings.emplace_back(&string[start_pos], end_pos - start_pos);
start_pos = string.find_first_not_of(delimiters, end_pos);
}
}
return substrings;
}
Take a look at std::string_view.
You can avoid allocating memory and it has a built-in substring function.
Just be careful when using printf for printing to console as "%s" will
print the whole string.
See printf documentation.
for(auto view : container_with_string_views)
printf("%.*s, (int)view.size(), view.data());

Error: Initialization with '{...}' expected for aggregate object

below is my code which processes the payload[] array and store it's result on myFinalShellcode[] array.
#include <windows.h>
#include <stdio.h>
unsigned char payload[] = { 0xf0,0xe8,0xc8,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,0x56,0x48,0x31 };
constexpr int length = 891;
constexpr int number_of_chunks = 5;
constexpr int chunk_size = length / number_of_chunks;
constexpr int remaining_bytes = length % number_of_chunks;
constexpr int size_after = length * 2;
unsigned char* restore_original(unsigned char* high_ent_payload)
{
constexpr int payload_size = (size_after + 1) / 2;
unsigned char low_entropy_payload_holder[size_after] = { 0 };
memcpy_s(low_entropy_payload_holder, sizeof low_entropy_payload_holder, high_ent_payload, size_after);
unsigned char restored_payload[payload_size] = { 0 };
int offset_payload_after = 0;
int offset_payload = 0;
for (size_t i = 0; i < number_of_chunks; i++)
{
for (size_t j = 0; j < chunk_size; j++)
{
restored_payload[offset_payload] = low_entropy_payload_holder[offset_payload_after];
offset_payload_after++;
offset_payload++;
}
for (size_t k = 0; k < chunk_size; k++)
{
offset_payload_after++;
}
}
if (remaining_bytes)
{
for (size_t i = 0; i < sizeof remaining_bytes; i++)
{
restored_payload[offset_payload++] = high_ent_payload[offset_payload_after++];
}
}
return restored_payload;
}
int main() {
unsigned char shellcode[] = restore_original(payload);
}
I get the following error on the last code line (inside main function):
Error: Initialization with '{...}' expected for aggregate object
I tried to change anything on the array itself (seems like they might be the problem). I would highly appreciate your help as this is a part of my personal research :)
In order to initialize an array defined with [], you must supply a list of values enclosed with {}, exactly as the error message says.
E.g.:
unsigned char shellcode[] = {1,2,3};
You can change shellcode to be a pointer if you want to assign it the output from restore_original:
unsigned char* shellcode = restore_original(payload);
Update:
As you can see in #heapunderrun's comment, there is another problem in your code. restore_original returns a pointer to a local variable, which is not valid when the function returns (a dangling pointer).
In order to fix this, restore_original should allocate memory on the heap using new. This allocation has to be freed eventually, when you are done with shellcode.
However - although you can make it work this way, I highly recomend you to use std::vector for dynamic arrays allocated on the heap. It will save you the need to manually manage the memory allocations/deallocations, as well as other advantages.
You can't assign a char * to a char []. You can probably do something with constexpr but I'm suspecting an XY problem here.

How to use std::find() with a 2d std: array?

I am writing a function CreateGrid() that is trying to take a std::string and a 2d std::array as parameters, and put the individual characters from the std::string into the array. The rest of the array, if space is left, should be filled with the alphabetical characters A-Y, inclusive, in alphabetical order, providing they do not already appear in the std::string. Each character should only appear once in the final returned array.
So for input string keyword = "HELO";
The output would be:
H E L
O A B
C D F
Note the char 'E' only appears once.
I am trying to use std::find() to test whether all the chars in the alphabet A-Y (Z intentionally excluded) is already in the array, due to the keyword, before inserting it if it is not so that there are no duplicates. I am getting a compile error.
Code:
array<array<char,3>,3> CreateGrid(std::string keyword, array<array<char,3>,3> myArray)
{
char letterToFind = 'A';
for (int row = (keywordLength/3); row < 3; row++ )
{
for (int column = (keywordLength % 3); column < 3; column++)
{
auto it = std::find(begin(myArray), end(myArray), letterToFind);
if ( it == end(myArray) ) // value not in array
{
myArray[row][column] = letterToFind; //insert
}
letterToFind++;
}
}
return myArray;
}
int main()
{
array<array<char,3>,3> myArray = { {'H','E','L'}, {'O','+','+'}, {'+','+','+'} };
CreateGrid("HELO", myArray);
return 0;
}
I get a compile error for this line:
auto it = std::find(begin(myArray), end(myArray), letterToFind);
message : see reference to function template instantiation '_InIt std::find<std::_Array_iterator<_Ty,5>,char>(_InIt,const _InIt,const char &)' being compiled with[_InIt=std::_Array_iterator<std::array<char,3>3>,_Ty=std::array<char,3>]
How do I check to see if a char is in the array already, and if not then add it?
This is not normally trivial since you have nested arrays. std::find can only return an iterator to the outer array, which isn't useful if you need to change the value in the inner array.
However, I notice that you don't actually use it other than to see if the sought element was located. So, we can redefine the operation: instead of finding the element in an inner array that contains the value, it's sufficient to find any inner array that contains the value you're looking for:
auto it = std::find(
begin(myArray), end(myArray),
[letterToFind](array<char,3> const & inner) {
return std::find(begin(inner), end(inner), letterToFind) != end(inner);
}
);
If you found such an inner array, then you know that the value exists in the 2d array and can proceed.
Since you don't need the iterator, you could also use std::any_of instead:
bool found = std::any_of(
begin(myArray), end(myArray),
[letterToFind](array<char,3> const & inner) {
return std::find(begin(inner), end(inner), letterToFind) != end(inner);
}
);
Your myArray parameter is an array containing array<char,3> elements. You are using find() to search only that outer array. So begin(myArray) will return an iterator that enumerates array<char,3> elements, and you can't compare a single char to a whole array<char,3>, which is why your find() call does not compile. You would have to loop though the outer array calling find() on each inner array instead.
A simpler way to implement this is to use a lookup table to keep track of the characters that you have already seen, eg:
const size_t MaxRows = 3;
const size_t MaxColumns = 3;
const size_t MaxCells = MaxRows * MaxColumns;
using gridRow = std::array<char, MaxColumns>;
using grid = std::array<gridRow, MaxRows>;
grid CreateGrid(const std::string &keyword)
{
grid g;
std::array<bool, 256> lookup{};
size_t numFilled = 0;
for(size_t i = 0; (i < keyword.size()) && (numFilled < MaxCells); ++i)
{
if (!lookup[static_cast<unsigned char>(keyword[i])])
{
lookup[static_cast<unsigned char>(keyword[i])] = true;
g[numFilled / 3][numFilled % 3] = keyword[i];
++numFilled;
}
}
for(char ch = 'A'; (ch <= 'Y') && (numFilled < MaxCells); ++ch)
{
if (!lookup[static_cast<unsigned char>(ch)])
{
g[numFilled / 3][numFilled % 3] = ch;
++numFilled;
}
}
return g;
}
int main()
{
grid myArray = CreateGrid("HELO");
...
return 0;
}
Live Demo
Alternatively, you can use a std::set or std::unordered_set for the lookup:
#include <unordered_set>
const size_t MaxRows = 3;
const size_t MaxColumns = 3;
const size_t MaxCells = MaxRows * MaxColumns;
using gridRow = std::array<char, MaxColumns>;
using grid = std::array<gridRow, MaxRows>;
grid CreateGrid(const std::string &keyword)
{
grid g;
std::unordered_set<char> lookup;
size_t numFilled = 0;
for(size_t i = 0; (i < keyword.size()) && (numFilled < MaxCells); ++i)
{
if (lookup.insert(keyword[i]).second)
{
g[numFilled / 3][numFilled % 3] = keyword[i];
++numFilled;
}
}
for(char ch = 'A'; (ch <= 'Y') && (numFilled < MaxCells); ++ch)
{
if (lookup.insert(ch).second)
{
g[numFilled / 3][numFilled % 3] = ch;
++numFilled;
}
}
return g;
}
int main()
{
grid myArray = CreateGrid("HELO");
...
return 0;
}
Live Demo

a program to sum 2 arrays and display output in third array. It's showing Runtime error. Why?

I edited the code. But now it's showing runtime error. Can anyone tell why ? This is a program to sum 2 arrays and display output in third array.
I also wanted to know if this code could be optimized ?
void sumOfTwoArrays(int arr[], int size1, int brr[], int size2, int crr[])
{
int k;
if(size1>size2){
k = size1;
}
else
k = size2;
int c = k;
int r = 0;
int i = size1-1;
int j = size2-1;
for(;i>=0&&j>=0;i--,j--){
int n = arr[i] + brr[j] + r;
if(n<=9){
crr[c] = n;
}
else
{
int r = n/10;
n = n%10;
crr[c] = n;
}
c--;
}
while(arr[i]>=0){
crr[c] = arr[i] + r;
r = 0;
c--;
}
while(brr[j]>=0){
crr[c] = brr[j] + r;
r = 0;
c--;
}
if(r!=0){
crr[c] = r;
}
}
You declare variables in a block scope, i.e. inside { ... }, and these variables are visible only within this block:
if(size1>size2){
int crr[size1+1];
int c = size1;
}
else{
int crr[size2+1];
int c = size2;
}
...
crr[c] = ... // neither crr nor c are valid here any more
BTW: C++ does not support variable length arrays like int crr[size1+1] (when size is not a compile-time-constant).
To overcome this, write...
int *crr;
int c;
if(size1>size2){
crr = new int[size1+1];
c = size1;
}
else{
crr = new int[size2+1];
c = size2;
}
...
delete[] crr;
About scope issue: see Stephan's answer.
I also wanted to know if this code could be optimized
By use of std::vector. OK, the following is only a fine option if you can use vectors outside as well – copying the raw arrays into vectors wouldn't be efficient either... But if you can, then you might like this variant:
template <typename T> // optional: you're more flexible if you make a template of...
void sumOfTwoArrays(std::vector<T> const& va, std::vector<T> const& vb, std::vector<T>& vr)
{
vr.resize(std::max(va.size(), vb.size() + 1));
int carry = 0; // renamed r to something more meaningful
// these pairs will help to avoid code duplication later
std::pair pa(va, va.rbegin());
std::pair pb(vb, vb.rbegin());
auto ir = vr.rbegin();
while(pa.second != pa.first.rend() && pb.second != pb.first.rend())
{
// just skip the if/else:
// assume you have arbitrary number, the else case will be entered anyway
// in 50 % of the cases - in the other 50 %, the else branch calculates
// the correct result, too; and on most modern machines, the branch is
// rather expensive, so you result in easier code and have quite a good
// chance to even perform better...
carry += *pa.second + *pb.second;
*ir = carry % 10;
carry /= 10;
++ir, ++pa.second, ++pb.second;
}
// avoiding of two identical while loops: iterate over the two pairs...
for(auto p : { pa, pb })
{
// just loop over, if we are already at the end, won't enter...
while(p.second != p.first.rend())
{
// STILL need to continue calculating the carry!
// imagine we have set it and ciphers following are all 9!
carry += *p.second;
*ir = carry % 10;
carry /= 10;
++ir, ++p.second;
}
}
// assign either 0 or 1...
*ir = carry;
}
Variant: instead of assigning 0, you could erase first element at the very end:
if(carry == 0)
{
vr.erase(vr.begin());
}
else
{
*ir = carry;
}
Note that this will move all the elements one position to front. On the other hand, if you repeatedly add vectors already containing a leading zero, you might prepend another one again and again without need, if you don't drop it again.
You wouldn't experience any of these issues if you inverted the order of digits in the vector, having least significant one at position 0 (you'd exchange rbegin() and rend() with begin() and end(), but would use the former for printing data to display...). Erasure at the end would be an O(1) operation then:
if(carry == 0)
{
vr.erase(std::previous(vr.end())
}
// ...
All this above will only work as expected if you keep your vectors normalised (i. e. all digits in between 0 and 9 inclusive). You might consider packing the vector into a separate class such that the data is hidden away from the user and only can be modified in controlled manner (assume you have a fine vector, but a user does v[7] = -1012...).
A runtime error suggests that it is a memory issue i.e. you are writing to some memory which is not allocated to be used by your code. So, as mentioned by other contributors, you should allocate proper memory for your arrays.
Following is modified version of your code which is working fine. You can see it working here:
void sumOfTwoArrays(int arr1[], int size1, int arr2[], int size2, int sumArr[])
{
int maxLen;
int* tArry;
int l;
if(size1>size2) { maxLen = size1; tArry = arr1; l = size1 - size2; }
else { maxLen = size2; tArry = arr2; l = size2 - size1; }
int carry = 0;
while(size1 && size2){
carry += arr1[--size1] + arr2[--size2];
sumArr[maxLen--] = carry%10;
carry /= 10;
}
while(l){
carry += tArry[--l];
sumArr[maxLen--] = carry%10;
carry /= 10;
}
sumArr[maxLen] = carry;
}
Calling code looks something like this:
...
int a[] = {9,9,9,9,9};
int b[] = {1};
int l1 = sizeof(a) / sizeof(int), l2 = sizeof(b)/sizeof(int);
int l3 = ((l1 > l2) ? l1 : l2) + 1;
int *c = new int[l3];
sumOfTwoArrays(a, l1, b, l2, c);
...
delete [] c;
...