String in Integer umwandeln und ausgeben ohne Library



  • Kompletter Code inkl.

    `putstring

    getstring

    copystring

    appendstring `

    wär mal toll.



  • #ifdef V1_Aufgabe_1
    
    // brauch ich doch nicht mehr, vorsichtshalber da lassen.
    int eigenestrlen(char *str) {
    
        int leng;
        int i;
        for (i=0; str[i] != 0; i++)
            {
                leng++;
            }
            return(leng);
        }
    
    int checknumbers (char* string) {
      int i;
      for (i = 0 ; string[i]!='\0';i++) {
        if (string[i] < '0' || string[i] > '9') {
          putstring("Bitte erneute eingabe der Zahl: nicht im Zahlenbereich:\n");
          return -1;
          }
        }
    
      return 1;
      }
    
    int checklength (char* string) {
      int i;
      for (i = 0;string[i]!='\0';i++){
        if (i > 3) {
        putstring("Bitte erneute eingabe der Zahl: nicht im Zahlenbereich:\n");
            return -1;
    
          }
        }
    
      return 1;
      }
    
    unsigned short int meinAtoi(char *zahlenstrahl)
    {
      unsigned short int i = 0;
    
            while(*zahlenstrahl){
                i = i*10+(*zahlenstrahl) - '0';
                zahlenstrahl ++;
            }
    return i;
    }
    
    void meinitoa(unsigned short int uwert, char* str)
    {
    unsigned short int startwert;
    unsigned short int i;
    
        startwert = uwert;
        str[0] = ' ';
    
     for (i=4; i>=1; i--) { //läuft rückwärts 0000 -> 0001->0002->0003->0004->0005> usw usw usw...
         //da max. 4 Stellen, kann ich es ab i=4 laufen lassen.
    
        // modulo rechnen und 48 bzw '0' von ascii wird addiert.
        str[i]=(startwert % 10) +'0';
        startwert /= 10;
    }
    
    }
    
    void emain()
    
    {
        unsigned short int zahl1;
        unsigned short int zahl2;
        unsigned short int result;
        char string_1[100];
        char string_2[100];
    
        INIT_BM_WITHOUT_REGISTER_UI;
    
        do {
    
        putstring("Bitte 1. Zahl eingeben:\n");
        getstring(string_1);
        }
        while (checknumbers(string_1)== - 1 || checklength(string_1) == -1);
    
        zahl1=meinAtoi(string_1);
    
        do {
        putstring("Bitte 2. Zahl eingeben:\n");
        getstring(string_1);
    
        } while (checknumbers(string_1)== -1 || checklength(string_1) == -1);
    
        zahl2=meinAtoi(string_1);
    
        result= zahl1 + zahl2;
    
        meinitoa(result,string_1);
    
        copystring("Addition beider Zahlen ist:\n",string_2);
        appendstring(string_1, string_2);
        putstring (string_2);
    
            END;
    }
    
    #endif // V1_Aufgabe_1
    

    Ihr könnt mir glauben, dass die Aufgabe mich an meine nervliche Belastungsgrenze geführt hat ... 😃

    Habe zwar Java Vorkenntnisse aber wir fangen in der Uni jetzt mit Mikrocontroller programmierung an und ich versuche mich schonmal in die Aufgaben einzuarbeiten.

    Programmiert wird über Qt-Creator mit einem externen .bat Programm, um dort alles einzugeben.



  • Swordfish schrieb:

    inkl.

    `putstring

    getstring

    copystring

    appendstring`

    🙄

    verano123 schrieb:

    void meinitoa(unsigned short int uwert, char* str)
    {
        unsigned short int startwert;
        unsigned short int i;
    
        startwert = uwert;
        str[0] = ' ';
    
        for (i=4; i>=1; i--) { //läuft rückwärts 0000 -> 0001->0002->0003->0004->0005> usw usw usw...
            //da max. 4 Stellen, kann ich es ab i=4 laufen lassen.
    
            // modulo rechnen und 48 bzw '0' von ascii wird addiert.
            str[i]=(startwert % 10) +'0';
            startwert /= 10;
        }
    }
    

    warum str[0]=' '; ?
    du setzt kein Zeichenkettenende ( '\0' )?
    warum 4 ... 1 und nicht 3 ... 0 ? (dann gehört an str[4] ein '\0' )

    verano123 schrieb:

    // ...
        copystring("Addition beider Zahlen ist:\n",string_2);
        appendstring(string_1, string_2);
        putstring (string_2);
    
            END;
    }
    

    Wozu? Du hast doch schon die beiden Zahlen addiert und das Ergebnis steht in result (das Du dann per meinitoa(result,string_1); in Zeile 111 als Zeichenkette in string_1 abgelegt hast), also string_1 ausgeben und gut iss?



  • Ich kann da nicht mehr mitlesen 😮

    Ich bin zwar kein C Profi, sondern eher Hobbyprogger und habe ein wenig rumgespielt:

    #include <stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include <ctype.h>    
    unsigned long int my_atoi (char *ergebnis)
    {
    	unsigned long int r=0;
    	int i = sizeof(ergebnis),j,k=1;
    	for (j = i; j >= 0; j--)
    	{
    		r = ((ergebnis[j]-48) * k) + r;
    		k = 10 * k;
    	}
    	return r;
    }
    int main(void)
    {   
        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);
        return 0;
    }
    

    Diese Lösung scheint zu funzen..... Jetzt musste nur noch die Eingabe hinbekommen


  • Mod

    Dein Programm hat mehrere Fehler/Schwächen:
    -Fehlende const-correctness.
    -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.
    -Magic Numbers.
    -Rechnung kann erheblich gekürzt werden und kann ohne Zwischenwerte auskommen.
    -Merkwürdige Bezeichnerwahl. ergebnis ?


  • Mod

    Um dem Elend mal ein Ende zu machen (ungetestet):

    unsigned long my_atoi(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;
    }
    


  • 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 das strlen 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.


Anmelden zum Antworten