# [C++] Text zu binär und umgekehrt



## Termy2007 (13. April 2007)

Hallo!
Ich möchte eine Forms-Anwendung in C++ (VC 2005 express) schreiben, welche einen eingegebenen Text aus der ersten TextBox in die einzelnen Zeichen aufteilt und dann diese als Binärzahlen (also die 0en und 1er) in der zweiten TextBox ausgibt.

Ich hab schon 2 Tage lang google gelöchert...hab aber nur C Code gefunden, der mit der Konsole arbeitet!

Ich hab da schon ein bisschen angefangen. Hier der Code für den Button, der die Umwandlung ins Binärsystem einleitet. 


```
private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) 
			 
			 { 
				 progressBar1->Value = 0;
				 progressBar1->Maximum = Convert::ToInt32(textBox1->Text->GetEnumerator());

				 int i;
				 int bitint;
				 string bitstring;
				 for(i = 0; i < Convert::ToInt32(textBox1->Text->GetEnumerator()); ++i) 
				 {
                                                 bitint = static_cast<int> (bitset<8>(textBox1->Text[i]));
				 bitstring = Convert::ToString(bitint);
				 textBox2->Text->Insert(Convert::ToInt32(textBox1->Text->GetEnumerator()), bitstring);
				 progressBar1->Value = progressBar1->Value + 1;
				 }
			

			 }
```

Folgender Fehler:

```
error C2440: 'static_cast': 'std::bitset<_Bits>' kann nicht in 'int' konvertiert werden
```

Bitte lacht mich net aus! Ich bin noch Anfänger  

Meine Fragen sind also:
1. Was mache ich falsch?
2. Kann man es auch einfacher haben?
3. Wie kann man die ganze Sache umdrehen (Binär zu Text)?

Ich höffe, ihr könnt mir helfen!
Mfg Termy 2007


----------



## pschilling (13. April 2007)

Hallo Termy,

ich bin zwar C++ Coder, habe aber gerade dein Problem mal so gelöst.


```
string txt = textBox1.Text;
            StringBuilder sb = new StringBuilder();
            
            CharEnumerator enumerator = txt.GetEnumerator();
            while( enumerator.MoveNext() ) {
                Char c = enumerator.Current;

                Int16 myInt = (short)c;
                sb.Append(myInt >= 128?"1":"0");
                if (myInt >= 128) myInt -= 128;
                sb.Append(myInt >= 64? "1" : "0");
                if (myInt >= 64) myInt -= 64;
                sb.Append(myInt >= 32? "1" : "0");
                if (myInt >= 32) myInt -= 32;
                sb.Append(myInt >= 16 ? "1" : "0");
                if (myInt >= 16) myInt -= 16;
                sb.Append(myInt >= 8 ? "1" : "0");
                if (myInt >= 8) myInt -= 8;
                sb.Append(myInt >= 4 ? "1" : "0");
                if (myInt >= 4) myInt -= 4;
                sb.Append(myInt >=  2 ? "1" : "0");
                if (myInt >= 2) myInt -= 2;
                sb.Append(myInt >= 1 ? "1" : "0");
                if (myInt >= 1) myInt -= 1;
                sb.Append(" ");
            }

            textBox2.Text = sb.ToString();
        }
    }
```

Funktioniert so weit, aber der Weg ist bestimmt nicht der eleganteste ;-)

Den umgekehrten Weg findest du bestimmt selbst heraus.

Schönen Gruß,

Peter


----------



## kle-ben (13. April 2007)

Hi,
ein bitset ist ein komplexer Datentyp den du nicht einfach in ein 
Integer casten kannst. Du kannst deinen bitset aber direkt mit der 
Funktion to_string in einen String wandeln lassen. 

In deinem Schleifenkopf würde ich den Funktionsaufruf :

```
Convert::ToInt32(textBox1->Text->GetEnumerator());
```
durch progressBar1->Maximum ersetzen.
Muss ja nicht jedesmal ausgeführt werden.

Benny


----------



## Termy2007 (13. April 2007)

Danke für die schnellen Antworten!

An pschilling:
Könntest du mir deinen Vorschlag etwas näher erklären?
Ich blick da nicht so richtig durch! 

Gibt es denn da nichts einfacheres?

