Resource icon

Kleine Sammlung von Konvertierungsroutinen für c++

Programmiersprache(n)
c++
Betriebssystem(e)
Linux
Hallo Leute!

Hier mal eine ganz kleine Sammlung von Funktionen um Strings in float- bzw. double-Variable umzuwandeln und umgekehrt.

Code:
/** Erst mal die header einbinden */
#include <iostream>
#include <sstream>
#include <complex.h>

/** Wandelt double in std::string um */
std::string lftoa(double number)
{
std::ostringstream buff;
buff << number;
return buff.str();
}

/** Wandelt int in std::string um */
std::string _itostr(int number)
{
std::ostringstream buff;
buff << number;
return buff.str();
}

/** Wandelt std::string in long double um */
long double atof(std::string zawo)
{
long double rewer = 0;
std::istringstream b(zawo);
b >> rewer;
return rewer;
}

/** Anzahl der Nachkommastellen von float bestimmen
    * und in einen string umwandeln */
#include <string>
#include <iomanip>

string convertFloat(float value, int stellen = 8)
{
  std::ostringstream o;
  o.setf(ios::fixed,ios::floatfield);
  if (!(o << setprecision(stellen) << value))
    return "";
  return o.str();
}
Eine Funktion zum runden für c könnte so aussehen:
Code:
double runden(double zahl, unsigned int Stellen)
{
  double teiler = 0;
  teiler = pow(10, Stellen);
  zahl *= teiler;
   //cout << "1 Zahl: " << zahl << "teiler: " << teiler << endl;
  if (zahl >= 0)  zahl = floor(zahl + 0.5);
  else            zahl = ceil(zahl - 0.5);
  //cout << "2 zahl: " << zahl << "teiler: " << teiler << endl;

    zahl /= teiler;

  return zahl;
}
Nun etwas was ich irgendwo im Web gefunden habe. Eine Funktion zum Konvertieren
von Dezimalzahlen in ein Zahlensystem von 2 bis 36.
Hier gleich der code mit Beispiel(sehr kurz):
Code:
#include <iostream>
using namespace std;

string toBase (int base, int num)
{
    static string charset = "0123456789abcdefghijklmnopqrstuvwxyz";
    if (!num)
        return "";
    return toBase(base, num/base) + charset[num%base];
}

int main() // test
{
    cout << toBase (10, 27) << endl;  // 27 dez.
    cout << toBase (2, 27) << endl;   // 27 binär
    cout << toBase (16, 27) << endl;  // 27 hex
    cout << toBase (8, 27) << endl;   // 27 oktal
    cout << toBase (5, 27) << endl;   // 27 in base 5
}
Hier eine Alternative für abs:
Code:
double dabs(double wert)
{
int vzbyte;
union test
  {
   double absolutwert;
   unsigned char a[8];
  }tst;

if ((sizeof(double)) == 8)
  {
   tst.absolutwert = wert;
   vzbyte = tst.a[7] & 128;
   if(vzbyte != 0) tst.a[7] &= 127;
}
  else tst.absolutwert *= -1;
return tst.absolutwert;
}
Beispiel für diese Alternative:
Code:
* main.c
* Copyright (C) 2017 Josef Wismeth
*
* abstest is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* abstest is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>

double dabs(double wert)
{
int vzbyte;
union test
  {
   double absolutwert;
   unsigned char a[8];
  }tst;

if ((sizeof(double)) == 8)
  {
   tst.absolutwert = wert;
   vzbyte = tst.a[7] & 128;
   if(vzbyte != 0) tst.a[7] &= 127;
}
  else tst.absolutwert *= -1;
return tst.absolutwert;
}


