Forum: PC-Programmierung Parameter Dialog: Komma anstatt Punkt


von Joe C. (gladi)


Lesenswert?

Hallo Zusammen,

ich habe in meinem Programm ein CDialog integriert.
Es soll im Feld als Parameter eine float Zahl eingegeben werden.
Das Problem, es wird Punkt anstatt Komma akzeptiert, z. B. "0.03"
wie kann eine Gleitkommazahl entwieder mit komma oder Punkt angenommen 
werden?

Danke

C/C++ Code:
----------------------------------------------------------.cpp
1
///////////////////////////////////////////////////////////////////////////// 
2
// Dialogfeld CKalibrierfaktor 
3
4
5
CKalibrierfaktor::CKalibrierfaktor(CWnd* pParent) 
6
    : CDialog(CKalibrierfaktor::IDD, pParent) 
7
{ 
8
    //{{AFX_DATA_INIT(CKalibrierfaktor) 
9
    m_fWert = 0.0f; 
10
    //}}AFX_DATA_INIT 
11
} 
12
13
14
void CKalibrierfaktor::DoDataExchange(CDataExchange* pDX) 
15
{ 
16
    CDialog::DoDataExchange(pDX); 
17
    //{{AFX_DATA_MAP(CKalibrierfaktor) 
18
    DDX_Text(pDX, IDC_txtFaktor, m_fWert); 
19
    DDV_MinMaxFloat(pDX, m_fWert, 0.f, 100.f); 
20
    //}}AFX_DATA_MAP 
21
} 
22
23
24
BEGIN_MESSAGE_MAP(CKalibrierfaktor, CDialog) 
25
    //{{AFX_MSG_MAP(CKalibrierfaktor) 
26
        // HINWEIS: Der Klassen-Assistent fügt hier Zuordnungsmakros für Nachrichten ein 
27
    //}}AFX_MSG_MAP 
28
END_MESSAGE_MAP() 
29
30
----------------------------------------------------------.h 
31
32
class CKalibrierfaktor : public CDialog 
33
{ 
34
// Konstruktion 
35
public: 
36
    CKalibrierfaktor(CWnd* pParent = NULL);   // Standardkonstruktor 
37
38
// Dialogfelddaten 
39
    //{{AFX_DATA(CKalibrierfaktor) 
40
    enum { IDD = IDD_DLGFaktor }; 
41
    float    m_fWert; 
42
    //}}AFX_DATA 
43
44
45
// Überschreibungen 
46
    // Vom Klassen-Assistenten generierte virtuelle Funktionsüberschreibungen 
47
    //{{AFX_VIRTUAL(CKalibrierfaktor) 
48
    protected: 
49
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV-Unterstützung 
50
    //}}AFX_VIRTUAL 
51
52
// Implementierung 
53
protected: 
54
55
    // Generierte Nachrichtenzuordnungsfunktionen 
56
    //{{AFX_MSG(CKalibrierfaktor) 
57
        // HINWEIS: Der Klassen-Assistent fügt hier Member-Funktionen ein 
58
    //}}AFX_MSG 
59
    DECLARE_MESSAGE_MAP() 
60
};

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Indem Du einen String einliest und selber parst.

von Karl H. (kbuchegg)


Lesenswert?

Besteht die Gefahr, daß deine Benutzer mit 1000-er Seperatoren
arbeiten?
Wenn ja, dann gibt es keine wirklich gute Lösung dafür. Allerdings
sollte man ihnen das IMHO sowieso abgewöhnen. Führt in der Praxis
immer wieder zu Ärger.

Zu deinem Problem.
Die MFC-spezial DDX Makros, mit denen man ein Edit Feld so
einschränken kann, daß eine Zahleneingabe erwartet wird, sind
so in der Praxis sowieso Müll. Lösch einfach mal die Zahl aus
so einem Edit Feld raus (zb. mit einem Backspace) und die MFC
mault rum, daß man bitte eine Zahl eingeben möge. Einen Endbenutzer
kann man damit in den Wahnsinn treiben.

Lösung: Auch Zahleneingaben immer als Texteingaben machen, und
die Umwandlung in eine Zahl dann selbst (zb. mit einem sscanf)
machen. Dann ist es auch einfach im String, den man vom Control
bekommt, alle ',' durch '.' zu ersetzen, sodaß sscanf das richtig
parsen kann. Der Vorteil: Der Benutzer kann dann wahlweise
sowohl ',' als auch '.' als Dezimaltrenner verwenden. Geht aber
klarerweise nur dann, wenn 1000-er Seperatoren nicht benutzt werden.