Termy2007


----------



## pschilling (13. April 2007)

Hi Termy,

mit dem CharIterator durchlaufe ich den String und hole mir die einzelnen Zeichen.

Das zeichen wandle ich in einen Zahlenwert und wandle diesen in einen binärstring.

Ein char ist 1 byte groß, also genau 8 bits.

Jede bit-Position steht für eine Zahl. Das erste, also ganz linke bit steht für die 128, das 2 für 64 u.s.w.

Nun schau ich ob, der ASCII-Wert über 128 liegt. Wenn er es tut, setze ich also eine 1 an die erste position des binärstrings, sonst eine 0.

Das ganze wiederhole ich dann bis zum letzten bit mit den entsprechenden Werten.

Keine Zauberrei.

Gruß,

Peter


----------



## Termy2007 (13. April 2007)

Danke pschilling!
Hab ich verstanden...ok.
Und wie dreht man das um? Bzw. wie sieht dafür der Code aus?
Muss man dann nur gucken..ok hier hab ich ganz links ne 1 also über 128?
Das wird doch nicht reichen oder?


----------



## pschilling (13. April 2007)

Ahoi,

habe gerade mal die Funktion hier geschrieben:


```
public char binaryStringTochar(string binStr) {
            CharEnumerator enumerator = binStr.GetEnumerator();
            if( binStr.Length != 8 ) {
                // Kein gültiger binärstring
                return (char)0;
            }
            int i = 128;
            int value = 0;
            while (enumerator.MoveNext())            {
                Char c = enumerator.Current;
                if( c == '1') {
                    value += i;
                }
                else if(c == '0' ) {
                }
                else {
                    // Kein gültiger Binärstring !! Nur 1 und 0  sind erlaubt
                }
                i /= 2;
            }
            return (char)value;
        }
```

Diese wandelt dir einen 8-zeichen langen string in den entsprechenden char Wert.

Den Rest bekommst jetzt bestimmt auch hin.

Viel Erfolg,

Peter


----------



## MCoder (13. April 2007)

Ich glaube, bei der Umwandlung des "Char" kann man noch etwas Tipperei sparen  

```
Char c = enumerator.Current;

for( int i = 0; i < 8; i++ )
{
    sb.Append( (c & (0x80 >> i)) ? "1" : "0" );
}
            
sb.Append(" ");
```
Gruß
MCoder


----------



## Termy2007 (13. April 2007)

Danke für die Antworten.
Hab haber noch eine kleine Frage:


```
sb.Append( (c & (0x80 >> i)) ? "1" : "0" );
```

Was passiert da genau?
Vor allem:

```
0x80
```


```
? "1" : "0"
```

Sonst ist alles klar!
Danke für eure Hilfe!


----------



## pschilling (13. April 2007)

Nicht böse sein MCoder, dass ich deinen Code kommentiere 

Also 0x80 ist die hexadezimale Form für 128.

x  >> y (oder auch x << y) nennt man den Shift-Operator.

Mit diesem werden die bits des Wertes x um y Positionen nach rechts (bzw. links) verschoben.

```
int a = 0x80; // Der Wert 128 wird a zugewiesen Binäre darstellung 10000000
    a >> 1; // Bits um 1 nach rechts verschieben, Binäre darstellung     01000000 = 64
```


```
Ausdruck?a:b;
```
Kannst du als verkürzte Schreibweise für 

```
if( Ausdruck) {
    a;
}
else {
    b;
}
```
sehen.

Wenn Ausdruck == TRUE, dann wird der erste Wert verwendet, sonst der zweite hinter dem Doppelpunkt.

Gruß,

Peter


----------



## Termy2007 (13. April 2007)

Ah...ok
Ich beginne es zu verstehen!
Gut! Danke! Wenn das Programm fertig ist, werde ich es hier hoch stellen!
Kann aber noch ne Nacht dauern! ^^

Mfg
Termy2007


----------



## Termy2007 (13. April 2007)

Noch eine Frage:
Welche Headerdatei deklariert den "Stringbuilder"?


```
error C2065: 'StringBuilder': nichtdeklarierter Bezeichner
```


----------



## MCoder (13. April 2007)

pschilling hat gesagt.:


> Nicht böse sein MCoder, dass ich deinen Code kommentiere


Hallo Peter, das ist überhaupt kein Problem. Ich habe mich eh nach erfolgreich abgeschicktem Post ins Wochenende und in den Biergarten verabschiedet, so dass die Erklärung sonst ziemlich spät gekommen wäre  



Termy2007 hat gesagt.:


> Welche Headerdatei deklariert den "Stringbuilder"?


Hallo Termy2007, die StringBuilder-Klasse müsstest du mit

```
using namespace System::Text;
```
"erwischen".

Gruß
MCoder


----------



## Termy2007 (13. April 2007)

Und wie sieht es damit aus?


```
CharEnumerator enumerator
```

EDIT: Hat sich erledigt! Hab übersehen, dass es schon funktioniert hat! Sorry!
MfgTermy 2007


----------



## MCoder (13. April 2007)

"CharEnumerator" liegt direkt im System-Namespace, also *using namespace System;*.
Für solche Fragen ist ein Blick in die MSDN sehr zu empfehlen.

Gruß
MCoder


----------



## Termy2007 (14. April 2007)

Ich gebs auf!
Gibts da nix besseres, was auch wirklich auf C++ 2005 oder 2003 abgestimmt ist?
Die C-Funktionen sind mir ein wenig zu anfällig für Fehler (zumindest unter C++)!!

Im Grunde braucht man gar nicht so viel:
- Funktion, die den eingegebenen Text im seine "Einzelzeichen" zerlegt
- Funktion, die das jeweilige Zeichen umformt
- Funktion, die die Umformung in einen String umwandelt

Das alles haben wir ja schon und nach ein paar Veränderungen hat das Kompilieren auch gut funktioniert.....aber das Programm stürzt dann on-the-run beim Umformen ab!

Vor allem das Zerlegen wäre mir wichtig! Die anderen C-Codes haben funktioniert!

Freue mich auf Antworten!
Mfg Termy 2007


----------



## pschilling (14. April 2007)

Welche C-Funktionen verwendest du denn ?

Ich habe mir ne kleine Demoapplikation gebastelt die mir genau deine gewünschten Umwandlungen durchführt. 

Habe aber nur mit bis zu 20 Zeichen langen Texten getestet.

In meinem code wird keine reine c Funktion verwendet!

Du beschreibst dein Schritte, die zu tun hast, doch ziemlich genau:
[ZITAT}
Im Grunde braucht man gar nicht so viel:
- Funktion, die den eingegebenen Text im seine "Einzelzeichen" zerlegt
- Funktion, die das jeweilige Zeichen umformt
- Funktion, die die Umformung in einen String umwandelt
[/ZITAT}

Dann mach doch genau des ;-)
Ich schreibe mir meine Funktionen lieber selber, anstatt Stundenlang nach einer existierenden Lösung zu finden.

Dafür wende ich maximal 1 Stunde auf!

Viel Erfolg,

Peter


----------



## Termy2007 (14. April 2007)

Hallo!
Mein Problem war folgendes:

```
CharEnumerator enumerator = txt.GetEnumerator();
```
Hier hat mir der Compiler irgendwas von "cannot convert to int" ausgegeben...und dann hatte ich noch ein Problem mit der Initialisierung vom StringBuilder:

```
StringBuilder sb = new StringBuilder();
```
Da hat er mir gesagt, dass er die gewünschte Funktion nicht aufrufen kann!

Naja! Jedenfalls hab ichs mal anders versucht:

