472,958 Members | 2,136 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,958 software developers and data experts.

std::map<int, std::string[2]> problems

First of all, forgive me if this is the wrong place to ask this question,
if it's a stupid question (it's my second week with C++), or if this is
answered some place else (I've searched but not found anything).

Here's the problem, I have two sets of files, the name of a file contains a
number which is unique for each set but it's possible (even probable) that
two files in different sets have the same numbers. I want to store these
file-names in such a way that I can retrieve them by their number. For this
I thought I'd use a map with the number as the key an an array of strings
to store the file-names, however I've run into trouble when trying to use
this solution.

When adding the file-names to the map I don't know if a filename from the
other set already exists, but given examples at:
http://www.fredosaurus.com/notes-cpp.../map/pair.html
http://www.fredosaurus.com/notes-cpp...-wordfreq.html
it seams like entries not found are created and if they are found I can
modify them.
Here's code that displays my problem:

#include <map>
#include <string>
#include <vector>

using std::map;
using std::string;
using std::vector;

class Files
{
public:
void nextFile(string*, string*);
void open(vector<string>*, int);

private:
int getNumber(string); // Gets the number from the filename

map<int, string[2]> fileSets;
map<int, string[2]>::iterator iter;
};

// Return the next pair of files
// I've removed a bit of code to keep it short,
// among other things checks for fileSets.end().
void Files::nextFile(string* file1, string* file2)
{
iter++;
// Return the pointers to the filenames
file1 = &(iter->second[0]);
file2 = &(iter->second[1]);
}
// Add files to the sets
// files is a vector with the filenames to be added.
// setNr is the number of the set the files should be
// added to, can be 0 or 1.
void Files::open(vector<string>* files, int setNr)
{
if(setNr < 2)
{
for(int i = 0; i < files->size(); i++)
{
// Add the file to the correct set
int fileNumber = getNumber((*files)[i]);
(fileSets[fileNumber])[setNr] = (*files)[i];
// This does not work ^^^^^^^
}
}

// Set the iterator
iter = fileSets.begin();
}

------------------------------------------

When compiling on gcc 3.3 I get the following:

/usr/include/c++/3.3.4/bits/stl_map.h: In member function `_Tp& std::map<_Key,
_Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = int, _Tp =
std::string[2], _Compare = std::less<int>, _Alloc =
std::allocator<std::pair<const int, std::string[2]> >]':
Files.cpp:46: instantiated from here
/usr/include/c++/3.3.4/bits/stl_map.h:319: error: ISO C++ forbids casting to an
array type `std::string[2]'

------------------------------------------
and I get similar results when using gcc 3.4. Obviously there's some problem
with the array but I can't figure out what and would appreciate a nudge in the
right direction, and since I'm still learning any other comment too.

PS:
It's not possible to get random access to a map if the key is not known
but if I have an (bidirectional) iterator pointing at some element in the
map, and know that the element I'm interested in is N elements from the one
the iterator is currently pointing at can I jump to that element by adding
N to the iterator, e.g. iter+=N ?

--
Erik Wikström
Jul 23 '05 #1
19 6067
Erik Wikström wrote:
First of all, forgive me if this is the wrong place to ask this question,
It's not. You're fine.
if it's a stupid question (it's my second week with C++), or if this is
answered some place else (I've searched but not found anything).
It may have been answered already, but sometimes it's rather hard to find.
[...]

map<int, string[2]> fileSets;
You simply can't do that. Arrays cannot be the stored data in a standard
container. If you need two strings there, either make a pair (std::pair)
or make your own struct.
[...]


V
Jul 23 '05 #2

"Erik Wikström" <er***********@telia.com> schrieb im Newsbeitrag
news:XO*******************@newsb.telia.net...
Here's the problem, I have two sets of files, the name of a file contains
a
number which is unique for each set but it's possible (even probable) that
two files in different sets have the same numbers. I want to store these
file-names in such a way that I can retrieve them by their number. For
this
I thought I'd use a map with the number as the key an an array of strings
to store the file-names, however I've run into trouble when trying to use
this solution.
As Victor already explained, you cannot use a C style array as the value
type of a standard container. But you could use an std:: vector instead.
However, as you describe your problem, you have two sets of files, not one
set of pairs of files. So I would suggest to use two instances of
std::map<int, std::string>, one for each set of files.
PS:
It's not possible to get random access to a map if the key is not known
but if I have an (bidirectional) iterator pointing at some element in the
map, and know that the element I'm interested in is N elements from the
one
the iterator is currently pointing at can I jump to that element by adding
N to the iterator, e.g. iter+=N ?


Have a look at std::advance.

HTH
Heinz
Jul 23 '05 #3
> map<int, string[2]> fileSets;

string[2] has no = operator and no < operator - that's the whole
problem.
-Gernot
Jul 23 '05 #4
Victor Bazarov wrote:
Erik Wikström wrote:
map<int, string[2]> fileSets;

You simply can't do that. Arrays cannot be the stored data
in a standard container. If you need two strings there,
either make a pair (std::pair)


But in the case in question, the array did not constitute
the "stored data". The "stored data" elements in the map
are actually of type std::pair<int, std::string[2]>.
What's wrong with that?
--
Cheers,
Robbie Hatley
Tustin, CA, USA
email: lonewolfintj at pacbell dot net
web: home dot pacbell dot net slant earnur slant

----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Jul 23 '05 #5
"Gernot Frisch" <Me@Privacy.net> wrote in message
news:3h************@individual.net...
map<int, string[2]> fileSets;


string[2] has no = operator and no < operator - that's the whole
problem.
-Gernot


The comparison in the original post was being done on type int,
which DOES have "=" and "<" operators. std::map contains elements
of type std::pair<key_type, value_type>. Only the key_type
needs to be "comparable", as i understand it.

For example, the following program compiles fine:

#include <iostream>
#include <string>
#include <map>
#include <utility>
using std::cout;
using std::endl;
using std::string;
using std::map;
using std::pair;
using std::make_pair;
int main(void)
{
string Splat[2] = {"apple", "peach"};
map<int, string[2]> fileSets;
fileSets.insert(make_pair<int, string[2]>(37, Splat));
return 0;
}

However, when I try to run it, I get a general protection fault.
What am I doing wrong? I don't think it has to do with the
non-comparibility of std::string[2] , though. GPF usually
means illegal memory usage somewhere. (Possibly a problem
with the copy semantics of std::string[2]?)
Puzzled,
Robbie Hatley
Tustin, CA, USA
email: lonewolfintj at pacbell dot net
web: home dot pacbell dot net slant earnur slant

----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Jul 23 '05 #6

"Robbie Hatley" <lonewolfintj at pacbell dot net> schrieb im
Newsbeitrag news:42**********@spool9-west.superfeed.net...
"Gernot Frisch" <Me@Privacy.net> wrote in message
news:3h************@individual.net...
> map<int, string[2]> fileSets;


string[2] has no = operator and no < operator - that's the whole
problem.
-Gernot


The comparison in the original post was being done on type int,
which DOES have "=" and "<" operators. std::map contains elements
of type std::pair<key_type, value_type>. Only the key_type
needs to be "comparable", as i understand it.

For example, the following program compiles fine:

#include <iostream>
#include <string>
#include <map>
#include <utility>
using std::cout;
using std::endl;
using std::string;
using std::map;
using std::pair;
using std::make_pair;
int main(void)
{
string Splat[2] = {"apple", "peach"};
map<int, string[2]> fileSets;
fileSets.insert(make_pair<int, string[2]>(37, Splat));
return 0;
}

However, when I try to run it, I get a general protection fault.
What am I doing wrong? I don't think it has to do with the
non-comparibility of std::string[2] , though. GPF usually
means illegal memory usage somewhere. (Possibly a problem
with the copy semantics of std::string[2]?)


The second argument must either have an = operator or an cctor - I'm
not sure, I think it't the = op, which string[2] does not offer.
Jul 23 '05 #7
Gernot Frisch wrote:
The second argument must either have an = operator or an cctor - I'm
not sure, I think it't the = op, which string[2] does not offer.


For each STL container holds that the value type must be assignable and copy
constructable (23.1.3).

But why does this code compile?

Mathias
Jul 23 '05 #8
I suspect that string[2] decays to a pointer to its first element.

Dan

Jul 23 '05 #9
Dan Cernat wrote:
I suspect that string[2] decays to a pointer to its first element.


Huh? Decays? Where?

Most likely it compiles in some situations because none of the member
function of the class template 'map' are used that require copying or
assigning of the value. As soon as you employ one of them, there will
be an error.

V
Jul 23 '05 #10
Well, actually, I tried the code on VC7.1 and it doesn't compile
(cannot create the pair because it cannot find the appropriate copy
constructor for the type string[2]).
I was thinking that it compiles because, in the process of construction
of the contained element of type string[2], it converts the array into
a pointer to its first element and it copies the pointer, hence the GPF
he gets.

Your explanation doesn't explain the GPF he gets.

Dan

Jul 23 '05 #11
Dan Cernat wrote:
[..]
Your explanation doesn't explain the GPF he gets.


No, it doesn't. It wasn't meant to. The code is not supposed
to compile. For all I know, he runs some other program that
gives him the GPF while the code posted never actually makes it
to the executable stage.

If he needs the GPF explained, he has to go to the newsgroup for
the particular compiler he uses (and that's not VC+ v6 or v7.1
since both rightfully refuse to compile the code) and ask there.

V
Jul 23 '05 #12
Victor Bazarov wrote:
Dan Cernat wrote:
[..]
Your explanation doesn't explain the GPF he gets.

No, it doesn't. It wasn't meant to. The code is not supposed
to compile.

Actually, it's undefined behavior. Speculating on whether it compiles
or does something useful when it runs is just silly.
Jul 23 '05 #13
Victor Bazarov wrote:
No, it doesn't. It wasn't meant to. The code is not supposed
to compile. For all I know, he runs some other program that
gives him the GPF while the code posted never actually makes it
to the executable stage.


The code compiles fine at least with gcc 3.3.5. And raises an exception
during runtime.

Mathias
Jul 23 '05 #14
> The code compiles fine at least with gcc 3.3.5. And raises an
exception
during runtime.


How 'bout gcc 3.4?
Jul 23 '05 #15
Regarding my test program that compiles but crashes:

#include <iostream>
#include <string>
#include <map>
#include <utility>
using std::cout;
using std::endl;
using std::string;
using std::map;
using std::pair;
using std::make_pair;
int main(void)
{
string Splat[2] = {"apple", "peach"};
map<int, string[2]> fileSets;
fileSets.insert(make_pair<int, string[2]>(37, Splat));
return 0;
}

The comments went:

Gernot Frisch:
The second argument must either have an = operator
or an cctor - I'm not sure, I think it't the = op,
which string[2] does not offer.
Mathias Waack: For each STL container holds that the value type must be
assignable and copy constructable (23.1.3).
But why does this code compile?
"Gernot Frisch": The code compiles fine at least with gcc 3.3.5. And raises an
exception
during runtime.
How 'bout gcc 3.4?

I'm using the djgpp port of Gnu gcc version 3.4.3
in Windows 2000 Professional DOS console.

I have all the warning flags turned on, too:
-Wall -Wextra -pedantic etc etc etc

But gcc gives no warnings or errors when compiling
the above program.

I can see now that y'all are right, the program is flawed to the
core because the list elements can't be copied. I'm pretty sure
gcc creates an implicit default copy constructor for the pairs,
but the ctor is going to make ptrs that point to God knows where,
hence the GPFs.

I think the following is more like what the OP wanted, and this
compiles and runs without error:

#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <utility>

using std::cout;
using std::endl;
using std::string;
using std::map;
using std::vector;
using std::pair;
using std::make_pair;

class Files
{
public:
void nextFile(string*, string*);
void open(vector<string>*, int);

//private: // make public for test
int getNumber(string); // Gets the number from the filename

//map<int, string[2]> fileSets; // NO!!!

map<int, pair<string,string> > fileSets; // YES!!!

map<int, pair<string,string> >::iterator iter;
};

int main(void)
{
Files MyFiles;
pair<string,string> Splat;

Splat = make_pair<string,string>("apple", "peach");
MyFiles.fileSets.insert(make_pair<int, pair<string,string> >(48, Splat));

Splat = make_pair<string,string>("cucumber", "dill");
MyFiles.fileSets.insert(make_pair<int, pair<string,string> >(23, Splat));

cout
<< "Map element 23 first string = "
<< MyFiles.fileSets[23].first
<< endl;

cout
<< "Map element 23 second string = "
<< MyFiles.fileSets[23].second
<< endl;

cout
<< "Map element 48 first string = "
<< MyFiles.fileSets[48].first
<< endl;

cout
<< "Map element 48 second string = "
<< MyFiles.fileSets[48].second
<< endl;

return 0;
}
--
Cheers,
Robbie Hatley
Tustin, CA, USA
email: lonewolfintj at pacbell dot net
web: home dot pacbell dot net slant earnur slant

----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Jul 23 '05 #16
Mathias Waack wrote:
The code compiles fine at least with gcc 3.3.5. And raises an exception
during runtime.

Mathias

GCC has an extension that allows array assignment. Standard
C++ arrays are crippled.
Jul 23 '05 #17
Ron Natalie wrote:
Mathias Waack wrote:
The code compiles fine at least with gcc 3.3.5. And raises an exception
during runtime.

Mathias

GCC has an extension that allows array assignment. Standard
C++ arrays are crippled.


cat t2.cpp; g++ -Wall -c t2.cpp
int main()
{
int s0[2];
int s1[2] = s0;
int s2[2];
s2 = s0;
}
t2.cpp: In function `int main()':
t2.cpp:4: error: invalid initializer
t2.cpp:6: error: ISO C++ forbids assignment of arrays
t2.cpp:4: warning: unused variable `int s1[2]'

Mathias
Jul 23 '05 #18
On 2005-06-13 23:41, Heinz Ozwirk wrote:
"Erik Wikström" <er***********@telia.com> schrieb im Newsbeitrag
news:XO*******************@newsb.telia.net...
Here's the problem, I have two sets of files, the name of a file contains
a
number which is unique for each set but it's possible (even probable) that
two files in different sets have the same numbers. I want to store these
file-names in such a way that I can retrieve them by their number. For
this
I thought I'd use a map with the number as the key an an array of strings
to store the file-names, however I've run into trouble when trying to use
this solution.


As Victor already explained, you cannot use a C style array as the value
type of a standard container. But you could use an std:: vector instead.
However, as you describe your problem, you have two sets of files, not one
set of pairs of files. So I would suggest to use two instances of
std::map<int, std::string>, one for each set of files.
PS:
It's not possible to get random access to a map if the key is not known
but if I have an (bidirectional) iterator pointing at some element in the
map, and know that the element I'm interested in is N elements from the
one
the iterator is currently pointing at can I jump to that element by adding
N to the iterator, e.g. iter+=N ?


Have a look at std::advance.


Thank you all for your answers, I went with std::pair as Victor said and it
works great.

--
Erik Wikström
Jul 23 '05 #19
> But in the case in question, the array did not constitute
the "stored data". The "stored data" elements in the map
are actually of type std::pair<int, std::string[2]>.
What's wrong with that?


The fact that the value element is an array : string[2]
You cannot have an C-style array as key or value or both, regardless as to
what the elements are.

Stephen Howe
Jul 23 '05 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: gipsy boy | last post by:
// -- using namespace std; map<string,string> formMap; list<string> formParams; for(list<string>::iterator fit = formParams.begin(); fit!=formParams.end(); fit++) { cout << "key=" << *fit;...
5
by: Peter Jansson | last post by:
Hello, I have the following code: std::map<int,std::set<std::string> > k; k="1234567890"; k="2345678901"; //... std::set<std::string> myMethod(std::map<int,std::set<std::string> > k)...
13
by: jstanforth | last post by:
This is probably a very obvious question, but I'm not clear on what operators need to be implemented for std::map.find() to work. For example, I have a class MyString that wraps std::string, and...
1
by: Maxwell | last post by:
Hello, I having having oodles of trouble using the std lib in my MC++ (VS.NET 2003) Class library. I figured out a simple sample to reproduce the errors I am having. Create a MC++ (VS.NET 2003)...
4
by: lada77 | last post by:
All, Just wondering if one of you very helpful guru's out there could comment on some odd behaviour I am seeing. I'm betting it is something obvious but I am not experienced enough to tell...
0
by: mirkmmd | last post by:
Hi I am new to this site and also to c++. The problem I am facing is that I when I run the following code, I expect to get '"Today is sunny" at the end of the program. And I do get it in Visual...
2
by: darkkal | last post by:
Hi I'm a student majoring a computer . I tried to make a simple hashing table like (int) 1 , (std::string) "One" There is a problem in using std::map ㅜㅜ this is a simple code. PLZ~~Help...
2
by: jabbah | last post by:
I have some data in a map and I want to sort it. Currently I have implemented it like this: #include <iostream> #include <map> #include <string> using namespace std; int main(){
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
2
by: giovanniandrean | last post by:
The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
3
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all...
1
by: Teri B | last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course. 0ne-to-many. One course many roles. Then I created a report based on the Course form and...
3
by: nia12 | last post by:
Hi there, I am very new to Access so apologies if any of this is obvious/not clear. I am creating a data collection tool for health care employees to complete. It consists of a number of...
0
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.