My question is can we initialize 2-d array using int a[10][10] = {{0}}.
According to the top answer in initialize-large-two-dimensional-array-in-c,
int array [ROW][COLUMN] = {0};
which means: "initialize the very first column in the first row to 0, and all other items as if they had static storage duration, ie set them to zero."
However, checking C99 Standard 9899:TC3 and C++11 Standard N4296, I haven't found any official records supporting what was mentioned in this answer.
Besides, I do come across this issue when I try to solve the LeetCode 474. Ones and Zeroes problem with the following solution.
// To make question clear:
// It seems that "int dp[m + 1][n + 1] = {{0}}" cannot initilize all elem to 0
// "memset(dp, 0, sizeof dp)" is necessary to pass the OJ test. Any idea?
class Solution {
public:
// m : 0s, n : 1s
int findMaxForm(vector<string>& strs, int m, int n) {
int dp[m + 1][n + 1] = {{0}};
// We will get "Wrong Answer" without memset() function below
memset(dp, 0, sizeof dp);
for (auto& str : strs) {
auto cost = getCost(str);
for (int i = 0; i + cost.first <= m; ++i)
for (int j = 0; j + cost.second <= n; ++j)
dp[i][j] = std::max(dp[i + cost.first][j + cost.second] + 1,
dp[i][j]);
}
int max = 0;
for (int i = 0; i <= m; ++i)
for (int j = 0; j <= n; ++j)
max = std::max(max, dp[i][j]);
return max;
}
private:
pair<int, int> getCost(const string& str) const {
int cnts[] = {0, 0};
for (char c : str) ++cnts[static_cast<char>(c == '1')];
return {cnts[0], cnts[1]};
}
};
Your code is C++ code. Other questions and documents about C are irrelevant; C and C++ are different languages.
In Standard C++ , array dimensions must be known at compile-time. int dp[m + 1][n + 1] is an error (let alone trying to initialize it).
Possibly you're using a compiler that offers C++ VLA as a non-standard extension. In that case you are at the mercy of the particular compiler as to what the behaviour of the code will be, and what the behaviour of ={{0}} on it might be. The C++ standard will not help.
My advice would be to avoid non-standard constructs, so that you retain the guarantees provided by the standards documents.
Related
I have been trying to implement the Fibonacci series in linear time. I keep getting weird results each time I run the program. I am a newbie in C++.
int fib1(int n) {
int arr[n];
arr[0] = 0;
arr[1] = 1;
for (int i = 2; i < n; i++) {
arr[i] = arr[i - 1] + arr[i - 2];
}
return arr[n];
}
int main() {
int x = fib1(3);
cout << x << endl;
return 0;
}
The expected result is: 2
The result I am getting is: 4199748
Where did I mess up?
If arr is of length n it doesn't have an element with index n and therefore you are accessing the array out-of-bounds in return arr[n]. That causes undefined behavior and anything could happen. You probably wanted an array of length n+1 and iteration up to i <= n.
Furthermore the array size must be known at compile time in standard C++. Therefore the variable-length array arr[n] is only allowed because your compiler has special support for it. Use std::vector instead.
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;
...
The following code implements a suffix array algorithm.
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <string.h>
using namespace std;
/**--- Reference:http://www.geeksforgeeks.org/suffix-array-set-1-introduction/ ---*/
/**
* #brief store the information of suffix
*/
struct suffix
{
int index;
string suff;
};
/**
* #brief get suffix_array
* #param text
* #param n the length of text
*
* ps:
* b a n a n a
* 5 3 1 0 4 2
*
* 0 banana 5 a
* 1 anana Sort the Suffixes 3 ana
* 2 nana ----------------> 1 anana
* 3 ana alphabetically 0 banana
* 4 na 4 na
* 5 a 2 nana
*
* suffix array for "banana" is {5, 3, 1, 0, 4, 2}
*
* Rank array: the rank array rank[i] represents the rank of the suffix
* beginning at the ith position. That is, if suffix_array[i]=j,
* then rank[j] = i
*
*/
vector<int> buildSuffixArray(string& text, int n)
{
//store suffixes and their indices
struct suffix suffixes[n];
vector<int> suffix_array;
for (int i = 0; i < n; ++ i)
{
suffixes[i].index = i;
suffixes[i].suff = text.c_str() + i;
}
sort(suffixes, suffixes + n, [](struct suffix a, struct suffix b) {
return strcmp(a.suff.c_str(), b.suff.c_str()) < 0 ? 1 : 0;
});
for (int i = 0; i < n; ++ i)
suffix_array[i] = suffixes[i].index;
return suffix_array;
}
vector<int> rankArray(vector<int>& suffix_array)
{
vector<int> rank_array(suffix_array.size());
for (int i = 0; i < suffix_array.size(); i++)
rank_array[suffix_array[i]] = i;
return rank_array;
}
When I copy this code into Visual Studio, it reminds me that expressions must contain a constant value, and n-->(struct suffix suffixes[n]) can not be used in this place. The following is the Chinese error message that my compiler reports.
表达式必须含有常量值,参数n不可用作常量值
I don't understand why, and I can compile it by gcc with no mistake.
And I do not know how vector can be the return type value, could someone give me some suggestions?
Variable Length Arrays
I can compile it by gcc with no mistake.
An array suffix suffixes[n] is created on stack with automatic storage duration.
Then this n usually must be determined at compile-time in C++.
But some C++ compilers support VLA (variable length arrays) which is a C99 addition and allows declaring C-style arrays on stack with a non constant length.
VC++ does not support C99 and VLA, but GNU compiler supports VLA as an extension even in C90 and C++.
This is the reason why you can compile the above code by gcc without errors.
There are various related past posts.
Why can i declare an array with a predestined size on gcc but not on visual studio c++?
Why does a C/C++ compiler need know the size of an array at compile time?
Why aren't variable-length arrays part of the C++ standard?
Variable Length Array (VLA) in C++ compilers
If you add -pedantic (-pedantic-errors) option to gcc compile command, we can get warnings (errors) for most gcc extensions.
In this case, with this option we should get following warning (error) message:
ISO C++ forbids variable length array 'suffixes'
Implementation of buildSuffixArray
And I do not know how vector can be the return type value
Your buildSuffixArray goes to segmentation fault even in GNU compilers because suffix_array is not allocated.
The following minimally fixed version will work fine with GNU compilers:
std::vector<int> buildSuffixArray(const std::string& text, int n)
{
suffix suffixes[n];
for (int i = 0; i < n; ++ i)
{
suffixes[i].index = i;
suffixes[i].suff = text.c_str() + i;
}
std::sort(suffixes, suffixes + n, [](struct suffix a, struct suffix b) {
return std::strcmp(a.suff.c_str(), b.suff.c_str()) < 0 ? 1 : 0;
});
std::vector<int> suffix_array(n);
for (int i = 0; i < n; ++ i){
suffix_array[i] = suffixes[i].index;
}
return suffix_array;
}
But VC++ does not support VLA and the above fixed version still shows compile error with VC++.
The following code is an example avoiding VLA (, redundant argument n and lambda expression).
This will work fine with both gcc and VC++.
DEMO is here.
std::vector<int> buildSuffixArray(const std::string& text)
{
std::vector<suffix> suffixes(text.length());
for (std::size_t i = 0; i < suffixes.size(); ++i)
{
suffixes[i].index = i;
suffixes[i].suff = text.c_str() + i;
}
std::sort(suffixes.begin(), suffixes.end(), [](const suffix& a, const suffix& b) {
return (std::strcmp(a.suff.c_str(), b.suff.c_str()) < 0);
});
std::vector<int> suffix_array(text.length());
for (std::size_t i = 0; i < suffix_array.size(); ++i){
suffix_array[i] = suffixes[i].index;
}
return suffix_array;
}
In order to get more familiar with C++, I have started working on some algebraic problems. Now, I have created an algorithm which generate a combination of numbers, with some constraints, based on an input number:
void abc(const int n) {
std::vector<int> aOut, bOut, cOut; // creating vectors to store values (dynamic int arrays)
for (int a = 9; a <= n - 2; a++) {
for (int b = a + 1; b <= n - 1; b++) {
for (int c = b + 1; c <= n; c++) {
aOut.push_back(a);
bOut.push_back(b);
cOut.push_back(c);
// std::cout << "a = " << a << " b = " << b << " c = " << c << std::endl;
}
}
}
Now, I need to continue working with these vectors, so I need to return them somehow. I have tried to create an int array of the size: int ABC[N][3], where const int N = cOut.size();. This does not work, as N is not accepted as a constant.
I also tried making a counter in the loop where I generate the vectors, which I then transferred to a string which I then transferred to a constant integer - this did not work either.
I tried making a pointer to a constant int, and using it to change the constant in the loop, which did not work either.
I even found a way to calculate the size based on my loops:
const int n = 20;
const int n1 = n - 10; // Manipulating input
const int N = n1*(n1 + 1)*(n1 + 2) / 6; // Size of vectors
And then passing the value to the function as:
void abc(const int n, const int N) { // same code as before }
But nothing works. I am honestly out of ideas (and losing my head). I have browsed trough the forum and google, but without luck. If someone could point me in the right direction, I would be forever grateful.
Of cause the solution includes changing the void to a function that returns the parameters. I added the void as I would like to check if the values were printed correctly.
How about creating an element (container) which encapsulates your 3 vectors as a return element?
The problem you're having is that functions (like Mathemematicians want to) return one value, but this can be any value :).
You could use a class or a struct which will has the vectors as attributes:
struct returnElement { // choose an adequate name
std::vector<int> aOut, bOut, cOut;
};
so now your abc function would return the returnElement struct. It could look something like this:
returnElement abc (const int n) {
returnElement ret; // creating vectors to store values (dynamic int arrays)
for (int a = 9; a <= n - 2; a++) {
for (int b = a + 1; b <= n - 1; b++) {
for (int c = b + 1; c <= n; c++) {
ret.aOut.push_back(a);
ret.bOut.push_back(b);
ret.cOut.push_back(c);
}
}
return ret;
}
Why not have an std::array of std::vector?
std::array<std::vector<int>, 3> abc(int const n)
{
std::array<std::vector<int>, 3> outArray;
for (int a = 9; a <= n - 2; a++)
{
for (int b = a + 1; b <= n - 1; b++)
{
for (int c = b + 1; c <= n; c++)
{
outArray[0].push_back(a);
outArray[1].push_back(b);
outArray[2].push_back(c);
}
}
}
return outArray;
}
To answer your question concerning array sizes,
I have tried to create an int array of the size: int ABC[N][3], where const int N = cOut.size();. This does not work, as N is not accepted as a constant.
The size of an array (whether raw or std::array) must be compile-time constant. If the size is not known at compile-time you must either create a dynamic array (using new) or use an std::vector.
If you know how large the vector is to be, you can reserve space in it for your elements, like so:
std::vector<int> yourVec;
yourVec.reserve(100); // reserve space for 100 ints
or
std::vector<int> yourVec;
yourVec.resize(100, 0); // populates yourVec with 100 ints with value 0
See Choice between vector::resize() and vector::reserve() for the differences between reserve and resize.
I am trying to generate some lotto numbers and return the array that contain these numbers but I cant go any further; Help please
void getLotto(int rad[7]) {
int numbers[7];
for (int i = 0; i < 7; i++) {
numbers[i] = rand() % 35 + 1;
}
for (int j = 0; j < 7; j++) {
int n = rand() % 35 + 1;
if (n == numbers[j]) {
numbers[j] = rand() % 35 + 1;
return;
}
}
}
Arrays can't be returned by functions. A common thing to do is to dynamically allocate the array and return a pointer to its first element. This will work in your case but will generate a requirement for the caller to manage the memory (delete[] the new[]'ed memory). That's why C++ provides us with standard array classes: Use and return a std::vector. If you have C++11 support, return std::array.
Following may help, using Fisher–Yates_shuffle:
// Fisher–Yates_shuffle
// http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
std::vector<int> FisherYatesShuffle(std::size_t size, std::size_t max_size, std::mt19937& gen)
{
assert(size < max_size);
std::vector<int> res(size);
for(std::size_t i = 0; i != max_size; ++i) {
std::uniform_int_distribution<> dis(0, i);
std::size_t j = dis(gen);
if (j < res.size()) {
if (i != j) {
res[i] = res[j];
}
res[j] = 1 + i;
}
}
return res;
}
Live example
std::vector and std::array are better than regular arrays, but if you want to use regular arrays you can modify your function as follows:
// Arguments: renamed the array, added N (# of array elements)
void getLotto(int numbers[], size_t N) {
//int numbers[7]; // commented out local variable
for (int i = 0; i < N; i++) {
numbers[i] = rand() % 35 + 1;
}
for (int j = 0; j < N; j++) {
int n = rand() % 35 + 1;
if (n == numbers[j]) {
numbers[j] = rand() % 35 + 1;
return;
}
}
}
The brackets in int numbers[] indicates that the argument is an array, and what is actually passed is a pointer to the first element of the array. Modifying numbers in getLotto() modifies the array passed to the function.
The second argument is of type size_t because it is the platform-dependent alias for the unsigned integral type used by your system to represent the size of objects (like arrays).
This isn't as safe in that the function has to trust that numbers actually has N elements, but this is how you have a function modify a regular array instead of a container like std::vector.
You would call the function like this:
size_t N;
int numbers[N];
getLotto(numbers, N);
C++ does not allow to return an entire array as an argument to a function. However, you can return a pointer to an array by specifying the array's name without an index.
If you want to return a single-dimension array from a function, you would have to declare a function returning a pointer as in the following example:
int * myFunction()
{
.
.
.
}
Second point to remember is that C++ does not advocate to return the address of a local variable to outside of the function so you would have to define the local variable as static variable.
Now, consider the following function, which will generate 10 random numbers and return them using an array and call this function as follows:
#include <iostream>
#include <ctime>
using namespace std;
// function to generate and retrun random numbers.
int * getRandom( )
{
static int r[10];
// set the seed
srand( (unsigned)time( NULL ) );
for (int i = 0; i < 10; ++i)
{
r[i] = rand();
cout << r[i] << endl;
}
return r;
}
// main function to call above defined function.
int main ()
{
// a pointer to an int.
int *p;
p = getRandom();
for ( int i = 0; i < 10; i++ )
{
cout << "*(p + " << i << ") : ";
cout << *(p + i) << endl;
}
return 0;
}
When the above code is compiled together and executed, it produces result something as follows
624723190
1468735695
807113585
976495677
613357504
1377296355
1530315259
1778906708
1820354158
667126415
*(p + 0) : 624723190
*(p + 1) : 1468735695
*(p + 2) : 807113585
*(p + 3) : 976495677
*(p + 4) : 613357504
*(p + 5) : 1377296355
*(p + 6) : 1530315259
*(p + 7) : 1778906708
*(p + 8) : 1820354158
*(p + 9) : 667126415
There are two main ways of accomplishing this.
note: I'm not sure what your second for loop is doing. I guess the intention was to ensure that the numbers are all unique? You might want to take a look at it as that is not what it is doing.
For the purposes of this question, I've cut it down to just generating the random numbers to populate the array.
The first is to take your code and fix it to put the generated numbers into the array that was passed in:
#include <iostream>
void getLotto(int numbers[7]) {
for (int i = 0; i < 7; i++)
{numbers[i] = rand() % 35 + 1;}
return;
}
int main()
{
srand(time(0));
int lotto_numbers[7];
getLotto(lotto_numbers);
for (int i = 0; i < 7; i++)
{std::cout<<lotto_numbers[i]<<std::endl;}
}
numbers isn't actually passed in as an int[] but instead as an int* pointing to the array. This means that any changes you make to it in the function are changed in the original data.
Bear in mind that you need to keep track of your array bounds though, as the array could be defined as
int lotto_numbers[6]
which means that
numbers[7]
would be out of bounds.
The second method is to create the array on the heap. This means that you don't need to pass in an array but you can instantiate it in the function
I'm not actually going to provide the code for this here. Mainly because for something simple like this, the memory management is more trouble than it is worth. (you need to remember to call delete[] for everything created on the heap etc).
Instead, lets use something with memory management built in:
#include <iostream>
#include <vector>
std::vector<int> getLotto() {
std::vector<int> numbers;
numbers.reserve(7);
for (int i = 0; i < 7; i++) {
//numbers[i] = rand() % 35 + 1;
//would work, but is unsafe as you could potentially reference somthing out of range
//this is safer:
numbers.push_back(rand() % 35 + 1);
}
return numbers;
}
int main()
{
srand(time(0));
std::vector<int> lotto_numbers = getLotto();
for (auto i = lotto_numbers.begin(); i != lotto_numbers.end(); i++)
{
std::cout<<*i<<std::endl;
}
}
The vector handles the memory management for you. The vector can be returned, and the returned vector will still point at the allocated memory on the heap we have just populated. We don't need to free it as this will be done automatically when the vector goes out of scope.