Hallo Allerseits!
Strings kann man auf verschiedene Weise in ihre Einzelteile aufteilen. Dabei hat man zum Beispiel die Funktion sscanf(in stdio.h) zur Verfügung:
#include <stdio.h>
#include <string.h>
void DEZUBI( unsigned int zahl, char zudi[]) /*22:16 */
{
char wort[35], worz[35];
int slei, sleib;
unsigned int dum2, testwert, kon = 1;
for (slei = 0; slei <= 34; slei++)
wort[slei] = worz[slei] = '\0';
kon <<= 31 ;
for (slei = 0; slei <= 31; slei++)
{
testwert = kon >> slei; /* Bit30(1073741824dez) ist auf Char-Nr.0 */
dum2 = zahl & testwert;
if (dum2) wort[slei] = '1';
else wort[slei] = '0';
}
for (slei = 0; slei <= 31; slei++)
if (wort[slei] == '1') break;
for (sleib = 0; sleib <= 32; sleib++)
{
worz[sleib] = wort[slei];
if (wort[slei] == '\0')
break;
slei++;
}
for (slei = 0; slei <= 32; slei++)
zudi[slei] = worz[slei]; /* ohne Vornullen */
}
int main(int argc, char **argv)
{
int laenge = 0, i;
char satz[] = "Zur Zeit ist 14972 die kleinste langweilige Zahl.";
char strarray[8][48] = {0};
char binzahl[34] = {0};
int zahl = 0;
laenge = strlen(satz);
printf("Satz urspruenglich:\n%s\n", satz);
printf("Laenge in Byte: %d\n", laenge);
sscanf(satz, "%s%s%s%d%s%s%s%s", strarray[0],strarray[1],strarray[2],&zahl,strarray[4],strarray[5],strarray[6],strarray[7]);
printf("\nProbe:\n");
for (i = 0; i < 3; i++) printf("%s ", strarray[i]);
printf("%d ",zahl);
for (i = 4; i < 8; i++) printf("%s ", strarray[i]);
DEZUBI(zahl, binzahl);
printf("\nZahl dezimal: %d\nZahl binaer : %s\n", zahl, binzahl);
}
Die Funktion 'DEZUBI' wandelt dabei die Dezimalzahl in einen String um.
Dabei ist es wichtig was für einen Prozessor man vor sich hat. Bei ganz alten Boards 16 Bit, was eigentlich nur in einigen Steuerungen vorkommt. Dann noch 32Bit-Prozessoren und die 64-Bit-Brozessoren. Bei den alten Betriebssystemen kommt es dann darauf an, ob jetzt das Programm für den real mode oder den protected mode geschrieben wurde. Solche alte Compiler für DOS haben für den Datentyp int nur 16Bit, also 2 Byte zur Verfügung. Das sollte man dann mal kontrollieren wie lange welcher Datentyp ist.
Dazu habe ich für meine Linux-System mit 64-Bit auf gcc und codelite folgendes kleines Programm gezimmert:
#include <iostream>
//#include <stdio.h>
#include <cstdlib>
#include <limits.h>
#include <float.h>
int main(int argc, char** argv) {
long double ulle;
__uint128_t testv;
std::cout << std::endl << "Länge der Datentypen\nund deren Wertebereiche V0.21" << std::endl << std::endl;
std::cout << "char..........: " << sizeof(char) << " Byte in Bit: " << CHAR_BIT << std::endl;
std::cout << "signed char...: " << CHAR_MAX << " bis " << CHAR_MIN << std::endl;
std::cout << "unsigned char.: 0 bis " << UCHAR_MAX << std::endl << std::endl;
//printf("SCHAR_MAX : %d\n", SCHAR_MAX);
//printf("SCHAR_MIN : %d\n", SCHAR_MIN);
std::cout << "short........: " << sizeof(short) << "Byte" << std::endl;
std::cout << "SHRT_MAX : " << SHRT_MAX << std::endl;
std::cout << "SHRT_MIN : " << SHRT_MIN << std::endl;
std::cout << "USHRT_MAX : " << USHRT_MAX << std::endl << std::endl;
std::cout << "Datentyp int " << sizeof(int) << " Byte" << std::endl;
std::cout << "INT_MAX : " << INT_MAX << std::endl;
std::cout << "INT_MAX : " << INT_MIN << std::endl;
std::cout << "UINT_MAX : " << UINT_MAX << std::endl;
std::cout << std::endl << "long : " << sizeof(long) << " Byte" << std::endl;
std::cout << "LONG_MAX : " << LONG_MAX << std::endl;
std::cout << "LONG_MIN : " << LONG_MIN << std::endl;
std::cout << "ULONG_MAX : " << ULONG_MAX << std::endl<< std::endl;
std::cout << "float : " << sizeof(float) << " Byte" << std::endl;
std::cout << "FLT_MAX : ±" << std::fixed << FLT_MAX << std::endl;
std::cout << "FLT_MAX : ±" << std::scientific << FLT_MAX << std::endl;
std::cout << "FLT_MIN : " << FLT_MIN << std::endl;
std::cout << "FLT_DIG : " << FLT_DIG << std::endl;
std::cout << std::endl << "double : " << sizeof(double) << " Byte" << std::endl;
//printf("DBL_MAX : %lf\n", DBL_MAX);
std::cout << "DBL_MAX : ±" << DBL_MAX << std::endl;
std::cout << "DBL_MIN : " << DBL_MIN << std::endl;
std::cout << "DBL_DIG : " << FLT_DIG << std::endl;
std::cout << std::endl << "Datentyp long double: " << sizeof(long double) << " Byte" << std::endl;
std::cout << "LDBL_MIN : " << LDBL_MIN << std::endl;
std::cout << "_DBL_MAX : " << LDBL_MAX << std::endl;
std::cout << "LDBL_DIG : " << LDBL_DIG << std::endl;
std::cout << std::endl << "Long long int " << sizeof(long long int) << " Byte" << std::endl;
std::cout << "Long long int min: " << LLONG_MIN << std::endl;
std::cout << "Long long int max: " << LLONG_MAX << std::endl;
std::cout << std::endl << "Long long uint " << sizeof(long long int) << " Byte" << std::endl;
std::cout << "Long long uint max: " << ULLONG_MAX << std::endl;
ulle = (long double) ULLONG_MAX;
printf("\nLong long uint max: %LE\n", ulle);
std::cout << std::endl <<"__uint128_t laenge: " << sizeof(testv) << " Byte" << std::endl;
return EXIT_SUCCESS;
}
Da könnt Ihr dann kontrollieren wie lange welcher Typ ist und was für ein Datenbereich er hat.
Beide Programme und alle Sourcen hier stelle ich unter GPL-Lizenz.
Bei der Funktion DEZUBI prüfe ich mit dem Bitoperand '&' ob ein Bit gesetzt ist oder nicht. Dazu setze ich zunächst den Prüfwert der Zahl auf eins und schiebe dann den Wert um 31 Bit nach links. Dann ist beim Prüfwert nur das höchste Bit gesetzt. Nach und nach wird wenn jedes Bit einzeln getestet wird, der Wert wieder nach rechts verschoben um den richtigen Prüfewert für das jeweilige Bit zu haben. Ist der Wert ungleich Null so wird im String der nachher die binäre Zahl beiinhaltet eine eine 1 gesetzt, sonst eine Null.
Einige Compiler hatten dazu in den 90ern, wie etwa Symantec c++7.0 eine extra Funktion BCD genannt, die eine Dezimalzahl als Integerwert darstellte. Da es aber zu Verwechslungen kommen kann, sollte man mit so etwas vorsichtig sein:
unsigned int bcd(unsigned int dezimalwert)
{
unsigned int slei, bitwert, testwert, dumsm, rewer;
testwert = 1 << 7;
bitwert = 0;
dumsm = 1;
rewer = 0;
for (slei = 0; slei <= 7; slei++)
{
bitwert = dezimalwert & testwert;
testwert >>= 1;
if (bitwert) rewer += dumsm;
dumsm *= 10;
}
return rewer;
}
Diese ist meine eigene Version. Wiederum unter GPL-Lizenz. Hier der Vollständigkeit halber zum experimentieren. Der Vorteil dieses Verfahrens liegt in der Länge der benötigten Variablen. Um einen 8-Bit-Wert in c darzustellen benötige ich mindestens ein char-Array von 9 Byte Länge, da ja in c Strings Nullterminiert sind. Es gilt also Länge der darzustellenden Dezimalzahl in bit + 1 = Länge des char-Arrays in Byte. Bei der Darstellung von unsigned char sind es hier nur 4 Byte für unsigend int.
Bei der Funktion bcd sollte man eigentlich immer unsigned long als Rückgabewert verwenden um eine Dezimalzahl in binärer Form darzustellen. Hier eine Version nur für die Darstellung von unsigend char als binäre Zahl. Ansonsten muss obere Funktion dementsprechend modifiziert werden.
Die Ausgabe der ursprünglich gestellten Aufgabe mit meinem Beispiel ist folgende:
Satz urspruenglich:
Zur Zeit ist 14972 die kleinste langweilige Zahl.
Laenge in Byte: 49
Probe:
Zur Zeit ist 14972 die kleinste langweilige Zahl.
Zahl dezimal: 14972
Zahl binaer : 11101001111100
Hit any key to continue...