Forum: PC-Programmierung Wert eines characters ausgeben


von Nixwisser (Gast)


Lesenswert?

Hallo,

ich möchte versuchsweise in C++ ein ASCII-Zeichen in einen String 
einlesen, dessen ASCII-Wert in einer Variable speichern und ausgeben. 
Hier z.B. das 'H':

  char val;
  stringstream ss (stringstream::in | stringstream::out);
  ss << 'H';
  ss >> val;
  cout << val << endl;

Funktioniert aber nicht. Fragen: Warum nicht? Wie kann man das auf 
einfache Weise machen?

Danke schonmal.

von Nixwisser (Gast)


Lesenswert?

Achja, auf der Konsole wird eben das Zeichen und nicht der Wert 
ausgegeben. Mit einer Integer-Variable funktioniert es auch nicht.

von Peter (Gast)


Lesenswert?

ich finde das streamzeug in c++ hässlich!!!

Aber hier mein versuch der Lösung:

  char val;
  stringstream ss (stringstream::in | stringstream::out);
  ss << 'H';
  ss >> val;
  cout << (_int8)val << endl;

von teplotaxl (Gast)


Lesenswert?

du brauchst itoa

von Karl H. (kbuchegg)


Lesenswert?

>  cout << val << endl;

> Funktioniert aber nicht. Fragen: Warum nicht?

Weil der Datentyp von val ein char ist. Und für char ist nun mal 
definiert, dass bei der Ausgabe nicht der Zahlenwert, sondern das 
Zeichen an sich ausgegeben wird.

von Karl H. (kbuchegg)


Lesenswert?

teplotaxl wrote:
> du brauchst itoa

Quatsch

von Karl H. (kbuchegg)


Lesenswert?

Der Stringstream mag für dich jetzt nur eine Übung sein. Im Grunde 
brauchst du ihn hier nicht. Du musst nur dafür sorgen, dass der char bei 
der Ausgabe seine Sonderstellung verliert und als ganz normale 
Zahlenvariable angesehen wird. Peter hat ja schon gezeigt, wie man das 
mit einem Cast erzwingen kann.


  cout << (usnsigned int)'H' << endl;

von Peter (Gast)


Lesenswert?

@Karl heinz Buchegger
> (usnsigned int)'H'
kann das nicht schief gehen? (unsigned int) ist 2/4 byte gross 'H' 
1Byte, das ganze ist ja ein Cast, kann es dabei nicht passieren das im 
Speicher zu viele daten gelesen werden?

von Karl H. (kbuchegg)


Lesenswert?

Peter wrote:
> @Karl heinz Buchegger
>> (usnsigned int)'H'
> kann das nicht schief gehen? (unsigned int) ist 2/4 byte gross 'H'
> 1Byte, das ganze ist ja ein Cast, kann es dabei nicht passieren das im
> Speicher zu viele daten gelesen werden?

Nein, da kann nichts schief gehen.
Der Compiler weiss schon was in so einem Fall zu tun ist. Er ergänzt 
einfach die fehlenden Bytes mit 0-Bytes und schiebt erst dieses 
Zwischenergebnis in die Ausgabefunktion für unsigned int.
Getreu dem Motto: Vor eine Zahl kann man beliebig viele führende Nullen 
stellen, es ändert nichts an der Zahl.

von Nixwisser (Gast)


Lesenswert?

>Weil der Datentyp von val ein char ist. Und für char ist nun mal
>definiert, dass bei der Ausgabe nicht der Zahlenwert, sondern das
>Zeichen an sich ausgegeben wird.

Wo ist denn sowas definiert? In der Iostream-Klasse?