int main()
{
double plus = -25, abswert;

abswert = plus;

printf("Vorzeichenbit-Test\n");
printf("Länge der Datentypen.\n");
printf("Datentyp char.......: %ld\n", sizeof(char));
printf("Datentyp short......: %ld\n", sizeof(short));
printf("Datentyp int........: %ld\n", sizeof(int));
printf("Datentyp long.......: %ld\n", sizeof(long));
printf("Datentyp double.....: %ld\n", sizeof(double));
printf("Datentyp long double: %ld\n", sizeof(long double));
printf("dabs-Test:\n");
printf("Pluswert.................: %lf\n", plus);
printf("abswert alt..............: %lf\n", abswert);

abswert = dabs(plus);

printf("abswert neu..............: %lf\n", abswert);

return (0);
}
Um die folgenden Funktionen zu verstehen, zuerst einmal eine mit der man
eine unsigned char-Variable (wegen dem Vorzeichen-Bit) in einen c++String umwandeln kann:

Code:
std::string chartobin(unsigned char letter)
{
unsigned int slei, dum, testwert;
std::string binwert;

/* Ininitalisert die 8 Binärstellen mit Null */

for (slei = 0; slei <= 7; slei++)
  {
   testwert = 128 >> slei;  /* Bit7(128dez) ist auf Char-Nr.0 */
   dum = letter & testwert;
   if (dum != 0)  binwert += '1';
    else          binwert += '0';
  }
return binwert;
}
Etwas erweitert kann man diese Funktion dafür verwenden unsigned short binär in einen
char-Array darzustellen:
Code:
/** wandelt die in Parameter 1 als unsigned short gegebene Dezimalzahl
  * in einen char-String um(Parameter2), ist Parameter 3(vornullen) 0
  * dann werden die Vornullen bei der Umwandlung unterdrückt, sonst
  * erfolgt die Darstellung mit Vornullen
  */
void dectoshort( unsigned short zahl, char zudi[], short vornullen)
{
char wort[35], worz[35];
int slei, sleib;
unsigned short dum2, testwert, kon = 1;
// String vorbereiten
for (slei = 0; slei <= 34; slei++)
wort[slei] = worz[slei] = '\0';

kon <<= 15;

for (slei = 0; slei <= 15; slei++)
  {
   testwert = kon >> slei;  /* Achtung: Bit30 ist auf Char-Nr.0 */
   dum2 = zahl & testwert;
   if (dum2)  wort[slei] = '1';
    else     wort[slei] = '0';
  }
// Beginn des Ende der Vornullen feststellen
for (slei = 0; slei <= 15; slei++)
if (wort[slei] == '1') break;
// wort ist mit Vornullen, worz ohne Vornullen
for (sleib = 0; sleib <= 32; sleib++)
        {
         worz[sleib] = wort[slei];
         if (wort[slei] == '\0')
          break;
         slei++;
        }
// Ergebnis in den Parameter 2 übertragen
for (slei = 0; slei <= 15; slei++)
  if ( vornullen == 0)
   zudi[slei] = worz[slei]; /* wenn vornullen = 0 dann ohne Vornullen */
    else
     zudi[slei] = wort[slei]; // wenn vornullen =1 dann mit vornullen

}
Damit kann man sich aussuchen, ob man die Zahl mit oder ohne Vornullen haben will.

Wie man übrigens eine 4-Byte breite Fließkammazahl (float) mit Hilfe von Unions
darstellen kann, hier ein Programmbeispiel dazu:

Zunächst einmal der Header "floatintunion.h";
Code:
#ifndef FLOATINTUNION_H_INCLUDED
#define FLOATINTUNION_H_INCLUDED

#include <iostream>
#include <iomanip>

/**Achtung:
  * Im Speicher ist die Reihenfolge
  * mwertbytes[3], mwertbytes[2], mwertbytes[1], mwertbytes[0]
  * da mwertbytes[3] das Vorzeichenbit beo float enthält
*/
union einheit
{
  float messwert;
  unsigned char mwertbytes[4];
  unsigned short mwertshort[2];
};

void buzubin(unsigned int letter, char wort[]);
void zeigeWerte(union einheit ehe);
void dectoshort(unsigned short zahl, char zudi[], short vornullen);

#endif // FLOATINTUNION_H_INCLUDED
Jetzt die dazugehörige source "floatintunion.cxx":
Code:
#include "floatintunion.h"


