convert std:: vector of strings/doubles to arrays

P

puzzlecracker

I am using matheval library. Its functions take c-style parameters,
for example:

#include<matheval.h>

char * evaluator_evaluate(void * evaluator, int count, char
**names, double *values);

In my case, I want to convert std::vector of names and std::vector of
values to char ** and double *

Also, every name correspond to a unique value, and there could be
repetitions. What is the best way to arrange names and values
elegantly in terms of data structures? For now, I use vectors, and
both contains repetitions.

Please keep in mind that order of names and values matters and should
match.

Thanks
 
Z

ZikO

puzzlecracker said:
In my case, I want to convert std::vector of names and std::vector of
values to char ** and double *
Please keep in mind that order of names and values matters and should
match.

Thanks

Is it as simple? Or I did not understand something!
**names is almost the same as *names[] and *values is almost the same as
values[]. The little difference is the table / array a pointer
containing the address is a const pointer u cant "move" it

double * const values[] = {1.5, 3, 4.5};

so basically the program would be as below:

#include <iostream>
#include <vector>

using namespace std;

int main(int argc, char *argv[])
{
vector<string> v_str;
vector<double> v_dbl;
v_str.push_back("aaa");
v_str.push_back("bbb");
v_str.push_back("ccc");
v_str.push_back("ddd");
v_dbl.push_back(1.5);
v_dbl.push_back(3.0);
v_dbl.push_back(4.5);

// definition of arrays and filling them with vectors val
char* names[v_str.size()];
double values[v_dbl.size()];
for(size_t i=0; i<v_str.size(); ++i) {
// const_cast<double*> removes const given by c_str()
// as c_str() returns const values:
// const char* c_str();
// either u define names[] with const or keep
// const_cast<double*>() here.
names = const_cast<char*>(v_str.c_str());
}
for(size_t i=0; i<v_dbl.size(); ++i) {
values = v_dbl;
}


// end here is only checking that everything works fine
for(size_t i=0; i<v_str.size(); ++i) {
cout << names << endl;
}
for(size_t i=0; i<v_dbl.size(); ++i) {
cout << values << endl;
}

return 0;
}
 
Z

ZikO

puzzlecracker said:
> In my case, I want to convert std::vector of names and std::vector of
> values to char ** and double *
> Please keep in mind that order of names and values matters and should
> match.
>
> Thanks

Is it as simple? Or I did not understand something!
**names is almost the same as *names[] and *values is almost the same as
values[]. The little difference is the table / array a pointer
containing the address is a const pointer u cant "move" it

double * const values[] = {1.5, 3, 4.5};

so basically the program would be as below:

#include <iostream>
#include <vector>

using namespace std;

int main(int argc, char *argv[])
{
vector<string> v_str;
vector<double> v_dbl;
v_str.push_back("aaa");
v_str.push_back("bbb");
v_str.push_back("ccc");
v_str.push_back("ddd");
v_dbl.push_back(1.5);
v_dbl.push_back(3.0);
v_dbl.push_back(4.5);

// definition of arrays and filling them with vectors val
char* names[v_str.size()];
double values[v_dbl.size()];
for(size_t i=0; i<v_str.size(); ++i) {
// const_cast<double*> removes const given by c_str()
// either u define names[] with const or keep
// const_cast<double*>() here in order for the code to work.
names = const_cast<char*>(v_str.c_str());
}
for(size_t i=0; i<v_dbl.size(); ++i) {
values = v_dbl;
}


// end here is only checking that everything works fine
for(size_t i=0; i<v_str.size(); ++i) {
cout << names << endl;
}
for(size_t i=0; i<v_dbl.size(); ++i) {
cout << values << endl;
}

return 0;
}
 
Z

ZikO

ZikO said:
double * const values[] = {1.5, 3, 4.5};

I apologize for this line, it is completely rubbish and I really don't
know how I could write something like that !!! Must have been too late :p

It would work if I had three variables:

double a = 1.5;
double b = 3.0;
double c = 4.5;

and

double * const values[] = {&a, &b, &c};

However, regarding your problem, values[] is simply speaking a pointer
which you can't use operand ++ on, so u cant use values++. Table / array
is a pointer like below:

double* const value;

which contains the address of the table already. This is what I meant
yesterday :p.
 
S

SG

