|
Hi,
I have an structure declared in the .h file.
typedef struct
{
int nID;
TCHAR szName[MAX_PATH];
}MyStruct1;
typedef std::map<std:basic_string xmlns:std="#unknown"><tchar>, MyStruct1> MyStructList;</tchar></std:basic_string>
Another struct which contains the MyStructList list as it's member.
typedef struct
{
int age;
TCHAR Place[MAX_PATH];
MyStructList ObjList;
}MyMainStruct;
In the .cpp file.
void MyApp::main()
{
MyMainStruct objMainStruct;
UpdateList( objMainStruct.ObjList);
}
void MyApp::UpdateList(MyStructList &ObjList)
{
MyStruct1 MyStructObj;
_tcscpy(MyStructObj.szName, _T("ABCDE"));
MyStructObj.nID = 2532;
ObjList.Insert(MyStructList::value_type(_T("First"), MyStructObj)).second;
}
I am not able to update the MyStructList list structure in the function below.
When I perform an insert on the list or for that matter any operation on the list, my application (VC2005 on vista) crashes.
Is it because the way I have declared an List object inside another structure that this is not working?
Plesae help me there.
|
|
|
|
|
I am surprised that even compiles.
It should be :
void MyApp::UpdateList( MyStructList &objList )
{
MyStruct1 myStructObj;
_tcscpy( myStructObj.szName, _T("ABCDE") );
myStructObj.nID = 2532;
objList.Insert( MyStructList::value_type( _T("First"), myStructObj ) ).second;
}
|
|
|
|
|
I believe, when I create an instance of MyMainStruct object, the memory is not getting allocated to the MyStructList member. Is my understanding right?
If so how do i get about it?
I dont want to create any object on the heap and store it's pointer in the structure.
|
|
|
|
|
The only flaw I could see is having an implicit cast from CONST TCHAR* into TCHAR*. However, even in this case the code may work. Are you sure the reason of your crash is inside the map::insert?
My quick suggestion is trying the code by declaring the map's key as CONST TCHAR* instead.
--
Arman
|
|
|
|
|
Arman Z. Sahakyan wrote: The only flaw I could see
Well, see my other post.
How is the map comparing the keys ? Using a ==operator.
Now, what happens if you compare two TCHAR* strings using a == operator ? The addresses are compared, not the contents. Thus you will end up with crazy results if you don't use a comparison function like strcmp. The map doesn't know that it has to use such function to compare the keys, thus it will compare simply the pointers and you end up with unexpected results.
|
|
|
|
|
std::map uses operator ==?? I think no. It uses std::less predicate which uses operator < by default. And for string pointers it's common to use them as keys because identical strings are stored in the same location and different strings (I mean const char* ) in different.
But surely, I'd chose std::string as a more modern (and event more) alternative to those const char pointers!
--
Arman
|
|
|
|
|
Arman Z. Sahakyan wrote: std::map uses operator ==?? I think no.
Honnestly, I don't exactly what it uses internally, but it uses an arithmetic operator anyway (operator < for instance). And this is not really nice working with pointers
Arman Z. Sahakyan wrote: And for string pointers it's common to use them as keys because identical strings are stored in the same location
No, not necessarily. Otherwise you wouldn't need a strcmp function .
I guess it's okay if you are using static strings but once you start maniuplating those strings and copying to another TCHAR pointer, then everything is screwed. And you certainly want to use something else than just the same TCHAR pointer for your key.
|
|
|
|
|
Please, first fix the typos. For instance, you are missing a < character on the map declaration so we can't see the type you are using as a key. If you are using a TCHAR*, then review what we discussed yesterday, because it won't work. Use a std::string or std::wstring instead (because of the comparison operator that won't work for a TCHAR*).
Second, if you have a crash, it is very helpfull if you provide the exact location of the crash in your code (using the call stack from the debugger) and any other assert message that you get.
Third, the way you use the insert (and not Insert function) is a bit akward: why are you accessing the return value (you write a .second at the end) ? The insert function returns an iterator (the place where your data was inserted), why do you access this iterator ? It doesn't make any sense and makes the code difficult to understand.
Furthermore, you I find easier to use the [] operator directly:
ObjList[_T("First")] = MyStrucObj;
Anyway, as said yesterday, your problem certainly comes from the fact that you are using TCHAR* as key for the map. Please, consider seriously using a string wrapper class instead, or you will make your life a hell for nothing.
|
|
|
|
|
If you are not yet convinced about using a std::string as a key, here[^] is a discussion about a guy having issues because he is using a char* as key for the map. I'm almost sure that your problem is because of that (maybe not the crash but at least your program won't work at all the way you would expect it).
Just because it compiles doesn't mean that your code is correct. Just because it compiles with a TCHAR* as key doesn't mean that it is valid.
|
|
|
|
|
I am not sure if you guys understand the issue that I am facing.
typedef struct
{
int nID;
TCHAR szName[MAX_PATH];
}MyStruct1;
typedef std::map, MyStruct1> MyStructList;
Another struct which contains the MyStructList list as it's member.
typedef struct
{
int age;
TCHAR Place[MAX_PATH];
MyStructList ObjList;
}MyMainStruct;
//This code gives a crash.
void MyApp::UpdateList(MyStructList &ObjList)
{
ObjList.clear();
MyStruct1 MyStructObj;
_tcscpy(MyStructObj.szName, _T("ABCDE"));
MyStructObj.nID = 2532;
ObjList.Insert(MyStructList::value_type(_T("First"), MyStructObj)).second;
}
//But the given function adds all the structure object with their key without any crash.
void MyApp::UpdateList2()
{
MyStructList localObjList
MyStruct1 MyStructObj;
_tcscpy(MyStructObj.szName, _T("ABCDE"));
MyStructObj.nID = 2532;
localObjList.Insert(MyStructList::value_type(_T("First"), MyStructObj)).second;
}
Which means that there is nothing wrong with the insert operation that is performed on the localObjList list object which is a local copy.
when I create an instance of MyMainStruct object, will the MyStructList member of MyMainStruct also be instantiated.
void main()
{
MyMainStruct MainObj;
UpdateList(MainObj.objMyStructList);//This call crashes.
}
modified on Friday, February 13, 2009 3:22 AM
|
|
|
|
|
Comp_Users wrote: I am not sure if you guys understand the issue that I am facing.
You didn't explain it this way last time, so no I didn't know that it was crashing on clear (you said it was crashing on insert). Anyway, there's something important that you have to understant is that your code is 'broken' and you can end up with unexpected results. First, take some time to fix the issue with your key in the map, chances are that the problem will be solved. If that's not the case, then we can look at a code that is a bit cleaner and try to narrow the problem. Now, there's just too many issues with your code.
|
|
|
|
|
First, I want to thank the group for their responses to my last post. Now, I have it working. Here is what my code looks like:
<br />
button1.Create( TEXT( "xxx" ),<br />
WS_VISIBLE|WS_CHILD|WS_GROUP|BS_AUTORADIOBUTTON,<br />
CRect( 250, 50+charHeight+6, 250 + 9*charWidth, 50+2*(charHeight+6)), this, 2500 );<br />
<br />
<br />
button2.Create( TEXT( "yyyyyy" ),<br />
WS_VISIBLE|WS_CHILD|BS_AUTORADIOBUTTON,<br />
CRect( 250, 50+2*(charHeight+6), 250 + 9*charWidth, 50+3*(charHeight+6)), this, 2500 );<br />
The problem is that when it draws the text of the button, it also draws a different background. I would like the background of the buttons to be the same as the backgrounds of the window. Currently, I do not change the background of my main window. I am thinking that one solution would be to put the text out by calling the method TextOut.
Thanks
Bob
|
|
|
|
|
Seems a regular way of crating buttons and I don't see any special code that would make the button to draw its background differently... Are you sure that is the text that makes the button draw its bg differently?
--
Arman
|
|
|
|
|
Arman,
Thanks for the response. When the text is drawn on the screen, the background is a pale green (Note: my color vision is second rate). The normal background is white. When I make the size of the button bigger, I get a large pale green background. Therefore, I am fairly sure that the button is making the background change color. Is there an easy way for me to set the background of the button to be the same as the background of the window?
Thanks
Bob
|
|
|
|
|
I think you need to handle WM_CTLCOLOR message and set the buttons background transparent and/or set a specific color for it. Something like this:
HBRUSH CMyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
if (pWnd->GetDlgCtrlID() == IDC_MYBUTTON)
{
pDC->SetBkMode(TRANSPARENT);
}
return hbr;
}
--
Arman
|
|
|
|
|
Arman,
Thanks for the response. I am wondering what is the class CMyDlg? Is it a class derived from CButton? Is it the main window class?
Bob
|
|
|
|
|
I didn't mean a CButton derived class but the class inside which you create your buttons. I assumed it could be CDialog derived class (that is why the name CMyDlg) but actually it may be any CWnd derived class.
--
Arman
|
|
|
|
|
Arman,
Thanks for the response. I am doing this in a small test application first, to make sure I understand what is going on. Here is what the routine that I used:
<br />
HBRUSH<br />
CMainWindow::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)<br />
{<br />
HBRUSH hbr = CFrameWnd::OnCtlColor(pDC, pWnd, nCtlColor);<br />
if (pWnd->GetDlgCtrlID() == 2500 ) {<br />
pDC->SetBkMode(TRANSPARENT);<br />
}<br />
return hbr;<br />
}<br />
The class CMainWindow is the main window of the application. Here is the message map for the class:
<br />
BEGIN_MESSAGE_MAP( CMainWindow, CFrameWnd )<br />
ON_WM_CREATE()<br />
ON_WM_CTLCOLOR()<br />
END_MESSAGE_MAP()<br />
The method CMainWindow::OnCtlColor is being called (I verified this with the debugger) and the call
to SetBkMode is happening. However, the background for the button is being changed. I would like
to know either what I am doing wrong, how to debug it, or where to look for some more information.
Thanks
Bob
|
|
|
|
|
Some quick hints;
* try to set background color (instead setting transparent) via CDC::SetBkColor. Here you need to create a HBRUSH object as a member variable in your CMainWindow class (i.g. in constructor; m_brush=::CreateSolidBrush(RGB(my color)) .) Then return that m_brush from OnCrlColor any time you set SetBkColor.
* I'm pretty sure here at codeproject there could at least several good articles on WM_CTLCOLOR and/or OnCtlColor. I think you need make a search for those keys.
Regards.
--
Arman
|
|
|
|
|
Arman,
Thanks for the response. It solved my problem.
Bob Sherry
|
|
|
|
|
I created about 40 CComboBox dynamically,
and do following process for every combobox
-----------------------------------------------------------------
pComboBox[i]->AddString(str);
int iCurIndex = pComboBox[i]->SelectString( -1, str);
if(iCurIndex != -1)
pComboBox[i]->GetLBText(iCurIndex , str);
-----------------------------------------------------------------
When i is 36, exception will occur at line 3. At this time, iCurIndex is 0,
however,content of pComboBox[36] can't be acquired.
|
|
|
|
|
When i is 36, only pComboBox[0] to pComboBox[35] is valid.
So pComboBox[36] is invalid.
«_Superman_»
|
|
|
|
|
Ok below is my code for a Game of Life in C++, my question is how do I make it so after ever generation it stops and the user has to press enter to go to the next generation?
#include <iostream>
using namespace std;
#define alive '1' //This is to make it easier to set a cell to "alive" or "dead" by defining the words as variables equal to a symbol.
#define dead '0'
char currBoard[20][30];
char newBoard[20][30];
char a[20][30];
char b[20][30];
char c[20][30];
char d[20][30];
void printBoard(char a[20][30]);
void resetBoard(char b[20][30]);
int countNeighbors(char c[20][30],int x, int y);
void makeNewBoard(char c[20][30],char d[20][30]);
int main()
{
int g,x,y,i;
resetBoard(currBoard);
resetBoard(newBoard);
cout << "Number of Generations: ";
cin >> g;
x=0;
y=0;
i=1;
while((x>=0) && (y>=0))
{
cout << "Enter point #" << i << ": ";
cin >> y >> x;
currBoard[y][x]=alive;
i++;
}
for (int i=0;i<g;i++)>
{
if (i%2 == 0)
{
printBoard(currBoard);
makeNewBoard(currBoard,newBoard);
}
else
{
printBoard(newBoard);
makeNewBoard(newBoard,currBoard);
}
}
}
void resetBoard(char a[20][30])
{
int y,x;
for(y=0;y<20;y++)
{
for(x=0;x<30;x++)
{
a[y][x]=dead;
}
}
}
void printBoard(char b[20][30])
{
int y,x;
for(y=0;y<20;y++)
{
for(x=0;x<30;x++)
{
cout << b[y][x];
}
cout<<endl;
}
cout<<endl;
}
int countNeighbors(char c[20][30],int y, int x)
{
int prevx;
int prevy;
int nextx ;
int nexty ;
prevy = (y-1 < 0 ? 19 : y-1);
prevx = (x-1 < 0 ? 29 : x-1);
nexty = (y+1 >= 20 ? 0 : y+1);
nextx = (x+1 >= 30 ? 0 : x+1);
int neighbors=0;
if (c[y-1][x-1]==alive)
{
neighbors++;
}
if (c[y-1][x]==alive)
{
neighbors++;
}
if (c[y-1][x+1]==alive)
{
neighbors++;
}
if (c[y][x-1]==alive)
{
neighbors++;
}
if (c[y][x+1]==alive)
{
neighbors++;
}
if (c[y+1][x-1]==alive)
{
neighbors++;
}
if (c[y+1][x]==alive)
{
neighbors++;
}
if (c[y+1][x+1]==alive)
{
neighbors++;
}
return neighbors;
}
void makeNewBoard(char c[20][30],char d[20][30])
{
int neighbors;
int y,x;
for(y=0;y<20;y++)
{
for(x=0;x<30;x++)
{
neighbors=countNeighbors(c,y,x);
switch(neighbors)
{
case 0:
case 1:
d[y][x]=dead;
break;
case 2:
if (c[y][x]==dead)
{
d[y][x]=dead;
}
else
{
d[y][x]=alive;
}
break;
case 3:
d[y][x]=alive;
break;
case 4:
case 5:
case 6:
case 7:
case 8:
d[y][x]=dead;
break;
}
}
}
}</iostream>
|
|
|
|
|
I pick one number by one number from numbers of 1 to 100, then submit them to 5 places (20 numbers for each).
I hope results are differnent, so I use rand() and srand() to generate randomly "pick up" and "submit".
but results are same always. it sounds that rand() function is not random.
do you know how to solve the problem? any function which is real random?
thanks
|
|
|
|
|
I am not sure what you mean by submit. The function srand is to seed the random number generator. I have run some tests on the rand() function that comes with the Microsoft C/C++ compiler. I find it to be an excellent random number generator. Is it a perfect one? No. The function rand() is suppose to produce a random number whose value is independent of the last value it returned.
Are you saying that for two different seeds you are getting the same sequence of random numbers? If this is true, then I think there is a problem.
I have a feeling that I did not help you. I also believe that if I understood your problem better, I could give you a better answer.
Bob
|
|
|
|
|