1

I have known java for a while and I was trying to translate a java program i wrote to c++ but the copy function gives an odd result:

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

long gcd2(long a, long b) {
        if ( a == 0 )
            return b;
        return gcd2(b%a,a);
}

long gcd(long nums[]) {
    long ans = nums[0];
    int len = sizeof(nums);
    for (int i = 1; i < len; i++)
        ans = gcd2( nums[i] , ans );
    return ans;
}

string com(string s) {
    s = s+",";
    return (","+s);
}

void printa(long array[]) {
    for (int i = 0 ; i < sizeof(array); i++)
        cout << array[i] << ", ";
    cout << "\n";
}

int main()
{
    int length;
    cin >> length;
    long input[length];
    for (int i = 0; i < length; i++)
        cin >> input[i];

    string possible = "";

    int ans = 0;
    for (int a = 0; a < length; a++) {
        for (int b = length; b > a; b--) {
            long arr[b-a];

            std::copy(input+a,input+b,arr);
            printa(arr);

            long gcdans = gcd(arr);
            if (possible.find( com(gcdans+"") ) == -1 ) {
                possible += com(gcdans+"");
                ans++;
            }
        }
    }
    cout << (ans);

    return 0;
}

I give it the input of:

4

9 6 2 4

and it returns:

9, 6, 2, 4, 140725969483488, 4197851, 9, 6, 9, 6, 2, 4197851, 9, 6, 2, 4, 9, 6, 2, 4197851, 9, 6, 2, 4, 9, 4197851, 9, 6, 2, 4, 140725969483488, 4197766, 6, 2, 4, 4197851, 9, 6, 2, 4, 6, 2, 4, 4197851, 9, 6, 2, 4, 6, 4197851, 9, 6, 2, 4, 140725969483488, 4197766, 2, 4, 6, 4197851, 9, 6, 2, 4, 2, 4197851, 9, 6, 2, 4, 140725969483488, 4197766, 4, 4197851, 9, 6, 2, 4, 140725969483488, 4197766, 1 the number at the very end is what i want the program to output at the end, all the numbers above are me test printing the array to see its contents. Basically I am trying to copy a range of the array(for example (2,3,4) from (1,2,3,4,5,6)) But it gives weird numbers like 140725969483488 and 4197766 when the only numbers I input are 9 6 2 4

Eziz Durdyyev
  • 1,110
  • 2
  • 16
  • 34
  • When you declare an array in the stack, it must be given a CONST size. Using a variable to initialize the length of an array will be met with undefined behavior. Use new if you want dynamically sized arrays. – JGroven Feb 26 '18 at 23:03
  • 1
    That `long input[length];` is non-standard. Use `std::vector input;` – Jive Dadson Feb 26 '18 at 23:04
  • sizeof(array) returns length of the array in bytes, not the number of elements in array. – SolutionMill Feb 26 '18 at 23:05
  • 1
    I guess no one has yet said **"welcome to Stack Overflow".** Please take a look at our [intro pages](https://stackoverflow.com/help), with special attention to the one on [minimal complete examples](https://stackoverflow.com/help/mcve). Basically, you should strip your code down to the simplest example which reproduces the error. Most of the code above has nothing to do with the copying of part of an array. – Beta Feb 26 '18 at 23:06
  • @George Please see https://stackoverflow.com/questions/15013077/arrayn-vs-array10-initializing-array-with-variable-vs-real-number I admit that it says "not legal" rather than "undefined behavior". – JGroven Feb 26 '18 at 23:08
  • 1
    Change all the non-standard dynamic arrays to `std::vector` and use the `size()` method to get its length. You'll find the problem. Edit: SolutionMill may have given it away. I'm not sure, because I do not have a compiler that accepts the non-standard syntax. Make the change to std::vector in any case. – Jive Dadson Feb 26 '18 at 23:19
  • `void printa(long array[])` this doesn't do what you think it does. Same here `long gcd(long nums[] )` – Killzone Kid Feb 26 '18 at 23:20
  • @George it's ill-formed (so the compiler must complain, and if the compiler does generate an executable, then that executable has completely undefined behaviour) – M.M Feb 26 '18 at 23:21
  • @M.M. I think that's a non-standard extension that some compiler(s) implement. Yous guys, let it go. – Jive Dadson Feb 26 '18 at 23:22

1 Answers1

2

Variable length arrays is a C++ extension, not standard C++. If your compiler will allow them, then OK. However standard C++ would use an std::vector container which is dynamically sized at runtime, meaning you can initialise them with any size or numbers at runtime, and add anything you want at runtime.

Also note when passing an array in C++ to functions which take an array argument always (with the exception of explicitly declared sized reference to an array) gets passed as a pointer, so you can't know the size of the array once passed as an argument. So this:

void printa(long array[])
{
    for (int i = 0 ; i < sizeof(array); i++) {}
    // At this point of the code the sizeof(array) will return the size of
    // a pointer, usually 4 or 8 bytes.
    // It's a quirk that this happens, and is a holdover from C.
}

By taking an argument of std::vector you can know the size of the array. You can take the argument by value or by reference or pointer.

void printa(const std::vector<long>& array)
{
    for (int i = 0 ; i < array.size(); i++)
     {
        cout << array[i] << ", ";
        cout << "\n";
     }
}

This is the better way to do it. If you want to use a C array or raw array the way you did, you will have to pass both the array and the size of the array as separate arguments.

Also, about the variable length array extension feature, I'm not sure whether it is reliable or not because I've never used the extension. Again, standard C++ requires that size of arrays are constant values, (known at compile time). Edit: actually (known at compile-time) is a bad description because:

int main()
{
    int num = 6;
    int myarray[num]; // In standard C++ this won't compile
    //but
    const int num = 6;
    int myarray[num]; // Will
}

And one last thing, as SolutionMill pointed out, even if the sizeof(array) does give the right size and not the size of a pointer, it is the size given in bytes, not the number of elements, which was not you were wanting in:

for (int i = 0 ; i < sizeof(array); i++)

If the array is of 2 elements of 32 bit int, then the sizeof() operator will return size 8. A common but by no means pretty way to get the number of elements in an array is something like sizeof(array) / sizeof(array[0])

Zebrafish
  • 11,682
  • 3
  • 43
  • 119