Return an array from a function

Jun 9, 2014 at 6:20pm
I'm not great with C++, I'm more of a VB.Net guy. However I am trying to start programming more with C++. What I'm currently trying to do is return an array of string arrays. In VB.Net I would write the function like this:
1
2
3
Private Function LoadClasses() As List(Of List(Of String))
    'Yada Yada
End Function 


So my thought process is something like this:

1
2
3
4
string LoadClasses()[]
{

}


However, whenever I try to debug and run the code(using CodeLite 6.0 by the way), I receive this error:
'LoadClasses' declared as function returning an array


How should I structure my function?

For what it's worth, this is my full function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
string LoadClasses()[]
{
	try
	{
		string keywords[] = {"keyword", "global", "local", "as", "bool", "decimal", "number", "text"};
		string operators[] = {"operator", "=", "\+", "-", "\*", "\/", "\^"};
		string boolean[] = {"bool", "true", "false"}
		string number[] = {"number", "\d"}
		string decimal[] = {"decimal", "\d+(\.\d)?"}
		string whitespace[] = {"whitespace", "\s"}
		string identifier[] = {"identifier", "[a-zA-Z_][a-zA-Z_0-9]*"}
		
		return = {keywords, operators, boolean, number, decimal, whitespace, identifier}
	}
	catch
	{
		return {}
	}
}
Jun 9, 2014 at 7:42pm
I've figured out that you are unable to return an array from a function, rather you return a pointer(?) of an array. I've adjusted my code to this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
string* LoadClasses()
{
	try
	{
		string keywords[] = {"keyword", "global", "local", "as", "bool", "decimal", "number", "text"};
		string operators[] = {"operator", "=", "\\+", "-", "\\*", "\\/", "\\^"};
		string boolean[] = {"bool", "true", "false"};
		string number[] = {"number", "\\d"};
		string decimal[] = {"decimal", "\\d+(\\.\\d)?"};
		string whitespace[] = {"whitespace", "\\s"};
		string identifier[] = {"identifier", "[a-zA-Z_][a-zA-Z_0-9]*"};
		
		return = {keywords, operators, boolean, number, decimal, whitespace, identifier};
	}
	catch
	{
		return {};
	}
}


However, now I receive a bunch of errors:

These two after my first return
expected primary-expression before '=' token
extended initializer lists only available with -std=C==11 or -std=gnu++11


I receive these 3 after my curly bracket after the catch:
expected '(' before '{' token
expected type-specifier token before '{' token
expected ')' before '{' token'


I receive this after I return an empty array:
extended initializer lists only available with -std=C==11 or -std=gnu++11


And this one after my last curly bracket of my function:
control reaches end of non-void function [-Wreturn-type]


Edit - I realized that I had an '=' sign after my return statement. I removed that I get the same error as if I return an empty statement.
Last edited on Jun 9, 2014 at 8:06pm
Jun 9, 2014 at 8:09pm
Rather than using pointers and risking memory leaks in your program, using vectors is recommended. The vector object will handle the freeing of any memory allocated internally.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <vector>
...

std::vector<std::vector<std::string>> LoadClasses() {
    
    std::vector<std::string> keywords = {"keyword:", "global", "local", "as", "bool", "decimal", "number", "text"};
    std::vector<std::string> operators = {"operator:", "=", "\\+", "-", "\\*", "\\/", "\\^"};
    std::vector<std::string> boolean = {"bool:", "true", "false"};
    std::vector<std::string> number = {"number:", "\\d"};
    std::vector<std::string> decimal = {"decimal:", "\\d+(\\.\\d)?"};
    std::vector<std::string> whitespace = {"whitespace:", "\\s"};
    std::vector<std::string> identifier = {"identifier:", "[a-zA-Z_][a-zA-Z_0-9]*"};
    
    return std::vector<std::vector<std::string>> /*Notice same type as function type */
    {
        keywords, operators, boolean, number, decimal, whitespace, identifier
    };
}


http://coliru.stacked-crooked.com/a/29ef741925265d7c
Last edited on Jun 9, 2014 at 8:09pm
Jun 9, 2014 at 8:33pm
Whenever I try the example in which you provide, I receive an error stating:
C++98 '*' must be initialized by constructor, not by '{...}'

after every vector declaration. I also receive this error after the return:
' should be '> >' within a nested template argument list
ended initializer list only available with -std=C++11 or -std=gnu++11
Jun 9, 2014 at 8:49pm
That is because the code I provided is only compatible with the latest c++11, whereas you are compiling it with c++98 standard. So if you want to compile that code, you have to supply the -std=c++11 option to the compiler and make sure the compiler the compiler supports this as well. I believe gcc 4.7 is the minimum version needed
Jun 9, 2014 at 9:13pm
closed account (j3Rz8vqX)
As Smac suggested, you can use a vector of vectors.
Using c++98 regulations, you would have to push every data for each vector, as demonstrated above.

