|
Hi all...
First off, I'd like to thank all whom contribute to this board - it has been an extremely valuable resource for me - a non-programming expert.
I'm a mechanical engineer by trade but have written Visual C++ apps for quite some time; sometimes for fun, sometimes for timesaving. Right now, I'm developing an application that performs some extensive linkage analysis on motorcycle suspensions. As such, I'm using primarily "double" variables.
In the past, when I needed to display these values in my window, I could convert them to a string and write them to a text box and control their format. This time, however, I have simply set the on screen edit box variables as doubles and have direct relationships between my screen variables and my calculation variables to make screen updates and retrieving data from the screen easier/quicker.
However, now when I display the values on the screen, they're written out to some god-awful number of decimal places. Is there an easy way of limiting an edit box's number of decimal places when you do an UpdateData ?
Sorry that this is probably a very lame question, but your assistance is much appreciated.
-Chris
http://www.slideruleracing.com
|
|
|
|
|
In DoDataExchange() , look for the call to DDX_Text() which has the ID of the edit box you're entering. Replace with something like the following:
if ( pDX->m_bSaveAndValidate )
{
DDX_Text( pDX, IDC_EDIT1, m_flData )
<font color="green">
}
else
{
CString sRep;
<font color="green">
sRep.Format( _T( "%.3f" ), m_flData );
SetDlgItemText( IDC_EDIT1, sRep );
} Obviously it's not as tidy as simply calling DDX_Text .
You could add your own overload of DDX_Text if you're going to be doing this a lot. Look at the implementation in the MFC source code in DlgFloat.cpp for an example.
--
Mike Dimmick
|
|
|
|
|
I'd eliminate the use of UpdateData(). For each edit control, assign a CString member variable. When it comes time to update a control, do something like:
CString strSuspension;<br />
strSuspension.Format("%.3f", m_dSuspension1);<br />
m_edit.SetWindowText(strSuspension);
If you need to get the value from a control, use:
m_edit.GetWindowText(strSuspension);<br />
m_dSuspension1 = atof(strSuspension);
There are many ways to tackle this problem.
|
|
|
|
|
OK so I customized the CColorDialog and added a HEX edit box. What I want to know is how can I update this when the user changes a color in the color dialog box? Is there some function or way to tell me when I should change the hex edit box to reflect the current color selected by the user?
|
|
|
|
|
Router
|
|-- 192.168.0.2 <----> 192.168.0.1 (Client1 on LAN1)
|-- 172.16.0.2 <----> 172.16.0.1 (Client1 on LAN2)
|-- 10.10.0.2 <----> 10.10.0.1 (Client1 on LAN3)
Machines Specifications
Router
Windows XP Professional with Service Pack 1
Windows 2000 Server (Dual Boot)
Microsoft Visual Studio 6.0
AMD K6-II 500 MHZ, 256MB RAM
3Com Etherlink III ISAPNP Ethernet Adapter 10Mbps
HP Ethernet with LAN remote power Adapter 10/100 Mbps (PCI)
Intel 21143-Based PCI Fast Ethernet Adapter 10/100 Mbps
Client 1 on LAN 1
Windows 2000 Professional with SP3
Microsoft Visual Studio 6.0
Pentium II 450 MHZ, 256 MB RAM
Realtek RTL8029(AS) PCI Ethernet Adapter 10Mbps
Client 1 on LAN 2
Windows 2000 Professional with SP3
Microsoft Visual Studio 6.0
Pentium III 600 MHz, 128 MB Ram
3Com EtherLink XL 10/100 PCI For Complete PC Management NIC (3C905C-TX)
Client 1 on LAN 3
Windows 2000 Professional with SP3
Microsoft Visual Studio 6.0
Pentium II 266 MHz, 128 MB Ram
Linksys LNE 100 TX Fast Ethernet Adapter (PCI)
This is my network topology. A machine acting as a router is connected to three other machines acting as three different LANs. The problem is with the behaviour of Microsoft’s API Function GetAdaptersInfo(). This function gives complete information about any NIC in a PC such as MAC Address, IP Address, Subnet Mask, Default Gateway etc.
This function works fine when all the PCs are up and network is running. But fails when any one PC from any network is off. GetAdaptersInfo() gives 0.0.0.0 as IP Address, subnet mask etc. of the NIC whose associated network is down. There is nothing documented about this behaviour in MSDN.
One more strange thing is that this function has different behaviour on above four PCs. It works fine regardless of network is up or down on Client1 on LAN1 and on Client1 on LAN2 but fails (means give 0.0.0.0) on Router machine and Client3 on LAN3.
I am unable to understand who is causing this problem.
Whether it is operating system?
Whether it is NIC driver?
or simply it is a bug of GetAdaptersInfo()?
Anybody help please!!!!!!!!!!!1
Thanks
|
|
|
|
|
Hi All,
I am using VC++ 6.0 on a client running Win98.
I need to access a datasource on a webserver running NT 4.0.
The remote database is Access97.
The remote datasource is already set up as a System DSN via ODBC.
The remote datasource is not accessible via a LAN - it must be accessed by domain name or IP address.
I have searced the CDAO documentation but can't determine how to connect to a remote datasource via tcp/ip
Can anyone help with this?
My goal is to populate a combo box with a query from this remote datasource.
I tried ActiveX controls, but the intricacies of creating wrapper classes is beyond me at this time.
It would be faster for me to rewrite the entire project in Visual Basic just so I can use an ActiveX control but I really want to do this in C++.
Does anyone know of perhaps a pre-built class I can drop into my project?
My workaround at this time involves calling a Cold Fusion page on the server and parsing the returned text into the combobox. Very ugly.
Thanks!!!
EDIT
====
Thanks anyways! I cut the Gordian knot and just ported the Access DB over to a MySQL DB and I can connect with a standard ODBC string
|
|
|
|
|
I am trying t create a switch statment that sitches on names in an array
but I can only come up with a the loop below.
Is there a function that will return the numeric value of a char?
char Names[50]<br />
<br />
for(int i=0; i<50; i++){<br />
int temp = (int)Names[i];<br />
if(temp = the number value of 'pla')<br />
then do some stuff<br />
<br />
if(temp = the number value of 'oct'0)<br />
then do some more stuff<br />
}<br />
Steven
|
|
|
|
|
johnstonsk wrote:
the number value of 'pla'
You can not turn a string into a single int and then compair the ints...
[EDIT]
Well if your string is exactly 4 characters you can use a cast like you did in your code sample but this is the only case that it would reliably work...
[/EDIT]
John
|
|
|
|
|
some of the valuse in the char array vary
pla
oct
frozen
stopped
etc.....
steven
any ideas on how to do this?
steven
|
|
|
|
|
If there are more than 4 characters it won't work with just a cast because an int is 4 characters of data. Since there are only 26 letters and less than 4 billion possible english words ( I assume all are spelled correctly and there are no proper names...) you could come up with an algorithm to convert the words to 4 byte numbers.
John
|
|
|
|
|
you can do it on a char level, but you described a string...
'pla' is impossible
What are you trying to do, to comapre strings ?
|
|
|
|
|
What I am trying to do is I have read in a file and put specific name into an array.
For eash name in the array I want to do something different.
I would like to do a switch statemnt on each name in the name array, but a switch has to be an int.
So, I was going to try to spin through the array and for each element in the char array I was going to get its numeric value and compare it to the numeric value of the char I was looking for.
If the numeric values were the same then the chars must be the same and then we have a match.
I hope that all made sense.
thanks, steven
|
|
|
|
|
Well if your string is exactly 4 characters you can use a cast like you did in your code sample but this is the only case that it would reliably work...
John
|
|
|
|
|
Do you have any other ways that I can spin through an array and for each element in it do something different depending on the name??
steven
|
|
|
|
|
Why can't you use a string compare function and put the actual strings in if statements instead of a big switch statement.
John
|
|
|
|
|
This "char Names[50];" is an array of characters not strings/names. If if was a list of known names then you could use "if else" as follows:
if( !strcmp(Names[i],"some name" )
else if( !strcmp(Names[i],"some other name" )
This is 'C' code; in both 'C' and 'C++' there are more complicated, to start with, yet easier to maintain methods of accomplishing your goal.
INTP
|
|
|
|
|
I know I am asking why you are doing something rather than just answering your question so I apologize.
First, there is a way to get the numeric value of a char. Just cast the char as an int and there you go.
Second, there is no numeric value of a string so you can't do what you are asking.
In your sample code, you show:
char Names[50]
for(int i=0; i<50; i++)
{
int temp = (int)Names[i]; // reinitialization error?
if(temp = the number value of 'pla')
then do some stuff;
if(temp = the number value of 'oct'0)
then do some more stuff;
}
Where is your switch statement?
Are you simulating the switch with the if statements?
In the sample shown, you have a single name which can be up to 50 chars long. You are merely comparing 1 letter from that same name at a time. If you need 50 names, you'll need to define a 2 dimensional array like char Names[50][30];
If you absolutely have to use a switch statement (like a school project) you can create a struct which contains a key value and when you populate the struct you can increment the key.
struct NameStruct
{
char Names[50][30];
int key;
};
Then you can use the NameStruct.key value in your switch statement and access the names with NameStruct.Names[key]
If your end goal is to be able to loop through an array of strings and take a different action for each string you could try:
char Names[50][MAX_NAME_LENGTH];
int x;
for (x = 0; x < MAX_NAME_LENGTH; x++)
{
if(!strcmp(Names[x], "Text to compare"))
DoSomething();
if(!strcmp(Names[x], "Other text to compare"))
DoSomethingElse();
........
if(!strcmp(Names[x], "Last text to compare"))
DoSomethingEtirelyDifferent();
}
|
|
|
|
|
for (x = 0; x < MAX_NAME_LENGTH; x++)
Should be
for (x = 0; x < 50; x++)
and you should use the 'if else' construct to avoid unneeded calls to strcmp().
INTP
|
|
|
|
|
John R. Shaw wrote:
for (x = 0; x < MAX_NAME_LENGTH; x++)
Should be
for (x = 0; x < 50; x++)
and you should use the 'if else' construct to avoid unneeded calls to strcmp().
You are correct of course. Thank you!
I'm going to live forever or die trying!
|
|
|
|
|
Believe me I don't have to do this for a school project.
I have created a tool that display flight simulator data in real time.
Long story short:
(this is just another feature of the program)
The flight simulator writes to a file and I use the getline() function to get the names of signals that the sim wrote and put them in TSimHeader_arr[0].Name[i] which is an array in a struct.
anyways I think the function (char)strdup(name.c_str()) isn't putting them in the char array correctly.
Because when I read them bach out they are strange characters.
I don't know how to do this.
Does anyone???
steven
void setInitialValues(){<br />
sSignal.SimWriteFlag=1; <br />
sSignal.DisplayReadFlag=0; <br />
sHeader.SimStatus=setSimStatus();<br />
<br />
string name,unit,min,max,value;<br />
<br />
for(int i=0; i<sizeof(sHeader.Name); i++){<br />
getline(fin, name, ',');<br />
<br />
if(name == "STOP")<br />
break;<br />
getline(fin, unit, ',');<br />
getline(fin, min, ',');<br />
getline(fin, max, ',');<br />
getline(fin, value);<br />
<br />
TSimHeader_arr[0].Name[i] = (char)strdup(name.c_str()); <br />
TSimHeader_arr[0].Unit[i] = (char)strdup(unit.c_str()); <br />
TSimHeader_arr[0].Min[i] = atof(min.c_str());<br />
TSimHeader_arr[0].Max[i] = atof(max.c_str());<br />
TSimSignal_arr[0].Value[i] = atof(value.c_str());<br />
<br />
<br />
<br />
sig_count ++;<br />
<br />
}<br />
<br />
TSimHeader_arr[0].SignalCount = sig_count;<br />
<br />
writeRfmData();<br />
createRandNum();<br />
}
|
|
|
|
|
Prototype: char *_strdup( const char *strSource );
Bad: (char)strdup(name.c_str()); // this is incorrect usage
Good: strdup(name.c_str()); // normal usage
Ok: (char*)strdup(name.c_str()); // this is redundant
INTP
|
|
|
|
|
If it's a simple piece of work you want to do for each item, just use a chain of if statements using strcmp() to compare.
If it's harder (which I assume it is since you've got 50 entries in your table), define a function pointer type:
typedef int (PFNTASK*)(
const char* szName,
);
int DoPla( const char* szName, );
int DoOct( const char* szName, ); Then define a structure:
typedef struct
{
const char* szName;
PFNTASK pfnTask;
} TaskEntry; Now define your array:
TaskEntry namesAndTasks[] =
{
{ "pla", DoPla },
{ "oct", DoOct }
}; Finally, search for the operation to perform:
for( int iTask = 0; iTask < 50; ++i )
{
if ( strcmp(
temp,
namesAndTasks[iTask].szName
) == 0 )
{
namesAndTasks.pfnTask( temp, );
break;
}
} Usually quite effective. I prefer it to a long switch statement, even when I have sequential integer codes to switch on.
Because the code size is smaller, this can sometimes run faster than a huge switch statement too.
--
Mike Dimmick
|
|
|
|
|
Mike Dimmick wrote:
Usually quite effective. I prefer it to a long switch statement, even when I have sequential integer codes to switch on.
Because the code size is smaller, this can sometimes run faster than a huge switch statement too.
Actually, most modern compilers (and this includes VC) translate switch statements on large numbers of integer variables to jump tables.
On C#, switches on strings are allowed, and above a certain threshold the compiler generates a Hashtable with jump locations and the strings as a key.
ORACLE One Real A$#h%le Called Lary Ellison
|
|
|
|
|
I'm sure they do. I meant from a code maintenance point of view: it's a lot easier to maintain (I think) a set of moderately simple functions than it is to maintain a 500-line function with a huge switch statement in it.
Of course, you can still code the dispatching mechanism like:
switch ( iValue )
{
case 0:
HandleCase0();
break;
case 1:
HandleCase1();
break;
default:
assert( !"Error in case statement!" );
break;
} but that gets very boring, very quickly. Unless there was some clear profiling indication that the table version was too slow for a given code path, I'd stick to that.
As for how common libraries implement it: in Win32 programming, you typically write a big switch statement. MFC's message maps are table-based (complicated somewhat by supporting ranges). ATL's BEGIN_MSG_MAP family of macros mask a honking great if /else if chain.
The hash table implementation is probably nicer if you have a fixed set and can calculate it all in advance, and either know that you can't get false-positives or check that there's a match before you jump. For general, intelligible coding, I use the array. The threshold is obviously because the hash table has an overhead in the hash function and the extra check in any case.
MFC has, IIRC, a small hash table for each class with a message map which contains the most recently used message map entries, so it doesn't have to search the whole table (and potentially the base class's table, and its base class, and so on down) every time a common message arrives.
My solution does require that all your operations will take the same parameters. This ain't necessarily so. One of my implementations was for a varargs function where you had command identifiers, and each command could take 0, 1 or 2 parameters. So I had to have a parameter count field as part of my jump table structure which indicated what you needed to cast the function pointer to. Again, MFC does something similar for its message maps.
--
Mike Dimmick
|
|
|
|
|
Mike Dimmick wrote:
but that gets very boring, very quickly. Unless there was some clear profiling indication that the table version was too slow for a given code path, I'd stick to that.
I agree. Actually, everytime I see a huge switch statement (as I'm an OOP die-hard) I start to ask what's wrong with the design, since this should be solved by a virtual method call. Not all switches should be virtual calls, but normally they indicate some design flaw in an OOP world.
ORACLE One Real A$#h%le Called Lary Ellison
|
|
|
|