/* -----------------------------------------------------------------------
* Die Funktion buzubin wandelt den als int-Wert gegebenen Parameter 1
* in einem Binärwert vom Typ BYTE um. Dieser wird in Parameter 2 als
* String gespeichert. Es werden dabei immer 8 Stellen des Binärwertes
* gezeigt. Das neunte Byte im String dient zur String-Terminierung.
*Aufruf:  buzubin( Char-Wert_als_int, Binärwert_als_String);
*/

void buzubin(unsigned int letter, char wort[])
{
unsigned int slei, dum, testwert;
if ((letter < 0) || (letter > 255)) goto finito;

/* Ininitalisert die 8 Binärstellen mit Null */
for (slei = 0; slei <= 11; slei++)
  wort[8] = '\0';

for (slei = 0; slei <= 7; slei++)
  {
   testwert = 128 >> slei;  /* Bit7(128dez) ist auf Char-Nr.0 */
   dum = letter & testwert;
   if (dum != 0)  wort[slei] = '1';
    else          wort[slei] = '0';
  }
finito:    ;
}

void zeigeWerte(union einheit ehe)
{
int i;
char binwort[15], longwort[100];

//Werte von unsigned char zeigen
  std::cout << "floatwert: " << ehe.messwert << "     binaer: ";

  for (i = 3; i >= 0; i--)
   {
    buzubin(ehe.mwertbytes[i], binwort);
    std::cout << binwort << " ";
   }
   std::cout <<std::endl;
std::cout <<"Nun als unsigned char: " << std::endl;
for (i = 3; i >= 0; i--)
  {
   buzubin(ehe.mwertbytes[i], binwort);
   std::cout << "mwertbytes[" << i << "] = " << std::setw(3) << (int)ehe.mwertbytes[i] << "   Binaer: " <<  binwort << std::endl;
  }
//Werte von unsigned char zeigen
std::cout << std::endl << "Nun als unsigned short: " << std::endl;
for (i = 1; i >= 0; i--)
  {
   dectoshort( (unsigned long)ehe.mwertshort[i], longwort, 1);
   std::cout << "mwertshort[" << i << "] = " << std::setw(3) << (int)ehe.mwertshort[i] << "   binaer: " << longwort <<std::endl;
  }
std::cout << "---------------------------------------------------------" << std::endl;
}

/** wandelt die in Parameter 1 als unsigned short gegebene Dezimalzahl
  * in einen char-String um(Parameter2), ist Parameter 3(vornullen) 0
  * dann werden die Vornullen bei der Umwandlung unterdrückt, sonst
  * erfolgt die Darstellung mit Vornullen
  */
void dectoshort( unsigned short zahl, char zudi[], short vornullen)
{
char wort[35], worz[35];
int slei, sleib;
unsigned short dum2, testwert, kon = 1;
// String vorbereiten
for (slei = 0; slei <= 34; slei++)
wort[slei] = worz[slei] = '\0';

kon <<= 15;

for (slei = 0; slei <= 15; slei++)
  {
   testwert = kon >> slei;  /* Bit30(1073741824dez) ist auf Char-Nr.0 */
   dum2 = zahl & testwert;
   if (dum2)  wort[slei] = '1';
    else     wort[slei] = '0';
  }
// Beginn des Ende der Vornullen feststellen
for (slei = 0; slei <= 15; slei++)
if (wort[slei] == '1') break;
// wort ist mit Vornullen, worz ohne Vornullen
for (sleib = 0; sleib <= 32; sleib++)
        {
         worz[sleib] = wort[slei];
         if (wort[slei] == '\0')
          break;
         slei++;
        }
// Ergebnis in den Parameter 2 übertragen
for (slei = 0; slei <= 15; slei++)
  if ( vornullen == 0)
   zudi[slei] = worz[slei]; /* wenn vornullen = 0 dann ohne Vornullen */
    else
     zudi[slei] = wort[slei]; // wenn vornullen =1 dann mit vornullen

}
Nun die main.cc
Code:
#include <iostream>
#include "floatintunion.h"