```
progressBar1->Value = 0;
				 progressBar1->Maximum = 5;//Convert::ToInt32(textBox1->Text->GetEnumerator());

				 System::String ^text = textBox1->Text;
				 int i = 1;
				 int text_lenth = 5;//progressBar1->Maximum; 
				 int text2_lenth = 0;//Convert::ToInt32(textBox2->Text->GetEnumerator());
				

				 while (i <= text_lenth)
				 {
					 char current_char = Convert::ToChar(text->Substring(i, 1));
					 Int16 myInt = (short)current_char;
                     textBox2->Text->Insert(text2_lenth, myInt >= 128?"1":"0");
                     if (myInt >= 128) myInt -= 128;
                     textBox2->Text->Insert(text2_lenth, myInt >= 64? "1" : "0");
                     if (myInt >= 64) myInt -= 64;
                     textBox2->Text->Insert(text2_lenth, myInt >= 32? "1" : "0");
                     if (myInt >= 32) myInt -= 32;
                     textBox2->Text->Insert(text2_lenth, myInt >= 16 ? "1" : "0");
                     if (myInt >= 16) myInt -= 16;
                     textBox2->Text->Insert(text2_lenth, myInt >= 8 ? "1" : "0");
                     if (myInt >= 8) myInt -= 8;
                     textBox2->Text->Insert(text2_lenth, myInt >= 4 ? "1" : "0");
                     if (myInt >= 4) myInt -= 4;
                     textBox2->Text->Insert(text2_lenth, myInt >=  2 ? "1" : "0");
                     if (myInt >= 2) myInt -= 2;
                     textBox2->Text->Insert(text2_lenth, myInt >= 1 ? "1" : "0");
                     if (myInt >= 1) myInt -= 1;

					 i++;

				 }
```
Kompilieren geht! Doch während das Programm läuft, ich meine 5 Testzeichen eingebe und dann auf "Zu Binary" drücke kommen Runtime-Errors. Das liegt momentan an der Substring Funktion! Hab ich wohl noch nicht richtig verstanden!

Hast du (oder auch andere) einen Tipp für mich?


----------



## pschilling (14. April 2007)

Hi,

dein Problem ist folgendes:

Du iterierst über den String 'txt' mit :



```
int i = 1;
    while (i <= text_lenth)
    {
    }
```

Das muss aber so aussehen :


```
int i = 0;
    while (i < text_lenth)
    {
    }
```

Indizes beginnen immer bei 0. 

Du bist bei deiner Schleife über die Stringlänge hinausgeschossen. Das knallt immer.

Iterationen über Arrays immer von 0 bis length - 1.

Aber deine Probleme mit dem Compiler versteh ich immer noch nicht.

Du verwendest doch auch MS VS2005 oder?

Ich habe ein neues c#-Windows Projekt gestartet, den Code aus meinem ersten Beitrag reingeschrieben, kompiliert und es lief sofort!


Ich poste dir jetzt noch mal meinen gesamten Quelltext meiner Form. 
Vielleicht fehlt dir ja die richtige using Anweisung


```
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string txt = textBox1.Text;
            StringBuilder sb = new StringBuilder();

            CharEnumerator enumerator = txt.GetEnumerator();
            while (enumerator.MoveNext())
            {
                Char c = enumerator.Current;

                Int16 myInt = (short)c;
                sb.Append(myInt >= 128 ? "1" : "0");
                if (myInt >= 128) myInt -= 128;
                sb.Append(myInt >= 64 ? "1" : "0");
                if (myInt >= 64) myInt -= 64;
                sb.Append(myInt >= 32 ? "1" : "0");
                if (myInt >= 32) myInt -= 32;
                sb.Append(myInt >= 16 ? "1" : "0");
                if (myInt >= 16) myInt -= 16;
                sb.Append(myInt >= 8 ? "1" : "0");
                if (myInt >= 8) myInt -= 8;
                sb.Append(myInt >= 4 ? "1" : "0");
                if (myInt >= 4) myInt -= 4;
                sb.Append(myInt >= 2 ? "1" : "0");
                if (myInt >= 2) myInt -= 2;
                sb.Append(myInt >= 1 ? "1" : "0");
                if (myInt >= 1) myInt -= 1;
                sb.Append(" ");
            }

            textBox2.Text = sb.ToString();

        }
    }
}
```

Mit dem Code kann ich einen beliebig langen Text in einen binären String umwandeln.

Bis denne,

Peter


----------



## Termy2007 (14. April 2007)

Hallo pschilling



> Das muss aber so aussehen :
> 
> 
> ```
> ...



Wenn ich das so mache! Passiert gar nichts mehr, wenn ich den "To Binary" Button drücke.



> Du verwendest doch auch MS VS2005 oder?


Nicht ganz! MS VC++ 2005 Express



> ```
> using System;
> using System.Collections.Generic;
> using System.ComponentModel;
> ...



