-4

I am trying to obtain a long number, count how many digits it is, then take the 2nd last digit of that number and multiply it by 2, then iterate through the rest of the number multiplying each 2nd and then adding it to an array. It is the credit card problem set from cs50 if you guys know what I'm talking about.

When I make the program it throws back this error:

error: format specifies type 'long' but the argument has type '<dependent type>' [-Werror,-Wformat]
credit.c:22:21: error: use of undeclared identifier 'array'
    printf("%ld\n", array);
                    ^
credit.c:40:8: error: incompatible pointer to integer conversion returning 'long [nDigits]' from a function with result type 'long' [-Werror,-Wint-conversion]
return array;
       ^~~~~
3 errors generated.
make: *** [credit] Error 1

Code:

#include <cs50.h>
#include <stdio.h>
#include <math.h>

long find_2ndlast_nums(long x);

int main(void)
{
    long n;
    long nDigits;
    do
    {
        n = get_long_long("Please enter your credit card number:\n");
        nDigits = floor(log10(labs(n))) + 1;
    }
    while (nDigits < 13 || nDigits > 16);

    find_2ndlast_nums(n);

    printf("%ld\n", array);
}

long find_2ndlast_nums(long x)
{
    long nDigits = floor(log10(labs(x))) + 1;
    long array[nDigits];

    for (int y = 1; y < nDigits; y += 2)
    {
        x = (fmod((floor(x / 10 ^ y)), 10)) * 2;
        array[nDigits - y] = x;
    }
    return array;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
R_C
  • 333
  • 2
  • 6
  • 17
  • This has been asked many times, you can't return an array from a function. You need to use `malloc()` or to pass the array to the function as a parameter, modify it in the function if needed. – Iharob Al Asimi Jul 31 '17 at 04:02
  • 1
    Your function is declared to return a `long` and you try to return a `long[nDigits]`. Memory issues aside, why did you think this would work? – ApproachingDarknessFish Jul 31 '17 at 04:05
  • In `long find_2ndlast_nums(long x)`, do you understand what the first `long` means? – David Schwartz Jul 31 '17 at 04:07
  • Note: rather than `nDigits = ...` with its problem with `n==0` and impression of `log10()` calculation, code could use `while (nDigits < 10000000000000 || nDigits >= 10000000000000000);` – chux - Reinstate Monica Jul 31 '17 at 04:18
  • Program you have written is not going to work... From quick look I can find that the first error is that your variable 'array' is in the function find_2ndlast_nums() and you are trying to access it outside of that function, second is your return type of find_2ndlast_nums() is long, but you are trying to return an array. – deepakl Jul 31 '17 at 04:21
  • @IharobAlAsimi That is simply incorrect. I can very well return a pointer to static array declared inside a function. – Tanveer Badar Jul 31 '17 at 18:43
  • @TanveerBadar You mean "*strictly incorrect*". Yes you can, but when you are returning a local array from a function it's very unlikely that you know what a *static* array is. – Iharob Al Asimi Aug 01 '17 at 02:30

1 Answers1

4

There are two problems here:

  1. When you declare an array in C with type[count], it's allocated on the stack. As soon as your function returns, everything on the current stack frame will become invalid, so you can't return a stack-allocated array like this.

  2. Even if you could return that array, you declared the function as returning a long, not a pointer to long, so the signature's incorrect.

What I'd do is to allocate memory for the array on the heap, using malloc. Declare the function as returning a pointer, and then return the pointer to the array. Unfortunately, the calling function will have to remember to free the pointer afterward or you'll have a memory leak, but this is just one of the things that goes with the territory when you're using C.

So, something like this:

long *myFunc() {
    long *array = malloc(count * sizeof(long));

    // populate the array

    return array;
}

And in the client:

long *array = myFunc();

// do something with array, and when you're done:

free(array);

Alternatively, if you can know ahead of time what the maximum size of the array will be, you can have the function populate an already-allocated array. This has the advantage of making the code cleaner by letting your malloc and free occur in the same scope. Also, if the array doesn't need to leave the calling function, the calling function can allocate the array on the stack and pass it in, thus obviating the need for malloc and free altogether.

void populateArray(long *array, size_t arraySize) {
    // populate array. Don't write more than arraySize objects
    // or you'll cause a buffer overflow.
}
Charles Srstka
  • 16,665
  • 3
  • 34
  • 60