int main()
{
union einheit flint;

std::cout << "Test" << std::endl;
std::cout << "length of float: " << sizeof(float) << std::endl;
std::cout << "length of short: " << sizeof(short) << std::endl << std::endl;

flint.messwert = -123.4567;

//Werte von unsigned char zeigen
zeigeWerte(flint);

flint.messwert = 0;

std::cout << std::endl <<"Jetzt alle Variablen geloescht:" << std::endl;

//Werte von unsigned char zeigen
zeigeWerte(flint);

flint.mwertshort[0] = 59861;
flint.mwertshort[1] = 17142;

std::cout << std::endl << "Jetzt Zuweisung von Werten an short-Variable:" << std::endl;

//Werte von unsigned char zeigen
zeigeWerte(flint);

//flint.messwert = 0;
//std::cout << std::endl <<"Jetzt alle Variablen geloescht:" << std::endl;

  //mwertbytes[4];


return EXIT_SUCCESS;
}
Dieses Beispiel wurde auf SUSE Linux tumbleweed mit dem Kernel 4.16.12-2 default
mit der IDE Anjuta 3.28.0 mit gcc 7.2.1 Linux/unicode - 64 bit erstellt.



Nun eine Routine, mit der man signed char-Variable zu unsigned int umwandeln kann:
Code:
//Umwandlung von unsigned char zu int
int uchartoint(unsigned char letter)
{
int rewer = 0;
letter &= 255;
    if ( letter > 127)
  rewer = letter - 256;
   else rewer = (int)letter;
return rewer;
}

//Die Umkehr-Funktion dazu:
//Umwandlung von signed char zu int
int atoint(char letter)
{
int rewer;
if ( letter < 0)
  rewer = letter + 256;
   else rewer = (int)letter;
return rewer;
}
Diese sind notwendig, wenn man mit Verschlüsselungsroutinen arbeitet, da
put und get in c++ nur mit signed-Datentypen arbeiten kann.
Hierzu ein Beispiel:
Code:
//Liest ein Byte aus einer Datei als int-Variable ein, wichtig, da zum Beispiel deutsche Umlaute bei UTF8
//mit 2 bis 4 Bytes gespeichert werden.
//signed char wird in unsigned int umgewandelt  um besser chiffrieren zu können, wegen dem Vorzeichenbit.
int getint(std::fstream *datei)
{
int rewer = 0;
char buchs;
datei->get(buchs);
rewer = atoint(buchs);

return rewer;
}

//wandelt  einen 4-Byte int-Wert in 4 einzelne unsigned char um

void Talarius::intzuchar(int zuza)
{
union intpart{
unsigned int erge;
unsigned char ipart[4];
} ipt;

ipt.erge = zuza;

intteile[0] = ipt.ipart[0];
intteile[1] = ipt.ipart[1];
intteile[2] = ipt.ipart[2];
intteile[3] = ipt.ipart[3];
}

// Wandelt 4 einzelne unsigend char in sigend int um, bei chiffrieren mit unsigend char ausreichend
int Talarius::charzuint(unsigned char intteile[4])
{
union intpart{
unsigned int erge;
unsigned char ipart[4];
} ipt;

ipt.ipart[0] = intteile[0];
ipt.ipart[1] = intteile[1];
ipt.ipart[2] = intteile[2];
ipt.ipart[3] = intteile[3];

return ipt.erge;
}
void putint(std::ofstream *datei, int letter)
{
char buchs;
buchs = inttochar(letter); // Umwandlung von signed int zu signed char, da put nur signed char schreiben kann
datei->put(buchs);
}