Braucht man die wirklich alle?
Ich werds mal mit allen versuchen! Ich meld mich wenns funkrioniert/nicht funktioniert hat.

Mfg
Termy2007


----------



## Termy2007 (14. April 2007)

So! Nach etwas Umformung hat es funktioniert! Aber ein Fehler bleibt!!

Hier der jetzige Code:

```
String ^txt = textBox1->Text;
	     StringBuilder sb = gcnew StringBuilder(); //Hier passiert der Fehler!

                 CharEnumerator ^enumerator = txt->GetEnumerator();
                 while (enumerator->MoveNext())
                 {
                     Char c = enumerator->Current;

                     Int16 myInt = (short)c;
                     sb.Append(myInt >= 128 ? "1" : "0");
                     if (myInt >= 128) myInt -= 128;
                     sb.Append(myInt >= 64 ? "1" : "0");
                     if (myInt >= 64) myInt -= 64;
                     sb.Append(myInt >= 32 ? "1" : "0");
                     if (myInt >= 32) myInt -= 32;
                     sb.Append(myInt >= 16 ? "1" : "0");
                     if (myInt >= 16) myInt -= 16;
                     sb.Append(myInt >= 8 ? "1" : "0");
                     if (myInt >= 8) myInt -= 8;
                     sb.Append(myInt >= 4 ? "1" : "0");
                     if (myInt >= 4) myInt -= 4;
                     sb.Append(myInt >= 2 ? "1" : "0");
                     if (myInt >= 2) myInt -= 2;
                     sb.Append(myInt >= 1 ? "1" : "0");
                     if (myInt >= 1) myInt -= 1;
				 }

            textBox2->Text = sb.ToString();
```

Und hier der Fehler:

```
error C2664: 'System::Text::StringBuilder::StringBuilder(int)': Konvertierung des Parameters 1 von 'System::Text::StringBuilder ^' in 'int' nicht möglich
```

Frag mich bitte nicht, was das soll!

Mfg
Termy2007


----------



## fuxi019 (14. April 2007)

Hi,ich hätte mal eine frage warum dieses program nicht funktioniert,fehler sind keine darin.Also ausführen kann es das C++ aber nur bis zur if-verzweigung und dann muss ich wieder abbrechen.WEIß wer warum?


mfg


#include<iostream>
using namespace std;


void main()
{									//Vereinbarungsteil
 int gbd;
 char nm,f,p;



cout<<endl<<" Bitte gbd eingeben         "<<endl;
cin>>gbd;
cout<<endl<<" Bitte nm eingeben         "<<endl;
cin>>nm;



if(nm == f)					//weg

cout<<endl<<"Mein name ist: fuchsi"<<endl;

	else
if(nm == p)

cout<<endl<<"Mein name ist: patsi"<<endl;

cout<<endl<<"Mein Geburtsdatum ist: "<<gbd<<endl;
cout<<endl<<"Mein name ist: "<<nm<<endl;

}


----------



## pschilling (14. April 2007)

Hallo Termi,

mit dem Code


```
int i = 0;
    while (i < text_lenth)
    {
    }
```

wollte ich dir nur deinen Fehler in der Schleifenbedingung aufzeigen. Den Inhalt musst du natürlich schon drinnlassen, damit was passiert ;-)

Hallo fuxi019,

der Fehler, der bei dir in der if-Bedingung auftritt ist der, dass du gegen eine uninitialisierte Variable auf Gleichheit prüfst

char f;
...
if(nm == f) //weg

Du deklarierst zwar die variable f, initialisierst diese aber vor Ihrer ersten verwendung nicht

Dies solltest du immer beim programmieren beachten! Variablen immer initialisieren.

Das selbe gilt natürlich auch für die variable p ;-)

Schreibe es so:


```
char a = 'a'; // Erzeuge Variable mit Namen a und weise ihr den char-Wert 'a' zu
    char b = 'b';
    cin >> b;

    if( a == b ) { // Entspricht der eingegebene Wert, welcher jetzt in b gespeichert istdem Wert, welcher in a steht(also 'a').

    }
```

Ciao,

Peter


----------



## Termy2007 (15. April 2007)

