Does C++ allow VLAs as function parameter - c++

Given code is for generating a magic square in which i have used VLA for the function
create_magic_square(int n, int magic_square[n][n])
print_magic_square(int n, int magic_square[n][n])
#include <stdio.h>
void create_magic_square(int n, int magic_square[n][n]);
void print_magic_square(int n, int magic_square[n][n]);
int main()
{
int size;
printf("This program creates a magic square of a specified size");
printf("The size be an odd number between 1 and 99");
printf("Enter the size of magic square: ");
scanf("%d", &size);
if(size%2 == 0 || size < 0 || size > 99)
{
printf("Wrong Entry!!!");
return 0;
}
int square[size][size];
for( int i = 0; i < size; i++)
for(int j = 0; j < size; j++)
square[i][j] = 0;
create_magic_square(size, square);
print_magic_square(size, square);
return 0;
}
void create_magic_square(int n, int magic_square[n][n])
{
int row = 0, col = n/2;
magic_square[row][col] = 1;
while(magic_square[row][col] <= n*n)
{
int new_row = ((row - 1) + n) % n;
int new_col = ((col + 1) + n) % n;
if(magic_square[new_row][new_col] == 0)
{
magic_square[new_row][new_col] = magic_square[row][col] + 1;
row = new_row;
col = new_col;
}
else if(magic_square[new_row][new_col] != 0)
{
magic_square[row + 1][col] = magic_square[row][col] + 1;
row = row + 1;
}
}
}
void print_magic_square(int n, int magic_square[n][n])
{
for( int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
printf("%d ", magic_square[i][j]);
printf("\n\n");
}
}
when file saved with extension .cpp ,On compiling it is giving the following error:
When I changed this extension to .c, it worked fine.
What is the reason behind this?
I think VLAs are not allowed in C++, is it right?
NOTE: Check this link regarding VLAs as parameter:
Why use an asterisk "[*]" instead of an integer for a VLA array parameter of a function?

You can't use C-style array that way, all but the first extent must be compile-time constant.
What you can do is pass int *magic_square that points to a one-dimensional n*n array, and use a simple index-mapping function to get the linear index of the cell.
You tagged the question as C++, so you should know that
int square[size][size];
is not valid C++ either, though it's valid C99 and some compilers support it through extension.
For C++ I'd suggest to use std::vector<int> vec(size*size) as holder.

Related

Is it possible for a function to owerwrite the input array with a smaller one?

The task: Create a function that takes a list of numbers as a parameter, and returns a list of numbers where every number in the list occurs only once
As far as I know, functions can't return arrays. But if a function's parameter is an array, it will be automatically a reference parameter, so it will "overwrite" the input array even if it's a void function. Is there any way to overwrite (as reference parameter) the input array with a smaller one?
To be specific: in the code below I would like to overwrite the number[10] array with the newArray[6]
I just started to learn code this week, this is a practice task for me, so I would like to use C++ basics to solve this one, without pointers and more complex stuff. If it's not possible, it's okay too.
#include <iostream>
#include <string>
void selectionSort(int[], int);
void unique(int[], int);
void print(int[], int);
int main(int argc, char *args[]) {
int numbers[] = {1, 11, 34, 11, 52, 61, 0, 1, 34, 1, 61, 72};
int size = sizeof(numbers) / sizeof(int);
unique(numbers, size);
return 0;
}
void unique(int arr[], int size) {
selectionSort(arr, size);
int newSize = 1;
for (int i = 0; i < size - 1; ++i) {
if (arr[i] < arr[i + 1]) {
newSize++;
}
}
int newArray[newSize];
int index = 0;
for (int i = 0; i < size - 1; ++i) {
if (arr[i] < arr[i + 1]) {
newArray[index] = arr[i];
++index;
}
}
newArray[newSize - 1] = arr[size - 1];
print(newArray, newSize);
}
void selectionSort(int arr[], int size) {
for (int i = 0; i < size; i++) {
int min = i;
for (int j = i; j < size; j++) {
if (arr[j] < arr[min]) {
min = j;
}
}
std::swap(arr[i], arr[min]);
}
}
void print(int arr[], int size) {
for (int i = 0; i < size; ++i) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
}
This is not valid C++:
int newArray[newSize];
That's VLA, which is C99, only available with gcc.
Instead, do:
int* newArray = new int[newSize];
Return this:
return std::make_pair(newArray, newSize);
As you need to return the size as well!! Even if you can overwrite the input array (you can, obviously, depends on your contract, the documentation of your function), you need to return the new size.
But you may want to take a real C++ class.

