1

I need to use participants a[quantity] in the function dataIn. I tried making

void dataIn(int quantity, participants a[quantity]);

but that didnt work. Btw quantity is being taken from a text file.

void dataIn(int quantity);

int main()
{
    ifstream in("duomenys.txt");

    int quantity;

    in >> quantity;

    participants a[quantity];

    dataIn(quantity);


    return 0;
}
1
  • Keep on reading the tutorial you are learning from. It will introduce containers, which a much more elegant way of doing what you want. Commented Sep 15, 2019 at 9:26

2 Answers 2

1

The signature of your function is

void dataIn(int quantity, participants a[quantity])

At very first, C++ doesn't allow to use function parameters outside the function body, so this is the reason why it won't compile.

Apart from, this signature actually is equivalent to

void dataIn(int quantity, participants*)
// legal variant of, exactly equivalent(!),
// not re-using quantity parameter either (-> compiles):
void dataIn(int quantity, participants[])

Raw arrays are always passed to functions as pointer to their first element, we say: an array decays to a pointer. Note, though, that this doesn't apply for further dimensions, i. e.

void f(int[whatever][SomeCompileTimeConstant])

remains equivalent to

void f(int(*)[SomeCompileTimeConstant])

Back to the original function: Note that it accepts two parameters, so you need to pass two as well:

participants a[quantity];
dataIn(quantity, a);
//               ^

Note the array decaying to pointer, as mentioned already!

Additionally be aware that above is invalid C++:

int main()
{
     participants a[quantity];
}

You are defining a VLA (variable length array), but that is only valid in C, not in C++. However, as many C++ compilers can translate C as well, they provide VLA for C++ as an extension. And that's the problem, no guarantee that all compilers do so, so your code is not portable.

So if you need dynamically sized arrays, switch over to std::vector*:

void dataIn(size_t quantity, std::vector<participant>& v)`

Note that I changed type of quantity parameter as well: Appropriate type for passing array lengths is size_t, not int.

std::vector<participant> a;
a.reserve(quantity); // optimisation: prevents re-allocations
dataIn(quantity, participants);

Actually, with std::vector you can have a much cleaner interface:

std::vector<participant> dataIn( )
//                              ^ no parameters needed at all!
{
    ifstream in("...");
    size_t quantity;
    in >> quantity;
    // TODO: check stream state, and possibly maximum for quantity (file validity!)

    std::vector<participant> a;
    a.reserve(quantity);
    while(quantity--) { ... }

    return a;
}

As you see, all relevant file operations now are placed into one single function (dataIn) and not distributed all over your programme. Especially, the file stream itself is in scope of this function as well and will be closed automatically on leaving. Be aware that with return value optimisation, the vector will be immediately constructed at the target location, so there even isn't any copying or moving involved...


* Even if you need fixed size arrays, std::array is a more modern and better alternative, it just wraps around a raw array, but behaves like any other ordinary object, so nothing of all that decaying to pointer stuff, additionally it comes with a more elaborate interface, e. g. a size() member, so no need to rely on the 'good old' sizeof(array)/sizeof(*array) trick either.

Sign up to request clarification or add additional context in comments.

Comments

0

You can't just access a function parameter like that.

In the "participants a[quantity]", the compiler don't know about "quantity". So the "quantity" variable must be known.

Like :

void dataIn(int quantity, participants a[15]);

If you don't know the size, send it as a pointer.

void dataIn(int quantity, participants *a);

And parse it thanks to the "quantity" variable.

void dataIn(int quantity, participants *a)
{
   for (int i = 0; i < quantity; i++) {
       //Do something with the array of struct...
   }
}

5 Comments

That's not correct: participants*, participants[], participants[someVariable], participants[SomeCompileTimeConstant] are all equivalent for function parameters (so one could write participants[quantity], but that would only serve for denoting what the function actually expects) ; if a size is provided, it simply is ignored, so one could use anything (even non-matching sizes). That applies only for outer-most dimenstion, though, for further dimensions (int[][10][12]), size indeed needs to be supplied as compile time constant (unless relying on VLA compiler extension).
Am I missing something ? If I try "void func(int quantity, int array[quantity])" and quantity is not a const variable, it don't compile. Are you sure you can tell a function a variable size for an array ?
Doesn't compile, yes, but for a different reason: GCC: 'error: use of parameter outside function body'. You could try int n; void f(int a[n]) { } instead. Compiles fine with e. g. -std=c++17, but as well with -std=c++98 (GCC!), all of which disabling VLA extension. OK, the denoting part of my comment, as is, is not correct, but everything else remains...
You could try that as well: void f(int a[10]) { } void g() { int a[12]; f(a); }, absolutely fine... Try printing sizeof(a) inside f, what will you get? Matter changes pretty much if you use reference to array, though: void h(int(&a)[7]), now you'd get expected size and length would need to match in calling function.
Ah, about 'compiles fine': Be aware that's no true reference! A compiler might falsely accept illegal code, i. e. have a bug. True reference is only one to the standard – will look up the relevant passage, if you insist on...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.