Nagut..hat zwar nix mit mir zu tun...aber egal.
Ich geb auf! Vielleicht werd ich es in einer Woche nochmal mit einem neuen Ansatz versuchen. Oder jemand erklärt sich bereit mir die ganze Geschichte für C++ zu erklären! So dass es funktioniert!

Inmoment hab ich nur noch das Problem, dass er mir des txt->GetEnumerator() nicht in einen int-Wert umwandeln will! Sonst scheint alles zu funktionieren.
Hat jemand eine Idee?


----------



## pschilling (15. April 2007)

Versuchs doch mal mit txt.GetEnumerator().


----------



## Termy2007 (15. April 2007)

Das ist C#!
In C++ muss es txt->GetEnumerator() heißen!


----------



## pschilling (15. April 2007)

Hi termy,

das war ein tierisches Missverständnis von mir 

Ging die ganze Zeit von c# aus.

Hier noch mal den ganzen Kram in reinem C: 


```
// Diese Funktion konvertiert einen String in seine entsprechende binäre Darstellung
char *convertStringToBinaryString(char *in) {
    int len = strlen(in);
    char *retBuff = new char[len*9-1]; // Neues char array erzeugen mit genausoviel platz, wie die binäre darstellung brauch
    memset(retBuff,0,len*9-1);
    int j = 0; // Iteratorvariable, um über das Ziel-Chararray zu laufen
    for( int i = 0; i < len; i++ ) {
        int x = in[i];
        retBuff[j++] = (x >= 128 ? '1' : '0');
        if (x >= 128) x -= 128;
        retBuff[j++] = (x >= 64 ? '1' : '0');
        if (x >= 64) x -= 64;
        retBuff[j++] = (x >= 32 ? '1' : '0');
        if (x >= 32) x -= 32;
        retBuff[j++] = (x >= 16 ? '1' : '0');
        if (x >= 16) x -= 16;
        retBuff[j++] = (x >= 8 ? '1' : '0');
        if (x >= 8) x -= 8;
        retBuff[j++] = (x >= 4 ? '1' : '0');
        if (x >= 4) x -= 4;
        retBuff[j++] = (x >= 2 ? '1' : '0');
        if (x >= 2) x -= 2;
        retBuff[j++] = (x >= 1 ? '1' : '0');
        if( i == len-1) {
            retBuff[j++] = '\0';
        }
        else {
            retBuff[j++] = ' '; // Leerzeichen nach einer gesamten Binären Darstellung (8-Zeichen) einfügen
        }
    }
    return retBuff;
}
```

Vergiss nicht, den Speicher (retBuff) in der aufrufenden Funktion zu löschen 

Wenn dir das auch nicht auf die Sprünge hilft, weiss ichs auch net..

Gruß,

Peter


----------



## Termy2007 (15. April 2007)

Solange das jetzt funktioniert! ^^
Und wie dreht man das jetzt um?
Nur damit ich mal sehe wie ein Profi das macht! ^^


----------



## pschilling (15. April 2007)

Also Profi würd ich mich jetzt net nennen, vielleicht recht erfahren ;-)

Umgekehrt sieht das in reinem C dann so aus:


```
// Diese Funktion konvertiert einen genau 8Zeichen langen binärstring in den entsprechenden Char-Wert um
char CmfcdlgApp::convertBinaryStringCharToChar(char *in) {
    if( strlen(in) != 8 ) {
        // Kein gültiger binärstring
        return (char)0;
    }
    int i = 128;
    int value = 0;
    for( int j = 0; j < 8; j++ ) {
        char c = in[j];
        if( c == '1') {
            value += i;
        }
        else if(c != '0' ) {
            // Kein gültiger Binärstring !! Nur 1 und 0  sind erlaubt
            return (char)0;
        }
        i /= 2;
    }
    return (char)value;
}
```


Und jetzt komm doch endlich mal mit neuen Fragen rüber. 
Keinen Bock mehr auf Binärstrings ;-)

Gruß,

Peter


----------



## Termy2007 (15. April 2007)

pschilling hat gesagt.:


> Und jetzt komm doch endlich mal mit neuen Fragen rüber.
> Keinen Bock mehr auf Binärstrings ;-)



Hab ich schon! ^^

Hier: http://www.tutorials.de/forum/c-c/271427-c-string-string-konvertieren.html


----------