A work around (demonstrating vector):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <vector>

std::vector<std::vector<std::string> > LoadClasses() {

    std::string keywords[] = {"keyword:", "global", "local", "as", "bool", "decimal", "number", "text"};
    std::string operators[] = {"operator:", "=", "\\+", "-", "\\*", "\\/", "\\^"};
    std::string boolean[] = {"bool:", "true", "false"};
    std::string number[] = {"number:", "\\d"};
    std::string decimal[] = {"decimal:", "\\d+(\\.\\d)?"};
    std::string whitespace[] = {"whitespace:", "\\s"};
    std::string identifier[] = {"identifier:", "[a-zA-Z_][a-zA-Z_0-9]*"};

    const std::string *ptr[] = {keywords,operators,boolean,number,decimal,whitespace,identifier};
    const int size[] = {8,7,3,2,2,2,2};

    std::vector<std::vector<std::string> > t_vects;

    for(int i = 0; i < 7; ++i){
        std::vector<std::string> t_str;
        for(int j = 0; j < size[i];++j)
            t_str.push_back(ptr[i][j]);
        t_vects.push_back(t_str);
    }
    return t_vects;
}
int main()
{
    std::vector<std::vector<std::string> > vect;
    vect = LoadClasses();
    for(int i=0;i<vect.size();++i)
        for(int j=0;j<vect[i].size();++j)
            std::cout<<vect[i][j]<<std::endl;
    std::cout<<"Console exit >> Press enter: ";
    std::cin.get();
    return 0;
}
keyword:
global
local
as
bool
decimal
number
text
operator:
=
\+
-
\*
\/
\^
bool:
true
false
number:
\d
decimal:
\d+(\.\d)?
whitespace:
\s
identifier:
[a-zA-Z_][a-zA-Z_0-9]*
Console exit >> Press enter:

Another work around (demonstrating array):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
std::string** aExample(int *&n){
    static std::string keywords[] = {"keyword:", "global", "local", "as", "bool", "decimal", "number", "text"};
    static std::string operators[] = {"operator:", "=", "\\+", "-", "\\*", "\\/", "\\^"};
    static std::string boolean[] = {"bool:", "true", "false"};
    static std::string number[] = {"number:", "\\d"};
    static std::string decimal[] = {"decimal:", "\\d+(\\.\\d)?"};
    static std::string whitespace[] = {"whitespace:", "\\s"};
    static std::string identifier[] = {"identifier:", "[a-zA-Z_][a-zA-Z_0-9]*"};
    static int t[] = {8,7,3,2,2,2,2};

    n = t;
    static std::string *str[] = {keywords, operators, boolean, number, decimal, whitespace, identifier};
    return str;
}
int main()
{
    int *size;
    std::string **str = aExample(size);
    for(int i=0;i<7;++i)
        for(int j=0;j<size[i];++j)
            std::cout<<str[i][j]<<std::endl;
    std::cout<<"Console exit >> Press enter: ";
    std::cin.get();
    return 0;
}
keyword:
global
local
as
bool
decimal
number
text
operator:
=
\+
-
\*
\/
\^
bool:
true
false
number:
\d
decimal:
\d+(\.\d)?
whitespace:
\s
identifier:
[a-zA-Z_][a-zA-Z_0-9]*
Console exit >> Press enter:

With c++98
Last edited on Jun 9, 2014 at 10:26pm
Jun 9, 2014 at 10:23pm
It would seem you'd want a vector of vectors, or array of arrays.


Yep. I'm converting a lexical analyzer project that I did in VB.Net to C++. Currently with my VB.Net project, the slow down is to much after about 150 lines of code.

That is because the code I provided is only compatible with the latest c++11, whereas you are compiling it with c++98 standard. So if you want to compile that code, you have to supply the -std=c++11 option to the compiler and make sure the compiler the compiler supports this as well. I believe gcc 4.7 is the minimum version needed


Do you have any idea of how to do that with CodeLite 6.0 or at least know of some resources out there that I can refer to?
Jun 9, 2014 at 10:33pm
http://codelite.org/LiteEditor/ReleaseNotesCodeLite60

CodeLite 6.0 seems to support various compilers. You have to get a suitable one and configure CodeLite to pass appropriate options.
Jun 9, 2014 at 10:46pm
Alright, thank y'all so much.
Topic archived. No new replies allowed.