//Die Schreibroutine könnte so aussehen:
int SourceFile::fputDWORD(unsigned int letter, std::ofstream *datei)
{
int slei, rewer = 0;
unsigned int DWTeile[4] = {0,0,0,0};

DWTeile[3] = (letter >> 24);
DWTeile[2] = ((letter >> 16) & 255);
DWTeile[1] = ((letter >>  8) & 255);
DWTeile[0] = (letter & 255);

for (slei = 3; slei >= 0; slei--)
  datei->put(DWTeile[slei]);

return rewer;
}
Wer Schwierigkeiten hat einen QString in eindimensionale char-Arrays umzuwandeln hier eine Routine:
Code:
// Wandelt QString in eindimensionales char-Array um
void getCHname(QString dtnam,  char erge[], int arraygroesse)
{
int slei;
//char *name;
//name = dtnam.toAscii().data();  // kopiert einen QString in einen ASCII-String ist aber obsolet

QByteArray name = dtnam.toLatin1(); // neue Variante in QT

//An die einzelnen Bedürfnisse bitte anpassen, arraygroesse - 2 wegen der Nullterminierung des c-Strings
for (slei = 0; slei <  (arraygroesse - 2); slei++)
  {
   erge[slei] = name[slei];
   if (name[slei] == '\0') break;
  }
}
Hier eine abgewandelte Funktion zur Konvertierung von einem ASCII-String in eine string-Variable:
Code:
/// Wandelt einen ASCII-String in einen cpp-String um
std::string a_to_str(char puffer[])
{
std::ostringstream buff;
buff << puffer;
return buff.str();
}
Hier einige Möglichkeiten um die Bits bei unsigned char einzeln zu setzen oder zu löschen.
Wichtig bei chiffrieren:
Code:
//Parameter 1 von 0 bis 7
unsigned char getbitval(int bitnum, unsigned char wert)
{
unsigned char suwer =  1;
unsigned char sumwer, dumwer;

if (bitnum < 14)
{
  sumwer = wert & (suwer << bitnum);
  if (sumwer) dumwer = 1;
   else dumwer = 0;
}
return dumwer;
}
//Parameter 1 von 0 bis 7
unsigned char setbitval(unsigned char wert, int bitnum, int setzwert)
{
unsigned char istwert, bitwert, erge = 0;

istwert = getbitval(bitnum, wert);
if (istwert == setzwert) { erge = wert;} // std::cout << "*1*\n"; }
  else
   {
    bitwert = 1 << bitnum;
    //std::cout << "Setzwert: " << bitwert << std::endl;
    if((istwert == 0) && (setzwert == 1))
      {
       //std::cout << "*2erge= " << wert;
       erge = wert | bitwert;
      }
    if((istwert == 1) && (setzwert == 0))
      {
       //std::cout << "*3erge= " << wert;
       erge = wert & (255 - bitwert);
      }
   }

//std::cout << " **erge= " << erge << std::endl;
return erge;
}
Wer sich übrigens mal gefragt hat wie das mit den Einskomplement und Zweikomplement bei
der Bildung von signed char aussieht, hier ein Beispielprogrmm, das die Werte als Liste anzeigt.
Es veranschaulicht auch die Wirkung von setw() zur formatierten Textausgabe in c++.
Zuerst der header:
Code:
/**Datei zweikomp.h für das Programm zweikomp.cc */

#include <iostream>
#include <iomanip> // wegen setw

std::string chartobin(unsigned char letter);
int uchartoint(unsigned char letter);
int atoint(char letter);
Nun die dazugehöroge Source-Datei für die Funktionen:
Code:
/**Datei zweikomp.cxx für das Programm zweikomp.cc */

#include "zweikomp.h"

std::string chartobin(unsigned char letter)
{
unsigned int slei, dum, testwert;
std::string binwert;

/* Ininitalisert die 8 Binärstellen mit Null */

for (slei = 0; slei <= 7; slei++)
  {
   testwert = 128 >> slei;  /* Bit7(128dez) ist auf Char-Nr.0 */
   dum = letter & testwert;
   if (dum != 0)  binwert += '1';
    else          binwert += '0';
  }
return binwert;
}

//Umwandlung von unsigned char zu int
int uchartoint(unsigned char letter)
{
int rewer = 0;
letter &= 255;
    if ( letter > 127)
  rewer = letter - 256;
   else rewer = (int)letter;
return rewer;
}

