-
October 3rd, 2014, 02:48 PM
#1
How to use set<char*>?
Here is the code. Both set1 and set2 always store one string. I know why but I don't know how to use set<char*> and still allow me to store multiple strings? Thanks.
Code:
void PrintOut(const char* fileName)
{
char line[256];
set<char*> set1;
set<char*> set2;
char key[64];
char def[64];
char* pLine;
int index1;
int index2;
int count;
FILE* file = fopen(fileName, "r");
while(fgets(line, 64, file))
{
index1 = 0;
index2 = 0;
count = 0;
pLine = line;
while(*pLine)
{
if(count == 0)
key[index1++] = *pLine;
else
def[index2++] = *pLine;
if(*pLine == ' ')
{
if(*(pLine+1) == '.')
break;
if(count == 0)
{
key[index1] = '\0';
set1.insert(key);
index1 = 0;
}
else
{
def[index2] = '\0';
set2.insert(def);
index2 = 0;
}
count++;
}
pLine=pLine+1;
}
def[index2] = '\0';
set2.insert(def);
}
set<char*>::iterator next;
for(set<char*>::iterator it2=set2.begin();it2!=set2.end();++it2)
{
for(set<char*>::iterator it1=set1.begin();it1!=set1.end();it1=next)
{
next = it1;
next++;
if(*it1 == *it2)
set1.erase(*it1);
}
}
fclose(file);
}
-
October 3rd, 2014, 02:58 PM
#2
Re: How to use set<char*>?
They both displays the last string, right? That's because you are storing the pointer to the same string buffer. Try defining the set as set key<string>.
-
October 3rd, 2014, 03:09 PM
#3
Re: How to use set<char*>?
Originally Posted by Arjay
They both displays the last string, right? That's because you are storing the pointer to the same string buffer. Try defining the set as set key<string>.
I understand that. But my question is that is it still possible to store multiple strings in a set without using stl string? Thanks.
-
October 3rd, 2014, 04:10 PM
#4
Re: How to use set<char*>?
Yes it is. Rather than have key and def defined as fixed items on the stack, create them as dynamic elements on the heap (use new) each time round the while loop. You'll need to also free the memory as part of the function clean up.
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
October 3rd, 2014, 04:39 PM
#5
Re: How to use set<char*>?
Originally Posted by 2kaud
Yes it is. Rather than have key and def defined as fixed items on the stack, create them as dynamic elements on the heap (use new) each time round the while loop. You'll need to also free the memory as part of the function clean up.
Thanks for your reply! If I free the memory, then the string stored in the set1 and set2 will be destroyed. Here is my modified code. Would you tell me how to free the memory? Thanks.
Code:
void PrintOut(const char* fileName)
{
char line[256];
set<char*> set1;
set<char*> set2;
char key[64];
char def[64];
char* pKey;
char* pDef;
char* pLine;
int index1;
int index2;
int count;
FILE* file = fopen(fileName, "r");
while(fgets(line, 64, file))
{
index1 = 0;
index2 = 0;
count = 0;
pLine = line;
while(*pLine)
{
if(count == 0)
key[index1++] = *pLine;
else
def[index2++] = *pLine;
if(*pLine == ' ')
{
if(*(pLine+1) == '.')
break;
if(count == 0)
{
key[index1] = '\0';
pKey = new char[index1+1];
strcpy(pKey, key);
set1.insert(pKey);
index1 = 0;
}
else
{
def[index2] = '\0';
pDef = new char[index2+1];
strcpy(pDef, def);
set2.insert(pDef);
index2 = 0;
}
count++;
}
pLine=pLine+1;
}
def[index2] = '\0';
pDef = new char[index2+1];
strcpy(pDef, def);
set2.insert(pDef);
}
set<char*>::iterator next;
for(set<char*>::iterator it2=set2.begin();it2!=set2.end();++it2)
{
for(set<char*>::iterator it1=set1.begin();it1!=set1.end();it1=next)
{
next = it1;
next++;
if(*it1 == *it2)
set1.erase(*it1);
}
}
fclose(file);
}
-
October 3rd, 2014, 05:42 PM
#6
Re: How to use set<char*>?
Originally Posted by LarryChen
Thanks for your reply! If I free the memory, then the string stored in the set1 and set2 will be destroyed. Here is my modified code. Would you tell me how to free the memory? Thanks.
He said cleanup Larry. That means you free the memory when you're done with it. As to how you do it, I would think after nine years on this forum, you'd know that delete is used to free memory allocated with new.
-
October 3rd, 2014, 05:59 PM
#7
Re: How to use set<char*>?
Along with cleanup, it's important to understand what the following line does.
set1.erase(*it1);
Questions for Larry:
Does it remove the item from the set?
Does it free up the item pointed to by *it1 ?
-
October 3rd, 2014, 06:16 PM
#8
Re: How to use set<char*>?
Originally Posted by GCDEF
He said cleanup Larry. That means you free the memory when you're done with it. As to how you do it, I would think after nine years on this forum, you'd know that delete is used to free memory allocated with new.
Congratulations! You know delete! You are a GURU in C++. But would you please spare a second to read my post? Thanks.
-
October 3rd, 2014, 06:30 PM
#9
Re: How to use set<char*>?
Originally Posted by Arjay
Along with cleanup, it's important to understand what the following line does.
set1.erase(*it1);
Questions for Larry:
Does it remove the item from the set?
Does it free up the item pointed to by *it1 ?
Yes, it does remove the item from the set1. But I am not sure if set1.erase(*it1) will free the memory pointed by *it1. Any idea? Thanks.
-
October 3rd, 2014, 06:39 PM
#10
Re: How to use set<char*>?
Originally Posted by LarryChen
Yes, it does remove the item from the set1. But I am not sure if set1.erase(*it1) will free the memory pointed by *it1. Any idea? Thanks.
Larry, why ask the question?
Use the debugger and find out. Put a breakpoint on the set1.erase(...) line and inspect the *it1 value in the watch or local window. Then single step through just past the line and inspect the value again.
If you can't do this in your project, then create a test project that does the same thing.
Report back.
-
October 3rd, 2014, 06:48 PM
#11
Re: How to use set<char*>?
Originally Posted by Arjay
Larry, why ask the question?
Use the debugger and find out. Put a breakpoint on the set1.erase(...) line and inspect the *it1 value in the watch or local window. Then single step through just past the line and inspect the value again.
If you can't do this in your project, then create a test project that does the same thing.
Report back.
Yes, erase does free the memory. Thanks.
-
October 3rd, 2014, 08:18 PM
#12
Re: How to use set<char*>?
Originally Posted by LarryChen
Yes, erase does free the memory. Thanks.
Are you sure you are using the debugger correctly?
-
October 3rd, 2014, 08:36 PM
#13
Re: How to use set<char*>?
1) I agree with Arjay, you need to recheck. Hint: You initial code did not crash.
2) using char * leads to lots of problems. Consider:
Code:
set<char *> set1;
char * p1 = new char[10];
char * p2 = new char[10];
strcpy(p1,"hello");
strcpy(p2,"hello");
set1.insert(p1);
set1.insert(p2);
This will result in a set of size 2 (probably not what you want). This is because by default, the
comparison function will be operator <. This will just order by the address.
You will need to use the set constructor where you specify the comparison function.
Even after doing that, you will need to check that the string is in the set before
trying to insert it. If it is already in the set, the insert will fail, and will not be
deleted when you end up doing the eventual delete.
You might consider using smart pointers instead of raw pointers.
Last edited by Philip Nicoletti; October 3rd, 2014 at 10:06 PM.
Reason: forgot the second strcpy
-
October 4th, 2014, 03:33 AM
#14
Re: How to use set<char*>?
Originally Posted by LarryChen
I understand that. But my question is that is it still possible to store multiple strings in a set without using stl string? Thanks.
Why do you want to use set<char*>? Why not just use set<string> as it's far easier - you haven't got to bother with a comparison function and issues re allocating and freeing memory.
What is the format of your file layout and what are you trying to achieve?
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
October 4th, 2014, 04:10 PM
#15
Re: How to use set<char*>?
Originally Posted by LarryChen
Congratulations! You know delete! You are a GURU in C++. But would you please spare a second to read my post? Thanks.
You asked how to free memory. I told you. You seem confused by some very basic concepts, so I gave you a very basic answer.
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
|