C++ parameterized constructor makes code to stop working when large input's are passed

void initialize(int arr[], int size[], int n)
{
int i;
for(i = 1; i <= n; i++) {
arr[i] = i;
size[i] = 1;
}
}
class hell
{
public:
int edges;
int vertices;
pair<int , pair<int,int>> p[100000];
int disjoint_set[10000];
int cc_size[10000]; // size of connected components
hell(int e, int v)
{
edges = e;
vertices = v;
initialize(disjoint_set, cc_size, vertices);
}
};
In the following class when I create an object using vertices=100000 and edges=100000, the code stops working. But when we remove the initialize(disjoint_set, cc_size, vertices) it starts working. I don't have any clue to such behavior. Please guide me.
Arrays in C++ are zero indexed, which means that valid index is in [0..n[ range. Your code does it wrong:
for(i = 1; i <= n; i++) {
arr[i] = i;
size[i] = 1;
}
it should be:
for(i = 0; i < n; i++) {
arr[i] = i + 1;
size[i] = 1 + 1;
}
or better use algo std::iota() and std::fill():
std::iota( arr, arr + n, 1 );
std::fill( size, size + n, 1 );
and you better use std::vector, which will adjust its size properly, rather than have huge array.

Porting code from C++ to C. How do I deal with this vector and range based loop

I am trying to port to C. Since there's no vectors in C, I used a normal array, but I don't know how I'm going to deal with the ranged based loop on line 18.
for (int u : d[i]) if (dfs(rev[u])) {
par[i] = u;
rev[u] = i;
return true;
}
Complete code:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
const int Maxn = 200;
vector<int> d[Maxn];
int par[Maxn];
int rev[Maxn];
bool vs[Maxn];
bool dfs(int i) {
if (i < 0) return true;
if (vs[i]) return false;
vs[i] = true;
for (int u : d[i]) if (dfs(rev[u])) {
par[i] = u;
rev[u] = i;
return true;
}
return false;
}
int main() {
ios_base::sync_with_stdio(false);
int n;
cin >> n;
string s;
getline(cin, s);
for (int i = 0; i < n; i++) {
getline(cin, s);
stringstream ss(s);
vector<int> mk(n, 1);
mk[i] = 0;
int x;
while (ss >> x)
mk[x] = 0;
for (int x = 0; x < n; x++)
if (mk[x])
d[i].push_back(x);
}
memset(par, -1, sizeof par);
memset(rev, -1, sizeof rev);
for (bool ok = true; ok; ) {
ok = false;
memset(vs, 0, sizeof vs);
for (int i = 0; i < n; i++)
if (par[i] < 0) {
ok |= dfs(i);
}
}
int ans = 0;
for (int i = 0; i < n; i++)
ans += (par[i] < 0);
cout << ans;
}
In C there is no std::vector, the closes would be an array.
int array[] = [ 1, 3, 5, 7, 9 ];
for(int i = 0; i < sizeof array / sizeof *array; ++i)
printf("array[%d] = %d\n", i, array[i]);
If you get a pointer of an array of int, the you have to pass the length of
the array as well, as sizeof arr / sizeof *arr works with arrays only.
void foo(in *array, size_t len)
{
for(int i = 0; i < len; ++i)
printf("array[%d] = %d\n", i, array[i]);
}
void bar(void)
{
int array[] = [ 1, 3, 5, 7, 9 ];
foo(array, sizeof array / sizeof *array);
}
edit 2
I noticed that you've posted your code and that d is declared as vector<int> d[Maxn];. Also taking in consideration your recent comment
So this is an array of vectors. Do you have any idea how i can work with arrays taking that in consideration in C
There a couple of ways to convert the array of vectors in C. But this depends
on your needs. If for example you know that all vectors are going to have the
same size (for example int vectsize = 100), then you can create a two
dimensional array with the sizes1
int Maxn = 200;
int vectsize = 100;
int d[Maxn][vectsize];
memset(d, 0, sizeof d); // initialize all elements with 0
// filling the data
for(int i = 0; i < Maxn; ++i)
{
for(j = 0; j < vectsize; ++j)
d[i][j] = get_value_for(i, j);
}
The the range-loop is very easy:
// assuming that the variables i, par, rev are valid, i between 0 and Maxn-1
for(int j = 0; j < vectsize; ++j)
{
int u = d[i][j];
if (dfs(rev[u])) {
par[i] = u;
rev[u] = i;
return true;
}
}
It gets a little more complicated if you only know one dimension, for example
every vector in the array could have a different size.
d[0].size() --> 10
d[1].size() --> 1
d[2].size() --> 3
...
The you can create an array of pointers to int, but you would have to keep
another array of ints with the length for every d[i] vector.
int Maxn = 200;
int *d[Maxn]; // pointer to int[Maxn] arrays
int vectsize[Maxn];
// initializing with 0
memset(d, 0, sizeof d);
memset(vectsize, 0, sizeof vectsize);
// filling the data
for(int i = 0; i < Maxn; ++i)
{
vectsize[i] = get_length_for(i);
d[i] = malloc(vectsize[i] * sizeof *d[i]);
if(d[i] == NULL)
// error handling
for(j = 0; j < vectsize[i]; ++j)
d[i][j] = get_value_for(i, j);
}
Note that I'm using here (and in the last example) get_length_for() and get_value_for() as placeholders2.
Now your range-base loop would look like this:
// assuming that the variables i, par, rev are valid, i between 0 and Maxn-1
for(int j = 0; j < vectsize[i]; ++j)
{
int u = d[i][j];
if (dfs(rev[u])) {
par[i] = u;
rev[u] = i;
return true;
}
}
At some point however you would have to free the memory:
for(int i = 0; i < Maxn; ++i)
free(d[i]);
The third option would be using a double pointer and using malloc/realloc
to allocate the memory. This is the more general solution, but you have to
take care of memory management and that can be sometimes difficult, especially when you
haven't programmed in C to much. But also in case where both dimension are unknown, this is the way to go:
int Maxn = get_some_maxn_value();
int **d, *vectsize;
d = malloc(Maxn * sizeof *d);
if(d == NULL)
// error handling
vectsize = malloc(Maxn * sizeof *vectsize);
if(vectsize == NULL)
// error handling,
// if you exit the function, don't forget
// to do free(d) first as part of the
// error handling
// initialize all elements with 0
memset(d, 0, Maxn * sizeof *d);
memset(vectsize, 0, Maxn * sizeof *vectsize);
// filling the data (the same as above)
for(int i = 0; i < Maxn; ++i)
{
vectsize[i] = get_length_for(i);
d[i] = malloc(vectsize[i] * sizeof *d[i]);
if(d[i] == NULL)
// error handling
for(j = 0; j < vectsize[i]; ++j)
d[i][j] = get_value_for(i, j);
}
In this case the range-loop would look exactly as for the array of pointers.
Freeing the memory is a little bit different though:
for(int i = 0; i < Maxn; ++i)
free(d[i]);
free(d);
free(vectsize);
Like I said earlier, which one of these three methods to use depends on the way
the original C++ code fills the values, how long the vectors are, etc. Judging
form the C++ code you posted, you read an integer from the user and store it
in n. Then you read more values from the user and push then in the vector
d[i] for all i between 0 and Maxn-1. It seems that all vectors have at
most length n, but because of
if (mk[x])
d[i].push_back(x);
they also could have less than n elements. That's why I think that the third
solution is preferable here.
Annotations
1Prior to C99, Variable Length Arrays (VLA) were not supported, so if you had the
dimension in a variable, you had to use malloc to allocate enough memory.
C99 supports VLAs, but I'm not quite sure how well supported they are and/or
whether your compiler supports them.
I personally don't use them in my code at all, that's why I really don't know. I compiled this examples with GNU
GCC 6.4.0 (on linux) and they worked fine.
The first two options use VLAs, if your compiler doesn't support that, then
you have to use the third option.
For more information about VLAs:
malloced array VS. variable-length-array
What's the difference between a VLA and dynamic memory allocation via malloc?
Variable length array
GCC manual: 6.19 Arrays of Variable Length (in case you ise GCC)
2How you really get this values depends on the original C++ code.
So far I've only looked very briefly over your C++ code. Using the values from
my example get_length_for(0) would return 10, get_length_for(1) would return 1,
get_length_for(2) would return 3, etc.
Assuming d[i] is a vector, this is a similar loop:
for (size_t s = 0; s < d[i].size(); s++)
{
int u = d[i][s];
if (dfs(rev[u]))
{
par[i] = u;
rev[u] = i;
return true;
}
}

Outputting differences in arrays

I have to make a code where the user inputs altitude readings and the code is supposed to output total climb, total descent, and net change. This is what I have below. I can't figure out how to code to have it output what I want it to.
#include <iostream>
using namespace std;
int main()
{
int array[2010], n, c, d, swap; //the array
printf("Enter number of elements\n");
scanf("%d", &n);
printf("Enter %d integers\n", n);
for (c=0; c < n; c++)
scanf("%d", &array[c]);
for (c=0 ; c < ( n - 1 ); c++)
{
for (d = 0 ; d < n - c - 1; d++)
{
if (array[d] > array[d+1]) /* For decreasing order use < */
{
swap = array[d];
array[d] = array[d+1];
array[d+1] = swap;
}
}
}
printf("Sorted list in ascending order:\n"); //lists in order
for ( c = 0 ; c < n ; c++ )
printf("%d\n", array[c]);
// Returns minimum difference between any pair
int findMinDiff(int arr[2010], int n); //supposed to find differce
{
// Initialize difference as infinite
int diff = INT_MAX;
// Find the min diff by comparing difference
// of all possible pairs in given array
for (int d=0; d<n-1; d++)
for (int j=d+1; j<n; j++)
if (abs(array[d] - array[d--]) < diff)
diff = abs(array[d] - array[d--]);
cout<<"Total Climb "<<diff<<endl;
}
system("pause");
return 0;
}
I don't see why you are sorting the array. Sorting the array may cause problems in calculating the "total climb" and "total descent".
My understanding is that this assignment is about calculating the difference between two numbers and processing that difference.
void Process_Data(int array[2010], unsigned int quantity_of_climbs)
{
int total_climb = 0;
int total_descent = 0;
int minimum_change = INT_MAX;
for (int i = 0; i < quantity_of_climbs - 1; ++i)
{
const int height_change = array[i] - array[i+1];
if (height_change > 0) // A "climb"
{
total_climb += height_change;
}
if (height_change < 0) // A "descent"
{
total_descent = (-1) * height_change; // Change from negative to positive.
}
const int abs_height_change = abs(height_change);
if (abs_height_change < minimum_change)
{
minimum_change = abs_height_change;
}
}
// Display results
}

Damerau–Levenshtein distance (Edit Distance with Transposition) c implementation

I implemented the Damerau–Levenshtein distance in c++ but it does not give correct o/p for the input (pantera,aorta) the correct o/p is 4 but my code gives 5.....
int editdist(string s,string t,int n,int m)
{
int d1,d2,d3,cost;
int i,j;
for(i=0;i<=n;i++)
{
for(j=0;j<=m;j++)
{
if(s[i+1]==t[j+1])
cost=0;
else
cost=1;
d1=d[i][j+1]+1;
d2=d[i+1][j]+1;
d3=d[i][j]+cost;
d[i+1][j+1]=minimum(d1,d2,d3);
if(i>0 && j>0 && s[i+1]==t[j] && s[i]==t[j+1] ) //transposition
{
d[i+1][j+1]=min(d[i+1][j+1],d[i-1][j-1]+cost);
}
}
}
return d[n+1][m+1];
}
I don't see any errors. Can someone find a problem with the code?
The algorithm in the post does not compute Damerau-Levenshtein distance. In a wikipedia article this algorithm is defined as the Optimal String Alignment Distance.
A java implementation of DL distance algorithm can be found in another SO post.
To get the correct values of OSA distance please change the lines marked with - below with the lines marked with +
int editdist(string s,string t,int n,int m)
{
int d1,d2,d3,cost;
int i,j;
for(i=0;i<=n;i++)
{
for(j=0;j<=m;j++)
{
- if(s[i+1]==t[j+1])
+ if(s[i+1]==t[j+1])
cost=0;
else
cost=1;
d1=d[i][j+1]+1;
d2=d[i+1][j]+1;
d3=d[i][j]+cost;
d[i+1][j+1]=minimum(d1,d2,d3);
- if(i>0 && j>0 && s[i+1]==t[j] && s[i]==t[j+1] ) //transposition
+ if(i>0 && j>0 && s[i]==t[j-1] && s[i-1]==t[j] ) //transposition
{
d[i+1][j+1]=min(d[i+1][j+1],d[i-1][j-1]+cost);
}
}
}
return d[n+1][m+1];
}
It looks as if the code was copied from a program written in a programming language where array indices start at 1 by default. Therefore all references to the elements of the distance array d were incremented. However the references to the characters within the strings are references to 0-based arrays, therefore they should not be updated.
To compute the distance the distance array has to be properly initialized:
for( i = 0; i < n + 1; i++)
d[i][0] = i;
for( j = 1; j < m + 1; j++)
d[0][j] = j;
Since you have got the answer 5, you probably have your distance array already initialized correctly.
Since the above algorithm does not compute the DL distance, here is a sketch of a C implementation of the DL algorithm (derived from the SO post with a java impl. derived from an ActionScript impl. in the Wikipedia article).
#define d(i,j) dd[(i) * (m+2) + (j) ]
#define min(x,y) ((x) < (y) ? (x) : (y))
#define min3(a,b,c) ((a)< (b) ? min((a),(c)) : min((b),(c)))
#define min4(a,b,c,d) ((a)< (b) ? min3((a),(c),(d)) : min3((b),(c),(d)))
int dprint(int* dd, int n,int m){
int i,j;
for (i=0; i < n+2;i++){
for (j=0;j < m+2; j++){
printf("%02d ",d(i,j));
}
printf("\n");
}
printf("\n");
return 0;
}
int dldist2(char *s, char* t, int n, int m) {
int *dd;
int i, j, cost, i1,j1,DB;
int INFINITY = n + m;
int DA[256 * sizeof(int)];
memset(DA, 0, sizeof(DA));
if (!(dd = (int*) malloc((n+2)*(m+2)*sizeof(int)))) {
return -1;
}
d(0,0) = INFINITY;
for(i = 0; i < n+1; i++) {
d(i+1,1) = i ;
d(i+1,0) = INFINITY;
}
for(j = 0; j<m+1; j++) {
d(1,j+1) = j ;
d(0,j+1) = INFINITY;
}
dprint(dd,n,m);
for(i = 1; i< n+1; i++) {
DB = 0;
for(j = 1; j< m+1; j++) {
i1 = DA[t[j-1]];
j1 = DB;
cost = ((s[i-1]==t[j-1])?0:1);
if(cost==0) DB = j;
d(i+1,j+1) =
min4(d(i,j)+cost,
d(i+1,j) + 1,
d(i,j+1)+1,
d(i1,j1) + (i-i1-1) + 1 + (j-j1-1));
}
DA[s[i-1]] = i;
dprint(dd,n,m);
}
cost = d(n+1,m+1);
free(dd);
return cost;
}
Here is my C++ version of this algorithm:
int damerau_levenshtein_distance(std::string p_string1, std::string p_string2)
{
int l_string_length1 = p_string1.length();
int l_string_length2 = p_string2.length();
int d[l_string_length1+1][l_string_length2+1];
int i;
int j;
int l_cost;
for (i = 0;i <= l_string_length1;i++)
{
d[i][0] = i;
}
for(j = 0; j<= l_string_length2; j++)
{
d[0][j] = j;
}
for (i = 1;i <= l_string_length1;i++)
{
for(j = 1; j<= l_string_length2; j++)
{
if( p_string1[i-1] == p_string2[j-1] )
{
l_cost = 0;
}
else
{
l_cost = 1;
}
d[i][j] = std::min(
d[i-1][j] + 1, // delete
std::min(d[i][j-1] + 1, // insert
d[i-1][j-1] + l_cost) // substitution
);
if( (i > 1) &&
(j > 1) &&
(p_string1[i-1] == p_string2[j-2]) &&
(p_string1[i-2] == p_string2[j-1])
)
{
d[i][j] = std::min(
d[i][j],
d[i-2][j-2] + l_cost // transposition
);
}
}
}
return d[l_string_length1][l_string_length2];
}