//Umwandlung von signed char zu int
int atoint(char letter)
{
int rewer;
if ( letter < 0)
  rewer = letter + 256;
   else rewer = (int)letter;
return rewer;
}
Jetzt main.cc:
Code:
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-  */
/*
* main.cc
* Copyright (C) 2018 Josef Wismeth <josef@localhost>
*
* zweikomp is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* zweikomp is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "zweikomp.h"


int main()
{
unsigned int zkomp;
int i, ekomp, s_int, ekp;
std::string binaer, einskomp;

std::cout << "Zahlentest   unsigned -> Einskomplement -> Zweikomplement" << std::endl;

  for (i = 0; i <= 255; i++)
  {
   ekomp = ~i & 255;
   binaer = chartobin((unsigned char)i);
   s_int = uchartoint((unsigned char)i);
   einskomp = chartobin((unsigned char)ekomp);

   ekp = ekomp;
    if (ekp <= 127) ekp *= -1;
     else ekp = i;
   std::cout << "unsigned char: " << std::setw(3) << i << " Binär=" << binaer << "   Einskomp=" << std::setw(4);
   std::cout << ekp <<" binaer=" << einskomp << "   Zweikomp=" << std::setw(4) << s_int << std::endl;
  }


return EXIT_SUCCESS;

}
Hier übrigens ein Beispiel zur Konvertierung, das ich im Netz gefunden habe:
Code:
#include <iostream>
using namespace std;

string toBase (int base, int num)
{
    static string charset = "0123456789abcdefghijklmnopqrstuvwxyz";
    if (!num)
        return "";
    return toBase(base, num/base) + charset[num%base];
}

int main() // test
{
    cout << toBase (10, 27) << endl;  // 27 dez.
    cout << toBase (2, 27) << endl;   // 27 binär
    cout << toBase (16, 27) << endl;  // 27 hex
    cout << toBase (8, 27) << endl;   // 27 oktal
    cout << toBase (5, 27) << endl;   // 27 in base 5
}
Will man übrigens Zahlen der Basis 2 bis 36 zu einer anderen Basis (2 bis 36) umwandeln, etwa
von Basis 16 zu Basis sollte man dies nur indirekt tun. Also zuerst wieder mit Basis 10. Dann die erneute
Umwandlung.

Hierzu wieder ein Beispiel:
Wieder zuerst der Header:
Code:
#ifndef ZAHLWANDL_H_INCLUDED
#define ZAHLWANDL_H_INCLUDED

#include <iostream>
#include <termios.h>
#include <unistd.h>
#include <stdio.h> /// wegen getchar
#include <string.h>
#include <math.h>



int getch();
char* itoa(int value, char* result, int base);
int xwertzudez(int *wert, char puffer[], int basis);


#endif // ZAHLWANDL_H_INCLUDED
Dann die dazugehörige Source-Datei:
Code:
#include "zahlwandl.h"

int getch()
{
    struct termios oldt, newt;
    int ch;
    tcgetattr( STDIN_FILENO, &oldt );
    newt = oldt;
    newt.c_lflag &= ~( ICANON | ECHO );
    tcsetattr( STDIN_FILENO, TCSANOW, &newt );
    ch = getchar();
    tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
    return ch;
}

   /** C++ version 0.4 char* style "itoa":
     * Written by Lukás Chmela
     * Released under GPLv3.
     */
char* itoa(int value, char* result, int base)
{
        // check that the base if valid
        if (base < 2 || base > 36) { *result = '\0'; return result; }

        char* ptr = result, *ptr1 = result, tmp_char;
        int tmp_value;

        do {
            tmp_value = value;
               value /= base;
            *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
        } while ( value );

        // Apply negative sign
        if (tmp_value < 0) *ptr++ = '-';
        *ptr-- = '\0';
        while(ptr1 < ptr) {
            tmp_char = *ptr;
            *ptr--= *ptr1;
            *ptr1++ = tmp_char;
        }
        return result;
}

