-
April 21st, 2003, 06:01 PM
#1
user defined types and std::map
hello,
i want to make a map keyed on strings represented by char* (i.e. c strings). how would i do this?
it seems that if i declare map<char*, mytype>, then the keys would be the actual pointer and not the strings the pointers point to.
example: i want this to work:
const char* str1 = "test";
const char* str2 = "test";
map<char*, mytype*> m;
m[str1] = my_data;
assert(m.find(str2) != m.end());
thank you,
-- christopher
-
April 21st, 2003, 06:21 PM
#2
Check out the documentation for map.
Use the third template argument to specify the comparison
criterion.
--Paul
-
April 21st, 2003, 10:28 PM
#3
In terms of comparison, the default algorithm in the STL map container will compare points, not string. One solution is std::bind and a functor.
Kuphryn
-
April 22nd, 2003, 01:01 AM
#4
Try
std::map< std::string, your_type> coll;
// works - implicit conversion
coll[ "test"] = val;
//etc.
Best,
John
-
April 22nd, 2003, 02:35 AM
#5
Re: user defined types and std::map
Originally posted by clockworks
hello,
i want to make a map keyed on strings represented by char* (i.e. c strings). how would i do this?
it seems that if i declare map<char*, mytype>, then the keys would be the actual pointer and not the strings the pointers point to.
Why not use std::string instead of char*?
Code:
#include <string>
//...
std::string str1 = "test";
std::string str2 = "test";
map<std::string, mytype> m;
m[str1] = my_data;
assert(m.find(str2) != m.end());
//...
Regards,
Paul McKenzie
-
April 22nd, 2003, 06:11 AM
#6
Re: Re: user defined types and std::map
Originally posted by Paul McKenzie
Why not use std::string instead of char*?
Paul McKenzie
I definitely agree with Paul on this one. Unless you are very very careful, using char *'s as index into a map will invariably lead to memory leaks. Use std:string, it's much safer and much easier to handle. There is practically no performance penalty either.
For an example of the problems see this code:
Code:
// bad code !
std::map<char *, int, StringComp> m;
char *sz;
sz = new char[2];
sz[0] = '0';
sz[1] = 0;
m[sz] = 25;
// This char * now belongs to the map,
// so you should not free it until you free the item in the map
sz = new char[2];
sz[0] = '0';
sz[1] = 0;
m[sz] = 10;
// since "0" was already a key, it is not put into the map again
// now you DO have to delete [] it.
Simply awful
Get this small utility to do basic syntax highlighting in vBulletin forums (like Codeguru) easily.
Supports C++ and VB out of the box, but can be configured for other languages.
-
April 25th, 2003, 11:50 PM
#7
std::string will not work for what i want. i'm writing a huffman encoder and i have a map of frequencies per "chunk". a chunk could be 1, 2, 3, or n bytes.
so lets say i want to count the frequencies of 2 byte chunks of a text file. thus i want a map<char*, int> to do something like the following psudocode:
char chunk[2];
while (!eof) {
read_chunk(chunk, file);
freq_map[chunk] += 1;
}
obviously that won't work: no matter how interation of the loop, and diversity of the file, the map will be of size one at the end.
i tried doing something like this:
struct comp {
bool operator()(const char* s1, const char* s2) {
return memcmp(s1, s2, chunk_size) < 0;
}
};
map<char*, int, comp> freq_map;
but it doesn't solve the problem at all.
thanks for the help,
-- christopher
-
April 26th, 2003, 12:15 AM
#8
Originally posted by clockworks
std::string will not work for what i want. i'm writing a huffman encoder and i have a map of frequencies per "chunk". a chunk could be 1, 2, 3, or n bytes.
std::string can be 1, 2, 3, or n bytes. So far your reasoning doesn't eliminate std::string
so lets say i want to count the frequencies of 2 byte chunks of a text file. thus i want a map<char*, int> to do something like the following psudocode:
char chunk[2];
while (!eof) {
read_chunk(chunk, file);
freq_map[chunk] += 1;
}
This particular "chunk" is a sequence of some characters, correct? Does this same sequence keep changing but the pointer to it stay the same? Unless this is the reason for using pointers, there is nothing in the pseudo-code you posted that makes std::string unusable. As a matter of fact, the very first line (char chunk[2]) is a dead giveaway that std::string can be used.
Regards,
Paul McKenzie
-
April 26th, 2003, 04:35 AM
#9
paul,
excuse me, i'm a bit inebriated, but whats with the hints? no hints, just tell me how to do it...=)
what if my chunk is 4 bytes:
first byte: 0
second: 0
thrid: 0
fourth: 10
its my understanding that std::strings represent ascii strings. hence a 4 byte std::string can't start with 0 because that would be the empty string or something.
let me try to be more clear. my chunk is:
00000000 00000000 00000000 00001000.
how would i store that in an std::string? and write it to a file using fwrite()?
they don't teach stl in school, just algorithms, so i'm asking for explicit instructions on how to do this.
i actually remedied (sp?) the problem. i made a class called chunk_t that overloads the == operator, the < operator, the = operator, and a bunch of constructors, etc. it was a pain in the ***, but it worked. my huffman encoder compressed an 800k file to 300k (using 2-3 byte chunks), but i don't like having to introduce a new class like this.
anyways, thanks for the tips,
-- christopher
-
April 26th, 2003, 10:02 AM
#10
Originally posted by clockworks
paul,
excuse me, i'm a bit inebriated, but whats with the hints? no hints, just tell me how to do it...=)
what if my chunk is 4 bytes:
first byte: 0
second: 0
thrid: 0
fourth: 10
its my understanding that std::strings represent ascii strings. hence a 4 byte std::string can't start with 0 because that would be the empty string or something.
OK clockworks, stop right there
std::string does not necessarily wrap a null terminated string (if this was the reason for the apprehension in using it). Any sequence of bytes can be stored in a std::string, with the length of the string governed by the "length()" member function, not where a NULL may be located.
If you take a look at the std::string constructor, one of the constructors is:
std::string(const char *, size_type len);
You also have the assign() member function to add a series of characters to the std::string. std::string is much more than what you may think it is.
For your NULL example,
Code:
#include <string>
#include <iostream>
using namespace std;
int main()
{
char chunk[] = { 0, 0, 0, 16 };
std::string s;
s.assign(chunk, 4);
//OR
std::string s2(chunk, 4);
cout << "s has " << s.length() << " bytes "<< endl;
cout << "s2 has " << s2.length() << " bytes "<< endl;
cout << endl;
for (int i = 0; i < s.length(); ++i)
cout << (int)s[i] << endl;
cout << endl;
for (i = 0; i < s2.length(); ++i)
cout << (int)s2[i] << endl;
}
Output:
s has 4 bytes
s2 has 4 bytes
0
0
0
16
0
0
0
16
let me try to be more clear. my chunk is:
00000000 00000000 00000000 00001000.
how would i store that in an std::string? and write it to a file using fwrite()?
Is this already in "char" form and not just a binary number? If it is already in char form, the above example answers your question.
Code:
char YourChunkString[32];
// Assume YourChunkString has 32 characters.
std::string sChunk(YourChunkString, 32);
//...
fwrite( sChunk.data(), 1, sChunk.length(), YourFile);
If it isn't in char form, you have to convert it to binary. There is a C++ bitset class that helps you out that does the conversion, and you can save the conversion back to a std::string.
Code:
#include <bitset>
unsigned long YourChunkNum = 1839343L;
//...
std::bitset<32> b32( YourChunkNum );
std::string sChunk = b32.to_string();
they don't teach stl in school, just algorithms, so i'm asking for explicit instructions on how to do this.
Just come here for solutions
i actually remedied (sp?) the problem. i made a class called chunk_t that overloads the == operator, the < operator, the = operator, and a bunch of constructors, etc. it was a pain in the ***, but it worked. my huffman encoder compressed an 800k file to 300k (using 2-3 byte chunks), but i don't like having to introduce a new class like this.
Your code should be much neater once you use the std::string. Also, my suggestion is to get the book "The C++ Standard Library" by Nicolai Josuttis. It explains, in great depth, std::string and its capabilities.
Regards,
Paul McKenzie
-
April 26th, 2003, 06:58 PM
#11
wow cool, thanks for the post...=) i'm gunna clean up the code right now to use std::string! and i'm definantly gunna check out that book your recommended.
thank you,
-- christopher
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|