Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » und jetzt umgekehrt : string nach double

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
28.03.2003, 15:08 Uhr
bilbo



Hallo ,

bin noch newbie...vielleicht geht sowas ja ganz einfach:
Ich habe einen String von der Tastaur eingelesen:
zb.
2345
2345.3456
34e56
-345

andere Zeichen werden als fehlerhaft erkannt und es wird erneut zur eingabe aufgefordert...
nun möchte ich aber aus dem String ein double machen. Es gibt die Funktion atof(), die aber nur eine Genauigkeit von 5 zulässt....double und longdouble können aber eine Genauigkeit von 10 .

wie geht man damit um?

Wäre toll, wenn jemand helfen kann

vielen Dank,

B.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
31.03.2003, 02:09 Uhr
Hans
Library Walker
(Operator)


Hi,

in Informatik- und Programmierlehrbüchern findet man meisst irgendwo in Kapitel, das sich mit unterschiedlichen Zahlensystemen beschäftigt. Unter anderem erfährt man dort, das sich eine Zahl als eine Summe von Potenzen darstellen lässt. So ist z.B. die Zahl 123.456 in der Potenzform darstellbar als:

1*10^2 + 2*10^1 + 3*10^0 + 4*10^(-1) + 5*10^(-2) + 6*10^(-3)

Hierbei fällt auf, das bei Dezimalzahlen immer eine Multiplikation mit 10 im Spiel ist, und (dem Wesen einer Summe entsprechend) eine Addition. Die prinzipielle Vorgehensweise, um eine beliebige Zahl aus einem String in den gewünschten Datentyp zu konvertieren ist deshalb folgende:

1. Eine Variable mit 0 initialisieren, wo in der am Ende die umgewandelte Zahl drin steht.
2. Man nehme von links her ein Zeichen aus dem String und stelle fest, ob es ein Ziffernzeichen ist.
2a. Wenn es ein Ziffernzeichen ist, wird es in den Zahlenwert umgewandelt, den es repräsentiert. D.h. aus dem ASCII-Code für '2' wird der Zahlenwert Zwei.
2b. Die zuvor initialisierte Variable wird mit 10 multipliziert, und anschliessend die eben umgewandelte Zahl dazu gezählt (addiert).
3. Wenn es kein Ziffernzeichen ist, wird die Umwandlungsaktion beendet.

Das gilt bis hierher für ganze Zahlen genauso, wie für gebrochene. Ein Dezimalpunkt, bzw. einem Komma dient als Hinweis, dass man jetzt ein wenig anders weitermachen muss.

4. Der gebrochene Anteil muss erst mal in einer eigenen Variablen gepuffert werden. Er wird erst am Ende der Umwandlung per Addition dem ganzzahligen Anteil hinzugefügt.
5. Die weiteren Ziffern werden wie in Punkt 2, bzw. 2a behandelt. Nur anstelle der multiplikation in Punkt 2b muss jetzt eine Division erfolgen. Das kommt daher, das die Nachkommastellen in der Potenzdarstellung ein Minuszeichen im Exponenten (also vor der Hochzahl) haben. Und das bedeutet eben, das man durch 10 teilen muss.

Alternativ kann man bei Punkt 4 auch so weitermachen, wenn das Komma kommt:
4a. Das Komma wird überlesen
4b. Wir machen ganz genau so weiter, wie bisher, zusätzlich werden noch die Ziffern gezählt, die hinter dem Komma stehen.
4c. Am Ende wird sooft durch 10 geteilt, wie Nachkommastellen gezählt wurden. Bei 3 Stellen nach dem Komma wären das drei Divisionen durch 10.

Soweit die theoretische Erklärung, die mir hoffentlich einigermassen gelungen ist. In einem Programm sieht das ganze ungefähr so aus:

C++:
/* Datei: zahlein2.cpp

  Zum testen einer Routine für Zahlenumwandlungen

*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

double zahlein(char *s);

int main()
{
  double zahl;
  char s[20];

  printf ("Bitte geben Sie eine Zahl ein: ");
  fgets (s, 19, stdin);
  zahl=zahlein(s);
  printf ("Die eingegebene Zahl ist: %lf\n", zahl);

  //getch();
  return 0;
}

double zahlein(char *s)
{
  int ii, j, vz, nk;
  double w;

  ii=j=vz=nk=0; w=0;

  while (s[ii]==' ')    // mögliche führende Leerzeichen überlesen
        ii++;
  // Evtl. vorhandenes Vorzeichen überprüfen und merken
  if (s[ii]=='-')
    { vz=1;
       ii++;
    }
  a:
  // Solange, wie Ziffernzeichen da sind
  while (s[ii]>'/' && s[ii]<':')      // diese in den Zahlenwert umwandeln und
      { w = w * 10. + ( s[ii]-'0');  // zur Zahl hinzu fügen
        ii++;                        // nächstes Zeichen
        if (nk) j++;       // Wenn es Nachkommastellen sind, werden sie gezählt
      }
  if (s[ii]=='.' || s[ii]==',') // Komma behandlung
   {  nk++;      // Flag zur Kennzeichnung von Nachkommastellen
      ii++;      /* Komma überlesen */
      goto a;
   }
  for ( ; j>0; j--)  // Die Zahl entsprechend der Nachkommastellen
      w /= 10. ;     // durch 10 teilen
  return( vz ? -w : w);    // Die Zahl vorzeichengerecht an den Aufrufer liefern
}
/* Ausschnitt aus der ASCII-Tabelle:
   Zeichen     :  /  0  1  2  3  4  5  6  7  8  9  :
   Code  (dez) :  47 48 49 50 51 52 53 54 55 56 57 58
         (hex) :  2f 30 31 32 33 34 35 36 37 38 39 3a
*/




Hier hab ich die zweite Möglichkeit verwendet. Möglicherweise ist sie etwas zu Rechenintensiv, aber das dürfte sich angesichts der aktuellen Taktfrequenzen erst bei sehr großen Datenmengen bemerkbar machen, denke ich mal.

Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.

Dieser Post wurde am 31.03.2003 um 02:14 Uhr von Hans editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
31.03.2003, 09:43 Uhr
~0xdeadbeef
Gast


atof gibt einen double zurück, mit einer genauigkeit von 15 Stellen. Zumindest will es der Standard so.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
31.03.2003, 21:09 Uhr
Hans
Library Walker
(Operator)



Zitat:
atof gibt einen double zurück, mit einer genauigkeit von 15 Stellen. Zumindest will es der Standard so.


Hi $deadbeef,

ich hab's noch nicht ausprobiert, deshalb kann ich dazu nichts sagen, aber:
Wer kapiert hat, wie die oben angegebene Routine genau funktioniert, kann sie sich auch so umstricken, dass sie für andere Zahlensysteme, wie z.B. Hex- oder Binärzahlen verwendbar ist. Man wird zwar selten gebrochenen Zahlen so angeben, aber man kann dann auch HexZahlen einlesen, die nach anderen Konventionen gekennzeichnet sind. Die mit dem führenden Dollarzeichen, die ich bei Deinem Nick verwendet hab, stammt z.B. vom C-64.

Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
03.04.2003, 20:10 Uhr
Hans
Library Walker
(Operator)



Zitat:
~0xdeadbeef postete
atof gibt einen double zurück, mit einer genauigkeit von 15 Stellen. Zumindest will es der Standard so.


Hi,
hab's jetzt mit Borland C++ Builder 5.5 mal ausprobiert, - der macht es auch.

Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: