Autor Thema: Printing numbers  (Gelesen 4062 mal)

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« am: 25. October 2006, 21:54 »
Yay, ich bin's wieder, der noob... Is' seltsam, aber ich krieg offenbar nix hin. Vllt könnt ihr mir wieder helfen, wäre sehr nett. Ihr könnt mich auch auslachen...

Ich will ne beliebige 32-bit Zahl ausgeben. Eine einzelne Ziffer hab ich schon, aber wenn ich diesen code ausführe, kriege ich immer nur eine '1' als ausgabe. Bochs Debug bringt mir nix, da ich da nicht mehr durchsehe.
void printnum(_u32 n)
{
_u32 num = n;
if(num == 0) putch('0');
else
{
for(i=9;i>=0;i--)
{
_u32 exp = 10^i;
if(num >= exp)
{
_u8 d = num / exp;
putdigit(d);
num -= d * exp;
}
}
}
}

Hoffe ihr könnt mir noch einmal helfen...

PS: Sollte ich eine printf-funktion schreiben oder mich lieber von einer Klippe stürzen?

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 25. October 2006, 22:19 »
 :-D Das mit der Klippe is ne ganz schlechte Idee.
Wenn du schon ne Funktion für eine einfach Stringausgabe hast, guck dir das mal an:
void PrintDec(long num)
{
char buffer[11];
int i = 10;
do
{
buffer[--i] = '0' + (char)(num % 10);
num /= 10;
} while (num > 0);

buffer[10] = '\0';
Print(buffer + i);
}

Früher oder später ist aber eine richtige printf-Funktion, sehr hilfreich.

Krox

  • Beiträge: 38
    • Profil anzeigen
    • Coding42.de
Gespeichert
« Antwort #2 am: 25. October 2006, 22:20 »
einen kleinen Fehler seh' ich: das
if (num >= exp)verhindert nicht nur die Ausgabe führender Nullen, sondern so wie ich das sehe auch jede weitere Null in der Mitte der Zahl.

Die meisten Implemtierungen sehen ungefähr so aus (das hier ist natürlich nicht getestet^^):
void printnum (int n)
{
char tmp[20];
int i = 0;
if (n == 0) printch('0');
else
{
while (n > 0)
{
tmp[i++] = '0' + n % 10;
n = n / 10;
}
while (i-- > 0)
{
printch(tmp[i]);
}
}
}

Und wegen dem printf()... es erleichtert die Ausgabe enorm, und so viel Aufwand ist das auch nicht, zumindest wenn man nur %d und sowas unterstützt und keine zusätzlichen Format-Angaben zwischen % und d.
Aber falls du C++ benutzt, könntest du noch einen Schritt weiter gehen und einen Stream basteln mit überladenem "<<"-Operator und so. Wenn man sich in die Syntax für Operator-Überladungen erstmal herreingefunden hat, sind die wirklichen Routinen sogar einfacher (kein printf, sondern nur eine Überladung für int, einen für uint, etc...).
Aber printf oder stream is wohl Geschmacksfrage :)

edit: da war jemand schneller mit'm schreiben  :-D
21 ist nur die halbe Wahrheit

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #3 am: 25. October 2006, 22:22 »
_u32 exp = 10^i;
Da kennt einer wohl seine Programmiersprache nicht 8-) Das ist keine gute Voraussetzung :-D
Das "^" ist nämlich keine Potenz, sondern ein exklusiv oder :wink:

Insofern würd ich die Zahl rückwärts in einem String speichern (einfach immer den Rest von einer Division durch 10 in den String) und dann mit dem Ergebnis der Division genauso fortfahren. Danach den String umdrehen und dann erst ausgeben.

*lol* richtig was los heute
« Letzte Änderung: 25. October 2006, 22:24 von bluecode »
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #4 am: 25. October 2006, 22:25 »
@DarkThing, bei dir wird die Zahl falsch herum ausgegeben.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 25. October 2006, 22:32 »
Ich habs jetzt nochmal getestet und die Zahl wird richtigrum ausgegeben...

Dieser Code gibt jedenfalls 123 aus.
#include <iostream>
using namespace std;

void PrintDec(long num)
{
char buffer[11];
int i = 10;

do
{
buffer[--i] = '0' + (char)(num % 10);
num /= 10;
} while (num > 0);

buffer[10] = '\0';
cout << buffer+i << endl;
}

int main(int argc, char *argv[])
{
PrintDec(123);
return 0;
}

Ich fülle ja den Buffer von hinten nach vorne, sozusagen. i wird mit 10 initialisiert und dann immer kleiner.

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #6 am: 25. October 2006, 22:34 »
ups sry, das hab ich ganz übersehen :oops: Trotzdem ist das nicht unbedingt die portabelste Lösung :lol:
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #7 am: 25. October 2006, 22:40 »
Danke Leute!

Dass mit dem stream werde ich mir noch mal überlegen... Würde so was gerne auf OS ebene machen, wenn es überhaupt möglish ist...

Vielen dank noch mal...

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #8 am: 25. October 2006, 22:48 »
Kannst dir bei meinem OS anschauen. Ich versuch es kompatibel mit dem C++ Standard zu halten. Beteiligte Sourcedateien:
* libc++/ios
* libc++/ostream
* libc++/iostream
* kernel cout/etc. Implementation: kernel/libc++/iostream.cpp
* userspace cout/etc. Implementation: lightOS/x86/iostream.cpp (Ist noch durch nen kernel syscall gelöst, aber das wird sich ändern)
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #9 am: 09. November 2006, 19:57 »
Ich musste das ganze in Assembler schreiben... Aber... der sagt mir nur 'Division by Zero Error'...
putnum:
cmp ebx, 0
jz putzero

mov edi, tempstr

mov [n], ebx

putnum1:
mov eax, [n]
mov bx, 10
div bx
mov eax, '0'
add eax, edx

stosb

mov eax, [n]
mov bx, 10
div bx
mov [n], eax

cmp eax, 0
ja putnum1

mov esi, tempstr
call write

jmp putnum_end
putzero:
mov al, '0'
call putch
jmp putnum_end
putnum_end:
ret

Also, ich hab ja nur mov bx, 10
div bx
drin... wo is da eine division mit null?

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 10. November 2006, 16:13 »
Erst ma

DIV BXteilt nicht EAX durch BX sondern DX:AX durch BX

Das ergebniss steht dann in AX
der Divisions-Rest in DX

Wenn das ergebniss zu groß für AX ist, wird glaub ich auch ein Divisions fehler ausgelöst(~> Division durch null))
um das zu verhindern probier ma

XOR EDX, EDX
MOV EAX, [n]
MOV EBX, 10
DIV EBX

teilt EDX:EAX durch EBX
ergebnis in EAX
rest in EDX
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

 

Einloggen