Wir haben uns dafür spezielle DDX Funktionen geschrieben.
Zb. sowas
1
void C3dDDX_Text( CDataExchange* pDX, int nIdC, double& d, int Comma = 2 );

1
void C3dDDX_Text( CDataExchange* pDX, int nIdC, double& d, int Comma /* = 2 */ )
2
{
3
  CWnd*   pWnd = pDX->m_pDlgWnd->GetDlgItem( nIdC );
4
  CString str;
5
6
  pDX->PrepareEditCtrl( nIdC );
7
8
  ASSERT( pWnd );
9
  if( pDX->m_bSaveAndValidate ) {
10
    pWnd->GetWindowText( str );
11
    
12
    int n = str.Find( _T( "," ) );
13
    if( -1 < n ) {
14
      str.SetAt( n, '.' );
15
    }
16
17
    d = 0;
18
    _stscanf( str, _T( "%lf" ), &d );
19
  }
20
21
  else {
22
    TCHAR szBuf[64];
23
    _stprintf( szBuf, _T( "%-8.*lf" ), Comma, d );
24
    pWnd->SetWindowText( szBuf );
25
  }
26
}

Die haben dann auch noch den netten Nebeneffekt, dass man die
Anzahl der auszugebenden Nachkommastellen sauber definieren
kann.

Wenn der Dialog dann fertig ist, wird die DDX Zeile in DoDataExchange
gegen einen Aufruf so einer Funktion ersetzt:
1
void CKalibrierfaktor::DoDataExchange(CDataExchange* pDX) 
2
{ 
3
    CDialog::DoDataExchange(pDX); 
4
    //{{AFX_DATA_MAP(CKalibrierfaktor) 
5
    C3dDDX_Text(pDX, IDC_txtFaktor, m_fWert, 3); 
6
    //}}AFX_DATA_MAP 
7
}

Allerdings spielt dann der Dialogeditor nicht mehr mit. Daher
diesen Austausch erst ganz zum Schluss machen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

1000er-Separatoren ließen sich abfangen, indem vor der Konvertierung die 
Anzahl der Punkte und Kommata bestimmt wird bzw. das letzte 
entsprechende Zeichen im String als Dezimal{punkt|komma} verwendet wird:

"1.000,23"

Allerdings bleibt auch dann so etwas wie "1.000" nicht anständig 
interpretierbar.

von Joe C. (gladi)


Lesenswert?

Es wird mit 1000-er Seperatoren nicht gearbeitet.

von Joe C. (gladi)


Lesenswert?

Hallo Karl heinz Buchegger,

ganz herzlichen Dank!
Es hat funktioniert.

MfG
gladi

von spess53 (Gast)


Lesenswert?

Hi

Sieh mal nach, ob dein Compiler eine globale Variable 'Decimalseparator' 
kennt. Unter Delphi lässt sich das nämlich ganz einfach einstellen:

decimalseparetor:=',';

MfG Spess

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Nein, das kennt der Compiler nicht - das hier ist eine MFC-Anwendung.

Wobei es auch gar nicht dorthin gehört, richtig wäre es, die 
Locale-Informationen über das verwendete Zahlenformat auszuwerten.

Die für das Einlesen von Float-Zahlen verwendbare Funktion atof kann 
sehr wohl auch die Locale-Einstellugen des OS auswerten, dazu muss nur 
im Programm  die Win32-API-Funktion setlocale mit der Kategorie 
LC_NUMERIC und dem entsprechenden Landescode aufgerufen werden.

von Karl H. (kbuchegg)


Lesenswert?

Rufus t. Firefly wrote:
> Nein, das kennt der Compiler nicht - das hier ist eine MFC-Anwendung.
>
> Wobei es auch gar nicht dorthin gehört, richtig wäre es, die
> Locale-Informationen über das verwendete Zahlenformat auszuwerten.

Yep. Das wäre die schöne Lösung.
Der Krampf an der Sache (in meinem/unserem Fall) ist aber, daß
viele Leute aus der Technik daran gewöhnt sind einen Kommapunkt
einzugeben. Und wenn deine Clientel dann aus eine Mischung aus
Punkt und Komma Fetischisten besteht, hast du den A.... offen.

Für uns hat sich die Lösung mit dem String manipulieren
bewährt.
Jeder der schon mal versucht hat eine amerikanische
Datendatei in ein deutsches Excel zu importieren, kennt diesen
Krampf.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.