String in Integer umwandeln und ausgeben ohne Library
-
Danke.
Aber atoi war ja eigentlich gelöst und die (beiden letzten) Versionen vom TO sind besser als die von Hobbyprogger.
Das Elend ist bei itoa.
-
#include <stddef.h> #include <stdbool.h> bool itoa( char * dst, size_t dst_size, unsigned number ) { unsigned tmp = number; size_t i = 0; do ++i; while( tmp /= 10 ); if( i >= dst_size ) return false; dst[ i-- ] = '\0'; do dst[ i-- ] = '0' + ( number % 10 ); while( number /= 10 ); return true; }
?
// edit: die verf*****
0
!!
-
Bevor jetzt jemand Probleme beim compilieren/linken bekommt:
Mache Compiler liefern eine
itoa
Funktion mit.
Diese gehört aber nicht zum C-Standard (im K&R steht sie aber drin).
Zudem gibt es noch zwei verschiedene Versionen, einmal mit Angabe der Basis und einmal mit fester Basis 10.http://www.cplusplus.com/reference/cstdlib/itoa/
Diese Funktionen werden gerne auf Mikrocontrollern verwendet, wo ein
sprintf
zuviel Platz nimmt.
-
DirkB schrieb:
Zudem gibt es noch zwei verschiedene Versionen, einmal mit Angabe der Basis und einmal mit fester Basis 10.
itoa mit Basisvorgabe 2...16 und C99 konform:
https://www.c-plusplus.net/forum/p2485037#2485037
-
Ich bin beeindruckt von der Lösung von SeppJ. Ich habe das jetzt mal zusammengefasst und mir dann mit dem GCC mit Option -S das Ergebnis angeschaut. Hier der C Code:
#include <stdio.h> #include<string.h> #include<stdlib.h> #include <ctype.h> unsigned long my_atoi2(const char* str) { // Man beachte: Laut Aufgabenstellung nur positive Zahlen ohne Vorzeichen unsigned long value = 0; while(*str) { value *= 10; value += *str++ - '0'; } return value; } unsigned long int my_atoi (char *ergebnis) { unsigned long int r=0; size_t i = sizeof(ergebnis); int j,k=1; for (j = i; j >= 0; j--) { r = ((ergebnis[j]-48) * k) + r; k = 10 * k; } return r; } int main() { char ergebnis[15]; // unsigned long int zahl; // sprintf (ergebnis,"%s", "987654321"); // Hier musste die Eingabe proggen // zahl = atoi(ergebnis); zahl = my_atoi(ergebnis); printf("%li\n",zahl); zahl = my_atoi2(ergebnis); printf("%li\n",zahl); return 0; }
Hier der generierte ASM Code:
.file "c-forum2.c" .text .globl my_atoi2 .type my_atoi2, @function my_atoi2: .LFB2: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movq %rdi, -24(%rbp) movq $0, -8(%rbp) jmp .L2 .L3: movq -8(%rbp), %rdx movq %rdx, %rax salq $2, %rax addq %rdx, %rax addq %rax, %rax movq %rax, -8(%rbp) movq -24(%rbp), %rax leaq 1(%rax), %rdx movq %rdx, -24(%rbp) movzbl (%rax), %eax movsbl %al, %eax subl $48, %eax cltq addq %rax, -8(%rbp) .L2: movq -24(%rbp), %rax movzbl (%rax), %eax testb %al, %al jne .L3 movq -8(%rbp), %rax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE2: .size my_atoi2, .-my_atoi2 .globl my_atoi .type my_atoi, @function my_atoi: .LFB3: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movq %rdi, -40(%rbp) movq $0, -16(%rbp) movq $8, -8(%rbp) movl $1, -20(%rbp) movq -8(%rbp), %rax movl %eax, -24(%rbp) jmp .L6 .L7: movl -24(%rbp), %eax movslq %eax, %rdx movq -40(%rbp), %rax addq %rdx, %rax movzbl (%rax), %eax movsbl %al, %eax subl $48, %eax imull -20(%rbp), %eax cltq addq %rax, -16(%rbp) movl -20(%rbp), %edx movl %edx, %eax sall $2, %eax addl %edx, %eax addl %eax, %eax movl %eax, -20(%rbp) subl $1, -24(%rbp) .L6: cmpl $0, -24(%rbp) jns .L7 movq -16(%rbp), %rax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE3: .size my_atoi, .-my_atoi .section .rodata .LC0: .string "%li\n" .text .globl main .type main, @function main: .LFB4: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $48, %rsp movq %fs:40, %rax movq %rax, -8(%rbp) xorl %eax, %eax leaq -32(%rbp), %rax movabsq $3617292328856139833, %rdx movq %rdx, (%rax) movw $49, 8(%rax) leaq -32(%rbp), %rax movq %rax, %rdi call my_atoi movq %rax, -40(%rbp) movq -40(%rbp), %rax movq %rax, %rsi movl $.LC0, %edi movl $0, %eax call printf leaq -32(%rbp), %rax movq %rax, %rdi call my_atoi2 movq %rax, -40(%rbp) movq -40(%rbp), %rax movq %rax, %rsi movl $.LC0, %edi movl $0, %eax call printf movl $0, %eax movq -8(%rbp), %rcx xorq %fs:40, %rcx je .L11 call __stack_chk_fail .L11: leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE4: .size main, .-main .ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2" .section .note.GNU-stack,"",@progbits
Ich gehe mal davon aus, dass hier Experten sind, die u.U. auch an der Uni lehren und hier mit ihren Stundenten diskutieren und möchte daher jetzt nicht "Klugscheissen" - aber wenn ich den ASM Code von my_atoi und my_atoy2 anschaue, sehe ich da keinen grossen Unterschied... Oder übersehe ich da was?
-
Klar kann der Compiler optimieren, aber trotzdem ist dein
my_atoi
falsch.
Und multipliziern mit 10, subtrahieren der '0' machen beide Funktionen, das wars dann aber auch.Das Reultat vom
sizeof
ist für diesen Zweck völlig ungeeignet.Und probier das Ganze mal mit anderen Werten. Vor allem mit mehr oder weniger als 8 Stellen.
-
DirkB schrieb:
So wie die aufgerufen werden, geht das heutzutage gar nicht mehr, weilsie einen Bufferoverflow generieren können
Ich mag das. Macht mir einen Heidenspaß den Leuten ihre Programme um die Ohren zu hauen. Man hat ja sonst kein Hobby.
-
Hobbyprogger schrieb:
aber wenn ich den ASM Code von my_atoi und my_atoy2 anschaue, sehe ich da keinen grossen Unterschied... Oder übersehe ich da was?
C ist keine wirkliche Hochsprache und schon gar keine Lernsprache.
C-Codes haben naturgemäß die Eigenschaft, sehr umfangreich (viele loc) zu sein, es kommt darauf an, für Verständlichkeit+Wartbarkeit die Übersicht zu behalten und dafür sind kurze Codes von Vorteil (natürlich im normalen Rahmen und nicht obfuscated).Hobbyprogger schrieb:
Ich gehe mal davon aus, dass hier Experten sind, die u.U. auch an der Uni lehren
lol
"Experte" + "an der Uni" schließen sich gegenseitig aus.
-
EOP schrieb:
DirkB schrieb:
So wie die aufgerufen werden, geht das heutzutage gar nicht mehr, weilsie einen Bufferoverflow generieren können
Ich mag das. Macht mir einen Heidenspaß den Leuten ihre Programme um die Ohren zu hauen. Man hat ja sonst kein Hobby.
Die von mir bemängelten Funktionen wurden dem TO vorgegeben.
Der Teil ist also nicht sein Programm, sondern der vom Professor/Tutor/Lehrer.Wutz schrieb:
"Experte" + "an der Uni" schließen sich gegenseitig aus.
-
DirkB schrieb:
Klar kann der Compiler optimieren, aber trotzdem ist dein
my_atoi
falsch.
Und multipliziern mit 10, subtrahieren der '0' machen beide Funktionen, das wars dann aber auch.Das Reultat vom
sizeof
ist für diesen Zweck völlig ungeeignet.Und probier das Ganze mal mit anderen Werten. Vor allem mit mehr oder weniger als 8 Stellen.
Kann da nicht einer gleich sagen, dass man Strinlängen mit
int i = strlen(ergebnis)
ermittelt
Wieder was gelernt......
Dabke an alle!
-
SeppJ schrieb:
Dein Programm hat mehrere Fehler/Schwächen:
-Die Längenermittlung in Zeile 8 ist falsch. So geht das nicht in C. Noch einmal angucken, wie das mit den C-Strings und Arrays geht.
-Selbst wenn man die Länge korrekt ermitteln würde, wäre das komplett unnötig, wegen der Natur von C-Strings.Wir ermuntern gerne zur Selbsthilfe.
Aber beachte auch den 2. Punkt.
Da du in der Schleife danach sowieso durch den String gehst, kannst du da auch gleich auf das Ende prüfen. Du brauchst dasstrlen
gar nicht.
-
Hobbyprogger schrieb:
Kann da nicht einer gleich sagen, dass man Strinlängen mit
int i = strlen(ergebnis)
ermittelt
Wieder was gelernt......Tja und schon wieder falsch gelernt.
Korrekt ist
size_t i = strlen(ergebnis);
Es gibt "Überraschungen" wenn du den unsigned Typ size_t beim Rechnen nicht berücksichtigst, z.B. bei
if( strlen("123")-strlen("1234") < 0 ) u.ä.
-
Wutz schrieb:
Korrekt ist
size_t i = strlen(ergebnis);
Es gibt "Überraschungen" wenn du den unsigned Typ size_t beim Rechnen nicht berücksichtigst, z.B. bei
if( strlen("123")-strlen("1234") < 0 ) u.ä.
int kann man ruhig nehmen. dein konstruierter fehlerfall ist quatsch.
-
Dorfdeppen melden sich immer wieder ungefragt zu Wort.
-
Wutz schrieb:
Dorfdeppen melden sich immer wieder ungefragt zu Wort.
wow, du kannst dem dorfdeppen nicht einmal sachlich widersprechen.
bist ja voll der held.
-
Geistig weniger Bemittelte mit Geltungsdrang aber ohne Ahnung bekommen Antworten auf dem gleichen Niveau, das sie offenbaren.
-
Hallo Leute,
sorry hatte die letzten Tage garkeine Zeit hier reinzugucken.
Wollte keine Welle hier schlagen mit der Aufgabe.Der Thread kann gerne geschlossen werden. Hoffe, dass andere von den hier gestellten Fragen und Antworten profitieren können, die auch solche Probleme haben wie ich.
Danke für die Hilfe und die rege Diskussion
-
wurzelsepp schrieb:
Wutz schrieb:
Korrekt ist
size_t i = strlen(ergebnis);
Es gibt "Überraschungen" wenn du den unsigned Typ size_t beim Rechnen nicht berücksichtigst, z.B. bei
if( strlen("123")-strlen("1234") < 0 ) u.ä.
int kann man ruhig nehmen. dein konstruierter fehlerfall ist quatsch.
Ja. Tatsächlich ist es von Vorteil, wenn Nubes int für Größen nehmen genau desdawegen. Und der konstruierte Fall ist Quatsch. Ihr habt beide recht.
Oder nehmen wir mal einfach
assert(index>=0);//int assert(index<size);//int
versus
assert(index>=0);//size_t assert(index<size);//size_t
. int liefert potenziell mehr bessere Fehler.
Es ist irgendwie "besser", int zu nehmen, aber irgendwie "richtiger", size_t zu nehmen. Ich denke, es ist am besten, die Mitarbeiter zu size_t zu schulen. Und wenn das nicht geht, dann freies Gefecht. Meinetwegen double.
Naja, wenn int nur 4 Byte hat und size_t 8 Byte verbietet sich int eh. Dann vielleicht ssize_t oder intptr_t??? Ist nicht lecker.
-
verano123 schrieb:
Wollte keine Welle hier schlagen mit der Aufgabe.
Lass mal. Da hast du eh keinen Einfluß drauf.
Aber lieber etwas Leben als tote Hose.verano123 schrieb:
Hoffe, dass andere von den hier gestellten Fragen und Antworten profitieren können, die auch solche Probleme haben wie ich.
Haben sie. Auch von Fragen, die gar nicht gestellt wurden.