Euer Typecast funktioniert. Ich habe es mit int('H') hinbekommen. Gibt 
es einen Unterschied zwischen den Casting-Methoden (außer, das "(type) 
Wert" aus C herrührt?)

von Karl H. (kbuchegg)


Lesenswert?

Nixwisser wrote:
>>Weil der Datentyp von val ein char ist. Und für char ist nun mal
>>definiert, dass bei der Ausgabe nicht der Zahlenwert, sondern das
>>Zeichen an sich ausgegeben wird.
>
> Wo ist denn sowas definiert? In der Iostream-Klasse?

Ja und Nein. In erster Linie ist es natürlich die Sprachdefinition von 
C++, die vorschreibt, was bei der Ausgabe eines char zu passieren hat. 
Aber ntürlich gibt es in den Stream-Klassen eine Funktion, die 
letztendlich den char einfach so ausgibt, während sie bei einem int 
(zb.) zuerst eine Textrepräsentierung des int erzeugt.

> Euer Typecast funktioniert. Ich habe es mit int('H') hinbekommen. Gibt
> es einen Unterschied zwischen den Casting-Methoden (außer, das "(type)
> Wert" aus C herrührt?)

Es läuft beides aufs gleiche hinaus.
Rein syntaktisch macht deine Variante etwas anderes:

  int('H')

erzeugt ein int Objekt, welches mit dem ASCII-Code von 'H' initialisiert 
wird. Dieses temporäre int-Objekt wird ausgegeben und dann wieder 
zerstört.

Das ist aber reines theoretisches Geplänkel. In der Praxis läuft es aufs 
geliche hinaus und der Compiler wird auch in beiden Fällen identischen 
Code erzeugen. Interessant ist dieser Unterschied nur dann, wenn 
anstelle eines int tatsächlich mal ein 'richtiges' Objekt erzeugt werden 
muss.

von Nixwisser (Gast)


Lesenswert?

>Das ist aber reines theoretisches Geplänkel. In der Praxis läuft es aufs
>geliche hinaus und der Compiler wird auch in beiden Fällen identischen
>Code erzeugen. Interessant ist dieser Unterschied nur dann, wenn
>anstelle eines int tatsächlich mal ein 'richtiges' Objekt erzeugt werden
>muss.

Kannst du da mal ein Beispiel nennen?

von Karl H. (kbuchegg)


Lesenswert?

Nixwisser wrote:
>>Das ist aber reines theoretisches Geplänkel. In der Praxis läuft es aufs
>>geliche hinaus und der Compiler wird auch in beiden Fällen identischen
>>Code erzeugen. Interessant ist dieser Unterschied nur dann, wenn
>>anstelle eines int tatsächlich mal ein 'richtiges' Objekt erzeugt werden
>>muss.
>
> Kannst du da mal ein Beispiel nennen?

Klar

Wir brauchen dazu eine Klasse mit einem Konstruktor, der einen oder 
mehrere Werte übernimmt.
1
class Fractional
2
{
3
  public:
4
    Fractional( int Nominator, int Denominator )
5
    : nomi_( Nominator ),
6
      denomi_( Denominator )
7
    {}
8
9
  private:
10
    int nomi_;
11
    int denomi_;
12
};

und natürlich soll diese Klasse auch was machen. Sagen wir mal, wir 
verpassen ihr eine Funktion, die es ihr erlaubt, sich auf einen Stream 
auszugeben. Dazu noch einen freistehenden op<< der uns erlaubt, diese 
Funktion in gewohnter Syntax zu benutzen.
1
class Fractional
2
{
3
  public:
4
    Fractional( int Nominator, int Denominator )
5
    : nomi_( Nominator ),
6
      denomi_( Denominator )
7
    {}
8
9
   void output( ostream& out ) const { out << ((double)nomi_) / denomi_; }
10
11
  private:
12
    int nomi_;
13
    int denomi_;
14
};
15
16
std::ostream& operator<<( ostream& out, const Fractional& obj )
17
{
18
  obj.output( out );
19
  return out;
20
}

und jetzt möchten wir gerne die beiden Zahlen 5 und 8 als Bruch 
auffassen (dazu ist ja die Klasse Fractional gedacht) und den Wert des 
Bruchs in Zahlenform ausgeben
1
int main()
2
{
3
  std::cout << Fractional( 5, 8 ) << endl;
4
}

Hier wird ein temporäres Fractional Objekt erzeugt, mit den Werten 5 und 
8 initialisiert. Dieses temporäre Fractional Objekt wird aufgefordert 
sich auf den Stream auszugeben (wobei op<< benutzt wird) und dann 
zerstört sich das temporäre Objekt wieder.

Edit: Ach ja. Hier muss man über ein temporäre Objekt gehen. Mit simplen 
Casting kommt man hier nicht weiter.

von Nixwisser (Gast)


Lesenswert?

Besten Dank!

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.