//Gegenteil von itoa
int xwertzudez(int *wert, char puffer[], int basis)
{
  char zeichen [50];
  int slei, sleib, erge, lenge, zahl, dummy, fehlertest;
  strcpy(zeichen, "0123456789abcdefghijklmnopqrstuvwxyz");

  // Rückgabewert ist -1 falls basis ungueltig
  erge = -1;
  zahl = fehlertest = 0;
  lenge = strlen(puffer); //Feststellen der Stringlänge
  *wert = lenge;

  std::cout << "lenge = " << lenge << "\n";
        // Pruefe ob basis gueltig
  if (basis < 2 || basis > 36) return erge;

  // Test, ob andere Zeichen vorhanden sind
  for (slei = 0; slei < lenge; slei++)
   {
    for (sleib = 0; sleib < basis; sleib++)
     if (zeichen[sleib] == puffer[slei]) fehlertest++;
   }

//Umwandlung des Strings in eine Dezimalzahl
if (fehlertest != lenge)
  {
   erge = -2;
   return erge;
  }

  for (slei = lenge - 1; slei >= 0; slei--)
   {
    dummy = puffer[slei];
    for (sleib = 0; sleib <= 35; sleib++)
     if ((dummy == zeichen[sleib]) && (sleib > 0)) zahl += pow(basis, (lenge -slei -1)) * sleib;
   }
  erge = 0;
  *wert = zahl;

return erge;
}
Jetzt wieder die main.cc:
Code:
#include "zahlwandl.h"
#include <stdlib.h>


int main(void)
{
int wouhi = 8, deza, basis, erge;
char puffer[100];

do
switch(wouhi)
{

default:
      std::cout << std::endl  << "Programm zum umrechnen von Dezimal- und Hexadezimalzahlen" << std::endl << std::endl;
      std::cout << "Programmende..........0" << std::endl;
      std::cout << "dezi in hexa..........1" << std::endl;
      std::cout << "hexa in dezi..........2" << std::endl;
      std::cout << "Basis x in Basis y....3" << std::endl;
      std::cout << std::endl << "Ihre Wahl: " << std::endl;
      std::cin >> wouhi;
    break;

case 0:
    std::cout << "Programmende" << std::endl;
    return EXIT_SUCCESS;
   break;

case 1:
    deza = 0;
    std::cout << "Dezimalzahl?: ";
    std::cin >> deza;
    std::cout << "Hexa = 0x" << std::hex << deza << std::endl;
    wouhi = 8;
   break;

case 2:
     deza = 0;
     std::cout << std::endl << "Hexadezimalzahl?";
     std::cin >> std::hex >> deza; //puffer;
     //erge = xwertzudez(&deza, puffer, 16);
     //std::cout << std::endl << "Rückgabewert: " << erge << "dezimal= " << dec << deza;
     std::cout << "dezimal= " << std::dec << deza;
    wouhi = 8;
  break;

case 3:
     std::cout << std::endl << "Umzuwandelnde Zahl eingeben: ";
     std::cin >> puffer;
     std::cout << std::endl << "Basis dieser Zahl eingeben(von 2 bis 36): ";
     std::cin >> basis;

     erge = xwertzudez(&deza, puffer, basis);
     if (erge == 0)
      {
       std::cout << "Im Dezimalsystem: " << deza << std::endl;

       std::cout << std::endl << "Zielzahlensystem eingeben(2 bis 26): ";
       std::cin >> basis;
       itoa (deza, puffer, basis);
       std::cout << std::endl << "Dezi= " << deza << " Im "<< basis<< "er-System dargestellt: " << puffer;
      }
     else
      {
       std::cout << "Fehlerhafte Zeichen im String\n";
      }
     wouhi = 8;
  break;

}while(wouhi != 0);

return EXIT_SUCCESS;
}
Im letzteren Beispiel ist eine Fehlerkorrektur bei fehlerhafte Eingabe noch nicht implementiert.
Warum?
Ich war zu faul dazu!

Nun noch eine klitzekleine Methode für QT um Variable des Typs long double in QString zu konvertieren.
Das Prinzip ist ähnlich wie bei den ersten Funktionen:
Code:
QString faktorielle::qStringFromLongDouble(const long double myLongDouble)
{
  std::stringstream ss;
  ss << myLongDouble;

  return QString::fromStdString(ss.str());
}

Das Programm Talarius, das das Chiffrieren mit Hilfe von Bitmanipulationen auf Basis der Transposition
veranschaulicht, von mir als Lehrmaterial gedacht, wurde hier schon einmal inklusive Source-Code veröffentlicht.

