|
Guess you can't use a string type instead of a char*? If you used a string type throughout your application, and if that type used reference counting, then the only strings you would have to copy would be the literals, the others you would simply increase the reference count. This would clearly change your efficiency - no idea if for better or worse.
Peter
"Until the invention of the computer, the machine gun was the device that enabled humans to make the most mistakes in the smallest amount of time."
|
|
|
|
|
Kind of funny you should suggest that, because that's almost exactly what we have today. Once our string type has copied data from a buffer, then it is ref-counted to avoid further copies. We have a means to specify that the input string is a literal quoted string, in which case no copy of the string data is made at all (and ref-counting is not needed).
However in most cases programmers seem to use the version that copies string data even when they're supplying a literal quoted string. No reason other than they have other things on their mind when writing code, and don't seem to remember such details.
So my goal was to detect this and either automatically be more efficient, or give them a compiler error that forces them to use the more efficient version.
As an update I've found I can use "const" to detect the use of a non-literal buffer in some cases, but not all. For example:
char buff[100];<br />
...<br />
StringClass s1(buff);
const char* ptr = ...;
StringClass s2(ptr);
StringClass s3("hello");
So I would like to distinguish between the s2 and the s3 case (the s2 case should be copied since there's no telling where the pointer is pointing, and the s3 case should not be copied). I don't think C++ is going to let me do that.
Thanks for the ideas...
|
|
|
|
|
Hi,
I have a small problem with my radio buttons. I have a group of three buttons, when I click button 0 everythings fine, but if I click button 1 or 2 and special requirements are not met the software should give a message to the user and reselect button 0. I did it in the BN_CLICKED message handler of the two radio buttons like this:
void CDlgMacroColor::OnReferenceDynamic()
{
if(some condition)
{
m_EditColorRefThreshold.EnableWindow(TRUE);
}
else
{
AfxMessageBox("No Global Reference found! Changing to Local Color Reference.",MB_OK|MB_ICONEXCLAMATION,0);
m_EditColorRefThreshold.EnableWindow(FALSE);
m_iReferenceType = 0;
UpdateData(FALSE);
}
}
m_iReferenceType is the integer determining which radio button is selected.
The problem that occurs is, that with UpdateData(FALSE) a new BN_CLICKED message is sent to the same radio button I just declined (I would accept it if it was sent to the new one, but no, it's sent to the old one) and the user gets the message box twice.
Now my two questions: Why does this happen? and even more important: How can I avoid this?
Thanks in advance
Martin Dietz
|
|
|
|
|
m.dietz wrote: Why does this happen?
You are triggering an event from an event handler.
It sounds to me that if (some condition) is false then the radio buttons that represent invalid options should be "disabled". Then you would not need check the condition and act from inside the event handler.
|
|
|
|
|
Disabling the button is not possible, as the condition that defines whether this selection is allowed cannot be tested at OnInitDialog(). Anyway even if I found a way to test it there, the software requirement specification orders this interface behaviour (Maybe our product managers think that the user is not able to determine by his own how to enable that button if I disable it, and that's why he has to be told when trying to select this option... ).
That I trigger an event within an event handler should not be that unusual, I also use UpdateData(FALSE) in OnInitDialog() and UpdateData(TRUE) in OnOK(), well, I didn't test if those event routines also are called twice, but I don't think so. As I said, I would understand it if I got an BN_CLICKED on the new radio button, because changing the button in the GUI by UpdateData() is like clicking on it, but I get this event on the old button again and that's what irritates me.
|
|
|
|
|
m.dietz wrote: Disabling the button is not possible
Of course it is possible
m.dietz wrote: (Maybe our product managers think that the user is not able to determine by his own how to enable that button if I disable it, and that's why he has to be told when trying to select this option... ).
Sorry, I am a software developer not a psychiatrist. I can't provide mental health solutions for you. Even when the radio button is disabled there can still be a tooltip and/or "help" that would explain "how" to enable it. This would be a superior solution to the one you describe and if you did it and demonstrated it to "the managers" and they still reject it then I would start working on my resume.
|
|
|
|
|
m.dietz wrote: The problem that occurs is, that with UpdateData(FALSE)...
Another reason why UpdateData() should be avoided, especially with radio buttons. Assign a CButton object to each radio button, and use the SetCheck() method.
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
So you say that's a bug of UpdateData()? OK, I could assign an interface object for each radio button and set it by SetCheck() and get the value of it by GetCheck(), but apart from being that a big effort to uncheck every other option each time I want to check one option, doesn't that undermine the idea of having one value for the whole group? I would do that only as a last resort, and I don't think the situation is that desperate, there must be a way how Microsoft thought UpdataData should be used making a sense.
|
|
|
|
|
m.dietz wrote: So you say that's a bug of UpdateData()?
That's not what I said at all. See here for more.
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
OK, I read this article, and I disagree in more than one point.
The main reason why it says not to use UpdateData() is because this could mess up the original data. This can easily be avoided by keeping the original data stored in some variables/some structure, where it is read from by OnInitDialog() or some Init function you programmed yourself. Second I agree with the critic of NEVER using member variables of a function outside the class they are members of. Information handling between the dialog and the caller can be much easier achieved by giving a pointer to a memory location via a dialog function like InitData(). In this structure the caller writes its initialization data, OnInitDialog() reads from that structure to initialize the variables, in OnOK() the dialog writes back the result and the caller can read from the structure what he had in mind. This creates an usage of the dialog like
<br />
CMyDialog dlg;<br />
MYStructure str;<br />
str.Var1 = info1;<br />
str.Var2 = info2;<br />
dlg.MyInit(&str)<br />
dlg.DoModal();<br />
info1 = str.Var1;<br />
result = str.VarResult;<br />
In preserving the data in that structure you also always have a copy of your data for a Reset() which itself can call a function InitControls() shared with the OnInitDialog() routine. All intermediate data SHALL NOT BE STORED IN VARIABLES THE CALLER HAS ACCESS TO.
Second reason, why I disagree with that article: It says UpdateData would force you to keep an eye on your state and make sure it is always consistent and not a mixture of old and new data. That also can be avoided by keeping the separation between dialog data and display data. The only time a consistency check for display data has to be made is at the OnOK() event before writing the results back to the structure I used above. At every intermediate point it is not necessary to keep consistency, as all changes of UpdateData() only affects display data, not dialog data and when it is all checked at the OnOK() there still is time enough to tell the user what he did wrong (e.g "You can't choose 'dynamical selection' without selecting a rule.").
Third point of the article is the order in which the ON_CHANGE notifications happen. If there are some dependent data fields, the author says, then you get problems with setting the correct data of control B in accordance to the value of control A when the message is handled for control A. The author seemed to forget that it's YOU, the programmer, who knows about this dependencies, and YOU can set the values before calling UpdateData() making sure that the only work the ON_CHANGE event handler has to do is check that the data entered into control B is correct.
And to my humble opinon it's far easier to remember whether to use UpdateData with TRUE or FALSE than to remember each control and keep its value in an extra variable.
But this article does still not explain, why I get an ON_CLICK message for a control that is not clicked instead of an ON_CHANGE, which I can ignore if I want, and therefore, I still think this extra ON_CLICK message is neither wanted nor documented and something that is neither documented nor expected is a misbehaviour of software and as long as there are not really good reasons for this misbehaviour I see this as a caused by a bug.
|
|
|
|
|
You can fix this problem by putting this at the very beginning of your OnReferenceDynamic() function:
if (m_iReferenceType == 0)
return;
|
|
|
|
|
Sorry that doesn't work! Coming from the standard choice "local reference" at the beginning of the event handler m_iReferenceType is always 0. This I already tried on Friday.
Edit: It works if I set a UpdateData(TRUE) as the first line, but I don't know which unwanted events that wil bring...
-- modified at 3:51 Monday 6th August, 2007
|
|
|
|
|
If I have an integer value, and I want to write its value into a string, how do I work out how many characters the integer will take up?
For example, if I have the number 100, and I want to put it into a string using sprintf, how do I dynamically work out how many characters the number will take up (in this case 3)?
Thanks for your help!
--PerspX
"Nowadays, security guys break the Mac every single day. Every single day, they come out with a total exploit, your machine can be taken over totally. I dare anybody to do that once a month on the Windows machine." - Bill Gates
|
|
|
|
|
Why would you need that ?
|
|
|
|
|
I have a string of text displaying the size of a file (in bytes) in the form "File Size: %d bytes" (where %d is the file size) and I would like to allocate enough memory whatever the file size.
--PerspX
"Nowadays, security guys break the Mac every single day. Every single day, they come out with a total exploit, your machine can be taken over totally. I dare anybody to do that once a month on the Windows machine." - Bill Gates
|
|
|
|
|
Perspx wrote: I have a string of text displaying the size of a file (in bytes) in the form "File Size: %d bytes" (where %d is the file size) and I would like to allocate enough memory whatever the file size.
DWORD dwFileSize = 123456;
char s[28];
sprintf(s, "File Size: %lu bytes", dwFileSize);
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
To know how many characters in the formatted string are needed to allocate,
use _vscprintf an then use new or malloc with the number of characters returned.
|
|
|
|
|
Perspx wrote: how do I work out how many characters the integer will take up?
Why bother? Assume the worst case and allocate room for 10, or 20 if you are on a 64-bit machine.
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
That's bad programming and a waste of resources.
--PerspX
"Nowadays, security guys break the Mac every single day. Every single day, they come out with a total exploit, your machine can be taken over totally. I dare anybody to do that once a month on the Windows machine." - Bill Gates
|
|
|
|
|
Perspx wrote: That's bad programming and a waste of resources.
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
You can laugh but I bet that the reason that most Microsoft programs are slow and clunky is because the programmers who write them do bad programming techniques such as that.. and it doesn't matter for that particular example, as that only wastes 19 bytes at the maximum.. but if you apply that technique for other data allocation, then you could waste a lot more which makes your application unreliable and not perform so well..
--PerspX
"Nowadays, security guys break the Mac every single day. Every single day, they come out with a total exploit, your machine can be taken over totally. I dare anybody to do that once a month on the Windows machine." - Bill Gates
|
|
|
|
|
Please continue!
It's amazing!
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
|
|
|
|
|
Perspx wrote: I bet that the reason that most Microsoft programs are slow and clunky...
I highly doubt that. Reserving 1 byte or 20 bytes from the stack will make no noticeable difference in your code's execution time, but using the log10() function and asking the memory manager for countless small amounts of memory will.
Consider the following:
for (int x = 0; x < nFileCount; x++)
{
int nLength = (int) (log10(dwFileSize) + 1.0);
char *s = new char[18 + nLength];
sprintf(s, "File Size: %lu bytes", dwFileSize);
delete [] s;
} compared to:
char s[28];
for (int x = 0; x < nFileCount; x++)
{
sprintf(s, "File Size: %lu bytes", dwFileSize);
}
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
Perspx wrote: That's bad programming and a waste of resources.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
|
|
|
|
|
Is that a laugh at me or in agreement?
--PerspX
"Nowadays, security guys break the Mac every single day. Every single day, they come out with a total exploit, your machine can be taken over totally. I dare anybody to do that once a month on the Windows machine." - Bill Gates
|
|
|
|