int main(int argc, char *argv[])
{
     vector<string> v_str;
     vector<double> v_dbl;
     v_str.push_back("aaa");
[...]

     v_dbl.push_back(4.5);
     // definition of arrays and filling them with vectors val
     char* names[v_str.size()];
     double values[v_dbl.size()];

This is not valid C++. The array dimensions need to be constant
expressions. However, in your case v_str.size() is not a constant
compile-time expression but a runtime expression. You should consider
using a vector<char*> just like Giuliano Bertoletti. Also, copying
the doubles is not necessary. "&v_dbl[0]" already works as pointer
(double*). std::vector guarantees a consecutive array-like layout.


Cheers!
SG
 
Z

ZikO

SG said:
int main(int argc, char *argv[])
{
vector<string> v_str;
vector<double> v_dbl;
v_str.push_back("aaa");
[...]

v_dbl.push_back(4.5);
// definition of arrays and filling them with vectors val
char* names[v_str.size()];
double values[v_dbl.size()];

This is not valid C++. The array dimensions need to be constant
expressions. However, in your case v_str.size() is not a constant
compile-time expression but a runtime expression.

Cheers SG for that but I am honestly confused with that :/

I am just wondering this. If vector object can return a number at any
point of program by size() method, isn't done by intermediate temporary
object which is automatically constant? If it's constant, can't it be
use here?
I would buy that because at that moment size() = 3, of course it might
be different at any other point but at that exact point it's 3. It would
be different later on. But it would be different point :p.

I can even define constants right before char* names[] and double
values[] = ...

const size_t v_str_size = v_str.size();
const size_t v_dbl_size = v_dbl.size();

and use them ...
and program can still work. I am trying just clarify things as I am not
sure about them.

Also, copying
the doubles is not necessary. "&v_dbl[0]" already works as pointer
(double*). std::vector guarantees a consecutive array-like layout.

Please, can u provide a little example with this? Thanks

Regards
ZikO
 
S

SG

ZikO said:
I am just wondering this. If vector object can return a number at any
point of program by size() method, isn't done by intermediate temporary
object which is automatically constant? If it's constant, can't it be
use here?

See http://msdn.microsoft.com/en-us/library/3ffb821x.aspx

"constant expressions" are expressions that evaluate to some constant
value *at compile-time*. std::vector::size() is called at run-time.
So, "v_dbl.size()" is not a constant expression.

Other examples:

int func();

const int foo = 23; // foo is declared const AND initialized with
double myarray[foo]; // a const expression. Everything is fine.

const int bar = func(); // bar is declared const BUT dynamically
double myarray[bar]; // initialized => not valid C++

If you use the GCC C++ compiler make sure you use the switches "-Wall -
pedantic". The last one (pedantic) disables any extensions (like VLAs,
variable length arrays) that are not part of the official C++.
I would buy that because at that moment size() = 3, of course it might
be different at any other point but at that exact point it's 3. It would
be different later on. But it would be different point :p.

The compiler doesn't treat a vector in any special way.
std::vector::size could return a randomly chosen number for example.
The compiler doesn't know about how vector is supposed to behave. I
suppose it will be possible in future C++:

constexpr vector<string> v_str = {"blah", "foo", "bar"};
constexpr int s = v_str.size(); // <-- *may* work in C++0x

(btw: "constexpr" requires the initializer to be a constant
expression. So, this would not compile in case v_str.size() wasn't a
constant expression)


Cheers!
SG
 
S

SG

I suppose it will be possible in future C++:

  constexpr vector<string> v_str = {"blah", "foo", "bar"};
  constexpr int s = v_str.size(); // <-- *may* work in C++0x

I just veryfied that std::vector (as well as other containers) won't
have constexpr constructors. So,

constexpr vector<string> v_str = {"blah", "foo", "bar"};

would fail to compile even in C++0x. This it not surprising if you
think about it. Memory allocation can't be part of a constexpr
constructor or function. Such containers always have to be
initialized at runtime (unless they are going to be empty). ;-)

Cheers!
SG
 
Z

ZikO

I've got the point SG, that's explained me the problem. BTW thanks for
this two options in the g++ command -Wall and -pedantic. They are great.
I have just found that one the variables was not used in my program.

Cheers!
 
J

James Kanze

You may also find -ansi useful.

Or -std=c++98. (-ansi resolves to this for C++ sources. But it
may resolve to something else in the future, e.g. -std=c++03.
With -std=c++98, you not only know that you're getting a
"standard" version, you know which one.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top