Eine weitere Funktion kann sehr hilfreich bei Fließkommaberechnungen werden, gerade in gcc bei fmod().
Diese habe ich irgendwo im Netz(stackoverflow?) gefunden:

Code:
/*
double Epsilon(void)
{
double floatEps = 1;

    while (1 + floatEps / 2 != 1)
        floatEps /= 2;
return floatEps;
}
*/
///Angepasst an float:
float floatEpsilon(void)
{
float floatEps = 1;

    while (1 + floatEps / 2 != 1)
        floatEps /= 2;
return floatEps;
}
Folgendes Beispiel erläutert den Einsatz, quasi ein Beispiel für
"kosmetische" Korrektur bei der Ausgabe der Ergebnisse.
Den Source-Code dafür habe ich auf c-plusplus.net gefungen und geringfügig abgeändert:
Code:
#include <iostream>
#include <iomanip> // wegen std::setw(4)
#include <cmath>
/*
double Epsilon(void)
{
double floatEps = 1;

    while (1 + floatEps / 2 != 1)
        floatEps /= 2;
return floatEps;
}
*/
float floatEpsilon(void)
{
float floatEps = 1;

    while (1 + floatEps / 2 != 1)
        floatEps /= 2;
return floatEps;
}

float frunden(float zahl, unsigned int Stellen)
{
  float teiler = 0;
  teiler = pow(10, Stellen);
  zahl *= teiler;
   //cout << "1 Zahl: " << zahl << "teiler: " << teiler << endl;
  if (zahl >= 0)  zahl = floor(zahl + 0.5);
  else            zahl = ceil(zahl - 0.5);
  //cout << "2 zahl: " << zahl << "teiler: " << teiler << endl;

    zahl /= teiler;

  return zahl;
}

int main()
{

    float i = 0, k = 0.05, erge = 0.0, maxprecision;

    maxprecision = floatEpsilon();
    std::cout << "Maximale Genauigkeit bei float: " << maxprecision << std::endl;

    while(i <= 3.0)
    {
     erge = fmod (i, 0.5);
     if ( erge <= maxprecision) erge =0;
     //if ((erge >= 0.99998 * 0.5) && (erge <= 0.5 + 0.00001)) erge = 0.5;
     std::cout <<"fmod(" << std::setw(4) << i << ", 0.5) = " << frunden(erge, 3) << std::endl;
     i += k;
    }

     std::cout << "\n\nOhne frunden:\n\n";

    i = 0;

    while(i <= 3.0)
    {
     erge = fmod (i, 0.5);
     if ( erge <= maxprecision) erge =0;
     std::cout <<"fmod(" << std::setw(4) << i << ", 0.5) = " << erge << std::endl;
     i += k;
    }


    std::cout << "\n\nOhne floatEpsilon und frunden:\n\n";

    i = 0;

    while(i <= 3.0)
    {
     erge = fmod (i, 0.5);
     std::cout <<"fmod(" << std::setw(4) << i << ", 0.5) = " << erge << std::endl;
     i += k;
    }

return EXIT_SUCCESS;
}
Manche werden sich fragen ob die Funktion frunden() nicht ausreichen würde, wozu man den
floatEpsilon() brauchen würde.
Die Funktion floatEpsilon kann dazu verwendet werden, um zum Beispiel über if(maxprecision......)
fehlerhafte Berechnungen zu vermeiden. Zusammen mit meinen Eigenbau zum Ersatz für abs konnte ich so
einen Fehler bei der Verwendung der herkömmlichen Funktion abs() von gcc eingrenzen.
Dieser Fehler verursachte bei der Berechnung mit einer eigenen Version der Funktion
NormInv(double probability) Berechnungsfehler. Ein Beispiel in cpp werde ich in Kürze hier einstellen.



Damit man sich beim Suchen im Netz nicht gleich den Finger abbricht.

Ich wünsche inspiriert zu haben
rustyoldguy
Autor
rustyoldguy
First release
Last update
Bewertung
0,00 Stern(e) 0 Bewertungen
Oben