Anfänger benötigt hilfe -> segmentation fault



  • Hi... ich habe ein Problem, bei dem folgendem C-Programm, welches eigentlich nur Dezimale Zahlen in Binäre umwandeln soll.
    Soweit funktioniert das Programm, wenn ich jedoch eine Zahl eingebe, wo sich die Ausgebe nicht wiederholt und der Rest auch nicht 0 wird, bekomme ich "segmentation fault" angezeigt. Eigentlich hatte ich geplant, dass nach einer bestimmten Anzahl an Durchläufen (30) das Programm einfach aufhört ?!? Danke schon mal für die Hilfe...

    [cpp]
    #include <stdio.h>
    
    int main(void) {
        float kommazahl;
        float array_kommazahl[0][0];
        int zahl, rest;
        int i=0, j=0, loop=0, genauigkeit=30;
    
        printf("Bitte eine positive Kommazahl eingeben:");
        scanf("%f", &kommazahl);
    
    /*
        z.B.: die Dezimalzahl 8 soll ins 2er-System umgewandelt werden
    
        Verfahren:
        (1) Teile die Zahl mit Rest durch 2.
        (2) Der Divisionsrest ist die naechste Ziffer (von rechts nach links).
        (3) Falls der (ganzzahlige) Quotient = 0 ist, bist du fertig,
            andernfalls nimm den (ganzzahligen) Quotienten als neue Zahl 
            und wiederhole ab (1).
    
        8 : 2 = 4  Rest: 0
        4 : 2 = 2  Rest: 0
        2 : 2 = 1  Rest: 0
        1 : 2 = 0  Rest: 1
    
        Resultat: 1000
    */
    
        zahl = (int) kommazahl;
    
        while (zahl > 0) { // (3)
            rest = zahl % 2; // (1)
            printf("%d\n", rest); // Ausgabe 
            zahl = zahl / 2; // (2)
        }
    
        printf("\n:\n\n");
    
    /* 
        z.B: der Dezimalbruch  0,8  soll ins 2er System umgewandelt werden
    
        Verfahren fuer Nachkommaziffern:
        (1) Multipliziere die Zahl mit der Basis 2
        (2) Die Zahl vor dem Komma ist die naechste Ziffer des Ergebnisses
        (3) Schneide die Zahl vor dem Komma weg.
        (4) Wiederhole ab (1), bis der Rest 0 ist, sich ein Rest wiederholt
            oder die gewuenschte Genauigkeit erreicht ist.
    
        2 · 0,8 = 1,6    --> Ziffer: 1
        2 · 0,6 = 1,2    --> Ziffer: 1
        2 · 0,2 = 0,4    --> Ziffer: 0
        2 · 0,4 = 0,8    --> Ziffer: 0
        2 · 0,8 = 1,6    --> Ziffer: 1
    
        Der "Rest" 1,6 trat im 1. Schritt bereits auf.
        Ab dort wiederholen sich die Nachkommaziffern periodisch.
    
        -> Resultat: 0,1100110011001100110011001100110011001100110011001100...
    */
    
        kommazahl = kommazahl - (int) kommazahl;
    
        do {
            kommazahl *= 2; // (1)
    
            kommazahl = ( (int) (kommazahl * 10000.0 + 0.5)) / 10000.0; // Runden auf 4 Nachkommastellen
    
            array_kommazahl[i][i+1] = kommazahl; // Restwert in ein Array schreiben
    
            /*for ( j=1; j <= i; j++ ) {
                printf("\ntest - [%d][%d] - %f\n", i, j, array_kommazahl[i][j]); // test - Ausgabe
            } */
    
            if ( (int) kommazahl == 0) { // (2)
                printf ("0\n"); // Ausgabe
            } else { // (2) 
                kommazahl -= 1; // (3)
                printf ("1\n"); // Ausgabe
            }
    
            for ( j=1; j <= i; j++ ) {
                if ( array_kommazahl[i][j] == kommazahl ) { // (4) - Wiederholung feststellen
                    loop = j;
                }
            }
    
            if ( loop >= 1 ) {
                printf ("\nDer \"Rest\" von %f trat im %d. Schritt bereits auf, ab dort wiederholen sich die Nachkommaziffern periodisch.", kommazahl, loop-1);
                break;
            }
    
            if ( i >= genauigkeit ) {
                printf ("\nDie genauigkeit sollte nun ausreichen... (%d Bit)", genauigkeit); //  [b]Fehler[/b] - segmentation fault vor dieser Ausgabe... ????
                break;
            }
    
            if ( kommazahl == 0.0 ) {
                printf ("\nEs ist kein Rest mehr uebrig... :-)");
                break;
            }
    
            i++;
        } while ( loop == 0 || i <= genauigkeit || kommazahl != 0.0); // (4)
    
        return(0);
    }
    [/cpp]
    


  • versuch mal für das array

    float array_kommazahl[0][0];
    

    auch speicher anzulegen.

    float array_kommazahl[31][32];
    


  • evtl. greifst du in z.73/74 bzw. z.84/85 auch auf uninitialisierte werte zu?



  • irgendwie hab ich das mir dem Array anscheinend noch nicht ganz verstanden...

    wenn ich folgendes machen...

    float array_kommazahl[0][0];
    

    ... bekomme ich folgendes richtiges Ergebnis angezeigt...

    Bitte eine positive Kommazahl eingeben:2.2
    0
    1

    :

    0

    test - [1][1] - 0.400000
    0

    test - [2][1] - 0.400000

    test - [2][2] - 0.800000
    1

    test - [3][1] - 0.400000

    test - [3][2] - 0.800000

    test - [3][3] - 1.600000
    1

    test - [4][1] - 0.400000

    test - [4][2] - 0.800000

    test - [4][3] - 1.600000

    test - [4][4] - 1.200000
    0

    Der "Rest" von 0.400000 trat im 0. Schritt bereits auf, ab dort wiederholen sich die Nachkommaziffern periodisch.

    wenn ich jedoch dies mache...

    float array_kommazahl[31][32];
    

    ... bekomme ich ganz komische Zahlen angezeigt...?!?

    Bitte eine positive Kommazahl eingeben:2.2
    0
    1

    :

    0

    test - [1][1] - 0.000000
    0

    test - [2][1] - 0.000000

    test - [2][2] - 0.000000
    1

    test - [3][1] - 0.000000

    test - [3][2] - 0.000000

    test - [3][3] - 0.000000
    [...]

    😞

    ... bei der Eingabe der Zahl "0.77" bekomme ich auch das korrekte Ergebnis angezeigt, jedoch zum Schluss "segmentation fault" ⚠



  • #include <stdio.h>
    
    #define MAX_DIG 10
    
    int main(void) {
        float kommazahl;
        int zahl, rest;
        int genauigkeit=MAX_DIG;
        int repeat = 0;
    
        printf("Bitte eine positive Kommazahl eingeben:");
        scanf("%f", &kommazahl);
    
    /*
        z.B.: die Dezimalzahl 8 soll ins 2er-System umgewandelt werden
    
        Verfahren:
        (1) Teile die Zahl mit Rest durch 2.
        (2) Der Divisionsrest ist die naechste Ziffer (von rechts nach links).
        (3) Falls der (ganzzahlige) Quotient = 0 ist, bist du fertig,
            andernfalls nimm den (ganzzahligen) Quotienten als neue Zahl
            und wiederhole ab (1).
    
        8 : 2 = 4  Rest: 0
        4 : 2 = 2  Rest: 0
        2 : 2 = 1  Rest: 0
        1 : 2 = 0  Rest: 1
    
        Resultat: 1000
    */
    
        zahl = (int) kommazahl;
    
        while (zahl > 0) { // (3)
            rest = zahl % 2; // (1)
            printf("%d\n", rest); // Ausgabe
            zahl = zahl / 2; // (2)
        }
    
        printf("\n");
    
    /*
        z.B: der Dezimalbruch  0,8  soll ins 2er System umgewandelt werden
    
        Verfahren fuer Nachkommaziffern:
        (1) Multipliziere die Zahl mit der Basis 2
        (2) Die Zahl vor dem Komma ist die naechste Ziffer des Ergebnisses
        (3) Schneide die Zahl vor dem Komma weg.
        (4) Wiederhole ab (1), bis der Rest 0 ist, sich ein Rest wiederholt
            oder die gewuenschte Genauigkeit erreicht ist.
    
        2 · 0,8 = 1,6    --> Ziffer: 1
        2 · 0,6 = 1,2    --> Ziffer: 1
        2 · 0,2 = 0,4    --> Ziffer: 0
        2 · 0,4 = 0,8    --> Ziffer: 0
        2 · 0,8 = 1,6    --> Ziffer: 1
    
        Der "Rest" 1,6 trat im 1. Schritt bereits auf.
        Ab dort wiederholen sich die Nachkommaziffern periodisch.
    
        -> Resultat: 0,1100110011001100110011001100110011001100110011001100...
    */
    
        int kommas = ((( (int) (kommazahl * 10000.0 + 0.5)) / 10000.0) - (int) kommazahl)*10000;
    
        do {
            kommas *= 2; // (1)
    
    		if(repeat == 0){
        		repeat = kommas;
        	}else if(repeat == kommas){
        		printf ("\noO ein wiederholer ;)");
    			break;
        	}
    
            if (kommas/10000 == 0) { // (2)
                printf ("0\n"); // Ausgabe
            } else { // (2)
            	kommas -= 10000; // (3)
                printf ("1\n"); // Ausgabe
            }
        } while (kommas && --genauigkeit > 0);
    
        if ( kommas == 0 ) {
            printf ("\nEs ist kein Rest mehr uebrig... :-)");
        }else if ( genauigkeit == 0) {
            printf ("\nDie genauigkeit sollte nun ausreichen... (%d Bit)", MAX_DIG);
        }
    
        return(0);
    }
    

    ich habs jetzt mal so probiert. dachte mir man braucht sich ja nicht jeden wert merken sondern nur den ersten 😕



  • Leider funktioniert das so nicht, da die Wiederholung auch später einsetzen kann ...



  • voku1987 schrieb:

    Leider funktioniert das so nicht, da die Wiederholung auch später einsetzen kann ...

    ist mir mittlerweile auch aufgefallen 😞

    #include <stdio.h>
    #include <math.h>
    
    #define MAX_DIG 20
    
    int main(void) {
        double kommazahl;
        int zahl, rest;
        int genauigkeit=MAX_DIG;
        int repeat[MAX_DIG] = {};
        int i=0,z;
    
        printf("Bitte eine positive Kommazahl eingeben:");
        scanf("%f", &kommazahl);
    
        zahl = (int) kommazahl;
    
        while (zahl > 0) { // (3)
            rest = zahl % 2; // (1)
            printf("%d\n", rest); // Ausgabe
            zahl = zahl / 2; // (2)
        }
    
        printf("\n");
    
        int kommas = ((( (int) (kommazahl * 10000.0 + 0.5)) / 10000.0) - (int) kommazahl)*10000;
    
        do {
            kommas *= 2; // (1)
    
        	for(z=0;z<i;z++){
        		if(repeat[z] == kommas){
        			printf ("\noO ein wiederholer ;)");
        			return 0;
        		}
        	}
    
        	repeat[i++] = kommas;
    
            if (kommas/10000 == 0) { // (2)
                printf ("0\n"); // Ausgabe
            } else { // (2)
            	kommas -= 10000; // (3)
                printf ("1\n"); // Ausgabe
            }
        } while (kommas && --genauigkeit > 0);
    
        if ( kommas == 0 ) {
            printf ("\nEs ist kein Rest mehr uebrig... :-)");
        }else if ( genauigkeit == 0) {
            printf ("\nDie genauigkeit sollte nun ausreichen... (%d Bit)", MAX_DIG);
        }
    
        return(0);
    }
    


  • Schreib dir doch eine Funktion, die die fragliche Funktionalität kapselt.
    Du kannst auch sprintf für deine Rundungsaktionen verwenden, du ersparst dir eigene Rumrechnerei.

    char *nachkomma(float f,char *buffer,int genauigkeit)
    {
      int lauf=0;
      char tmp[100];
      while( lauf<genauigkeit, sprintf(tmp,"%.4f",f), atol(strchr(tmp,'.')+1) )
      {
        int hatvorkomma=(sprintf(tmp,"%.1f",f*=2),atol(tmp)!=0);
        buffer[lauf++]='0'+hatvorkomma;
        f-=hatvorkomma;
      }
      buffer[lauf]=0;
      return buffer;
    }
    
    #define GENAUIGKEIT 30
    char stellen[GENAUIGKEIT+1];
    puts( nachkomma( 0.8, stellen, GENAUIGKEIT ) );
    


  • Wutz schrieb:

    Schreib dir doch eine Funktion, die die fragliche Funktionalität kapselt.
    Du kannst auch sprintf für deine Rundungsaktionen verwenden, du ersparst dir eigene Rumrechnerei.

    char *nachkomma(float f,char *buffer,int genauigkeit)
    {
      int lauf=0;
      char tmp[100];
      while( lauf<genauigkeit, sprintf(tmp,"%.4f",f), atol(strchr(tmp,'.')+1) )
      {
        int hatvorkomma=(sprintf(tmp,"%.1f",f*=2),atol(tmp)!=0);
        buffer[lauf++]='0'+hatvorkomma;
        f-=hatvorkomma;
      }
      buffer[lauf]=0;
      return buffer;
    }
    
    #define GENAUIGKEIT 30
    char stellen[GENAUIGKEIT+1];
    puts( nachkomma( 0.8, stellen, GENAUIGKEIT ) );
    

    ... an welcher Stelle wird dann geprüft, ob sich die Werte wiederholen???



  • Wutz schrieb:

    es muss natürlich heissen:

    while( lauf<genauigkeit && (sprintf(tmp,"%.4f",f), atol(strchr(tmp,'.')+1)) )
    

    und genau hier gehören dann weitere gewünschte Abbruchbedingungen hin.



  • Hab es gestern doch noch hinbekommen, wie hier schon angesprochen wurde, reicht ein einfaches Array aus... 🙂 eine Frage hätte ich da jedoch noch - am Ende von meinem Programm habe ich ein "Logische XOR" in die while-Schleife geklatscht, hätte jedoch gerne noch "i < genauigkeit" mit eingebaut, funktioniert nur leider bei mir nicht ... ?!?

    [cpp]#include <stdio.h>
    
    int main(void) {
    	float kommazahl, kommazahl_darstellung;
    	float array_kommazahl[32], array_kommazahl_ergebnis[32];
    	char array_rest[32];
    	int y=0, zahl, rest, ergebnis;
    	int i=0, j=0, loop=0, basis, genauigkeit=30;
    
    	/* mache etwas (min. 1-mal) ... */
    	do { 
    		printf("Bitte eine positive Kommazahl eingeben:");
    		scanf("%f", &kommazahl);
    	/* ... solange die Eingabe kleiner 0 */
    	} while (kommazahl < 0);
    
    	/* mache etwas (min 1-mal) ... */
    	do {
    		printf("Bitte eine Basis >=2 ein:");
    		scanf("%d", &basis);
    	/* ... solange die Eingabe kleiner 2 */ 
    	} while (basis < 2 );
    
    /*
    	z.B.: die Dezimalzahl 8 soll ins 2er-System umgewandelt werden
    
    	Verfahren:
    	(1) Teile die Zahl mit Rest durch 2.
    	(2) Der Divisionsrest ist die naechste Ziffer (von rechts nach links).
    	(3) Falls der (ganzzahlige) Quotient = 0 ist, bist du fertig,
    		andernfalls nimm den (ganzzahligen) Quotienten als neue Zahl 
    		und wiederhole ab (1).
    
    	8 : 2 = 4  Rest: 0
    	4 : 2 = 2  Rest: 0
    	2 : 2 = 1  Rest: 0
    	1 : 2 = 0  Rest: 1
    
    	-> Resultat: 1000
    */
    
    	printf ("\nV O R K O M M A S T E L L E N:\n\n");
    
    	/* nur die Vorkommastellen (Integer = ganze Zahl) in die Variable 'zahl' schreiben */
        zahl = (int) kommazahl;
    
    	while (zahl > 0) { // (3)
    		rest = zahl % basis; // (1)
    		array_rest[y++] = rest; // Array fuer die umgekehrte Reihenfolge der Ausgabe
    		ergebnis = zahl / basis;
    		printf("%d : %d = %d  Rest: %d\n", zahl, basis, ergebnis, rest); // Ausgabe 
    		zahl = zahl / basis; // (2)
    	}
    
    	printf("\n-> Resultat: ");
    	while (--y >= 0) { // umgekehrte Reihenfolge der Ausgabe
     		printf("%d", array_rest[y]);
    	}
    
    /* 
    	z.B: der Dezimalbruch  0,8  soll ins 2er System umgewandelt werden
    
    	Verfahren fuer Nachkommaziffern:
    	(1) Multipliziere die Zahl mit der Basis 2
    	(2) Die Zahl vor dem Komma ist die naechste Ziffer des Ergebnisses
    	(3) Schneide die Zahl vor dem Komma weg.
    	(4) Wiederhole ab (1), bis der Rest 0 ist, sich ein Rest wiederholt
    		oder die gewuenschte Genauigkeit erreicht ist.
    
    	2 · 0,8 = 1,6    --> Ziffer: 1
    	2 · 0,6 = 1,2    --> Ziffer: 1
    	2 · 0,2 = 0,4    --> Ziffer: 0
    	2 · 0,4 = 0,8    --> Ziffer: 0
    	2 · 0,8 = 1,6    --> Ziffer: 1
    
    	Der "Rest" 1,6 trat im 1. Schritt bereits auf.
    	Ab dort wiederholen sich die Nachkommaziffern periodisch.
    
    	-> Resultat: 0,1100110011001100110011001100110011001100110011001100...
    */
    
    	printf ("\n\n\nN A C H K O M M A S T E L L E N:\n\n");
    
    	kommazahl = kommazahl - (int) kommazahl; // z.B. kommazahl = 2,5 - 2 = 0,5
    	kommazahl_darstellung = kommazahl; // nur zur Veranschaulichung in der Ausgabe
    
    	do {
    		kommazahl *= basis; // (1)
    		kommazahl = ( (int) (kommazahl * 1000.0 + 0.5)) / 1000.0; // Runden auf 4 Nachkommastellen
    		array_kommazahl[j] = kommazahl; // Restwert in ein Array schreiben
    
    		for ( j=0; j < i; j++ ) { 
    			// printf("\ntest - [%d][%d] - %f\n", i, j, array_kommazahl[j]); // test - Ausgabe
    			if ( array_kommazahl[j] == kommazahl ) { // (4) - Wiederholung feststellen
    				loop = j;
    			}
    		}
    
    		if ( (int) kommazahl == 0 && loop == 0) { // (2)
    			printf ("%d * %.1f = %.1f  --> Ziffer: %d\n", basis, kommazahl_darstellung, kommazahl, (int) kommazahl); // Ausgabe
    			array_kommazahl_ergebnis[j] = (int) kommazahl;
    		} else if ( (int) kommazahl != 0 && loop == 0) { // (2) 
    			printf ("%d * %.1f = %.1f  --> Ziffer: %d\n", basis, kommazahl_darstellung, kommazahl, (int) kommazahl); // Ausgabe
    			array_kommazahl_ergebnis[j] = (int) kommazahl;
    			kommazahl -= (int) kommazahl; // (3)
    		}
    
    		if ( loop >= 1 ) {
    			printf ("\nDer \"Rest\" von %f trat im %d. Schritt bereits auf.\nAb dort wiederholen sich die Nachkommaziffern periodisch.\n", array_kommazahl[j-1], loop); 
    			printf ("\n-> Resultat: 0,");
    			for ( j=0; j < i; j++ ) {
    				printf ("%d", (int) array_kommazahl_ergebnis[j]);
    			}
    			printf ("\n");
    		}
    
    		if ( kommazahl == 0.0 ) {
    			printf ("\nEs ist kein Rest mehr uebrig... :-)");
    			printf ("\n-> Resultat: 0,");
    			for ( j=0; j < i; j++ ) {
    				printf ("%d", (int) array_kommazahl_ergebnis[j]);
    			}
    			printf ("\n");
    		}
    
    		if ( i >= genauigkeit ) {
    			printf ("\nDie Genauigkeit sollte nun ausreichen... (%d Bit)", genauigkeit);
    			printf ("\n-> Resultat: 0,");
    			for ( j=0; j < i; j++ ) {
    				printf ("%d", (int) array_kommazahl_ergebnis[j]);
    			}
    			printf ("\n");
    			break;
    		}
    
    		kommazahl_darstellung *= basis; // nur zur Veranschaulichung in der Ausgabe
    		kommazahl_darstellung = ( (int) (kommazahl_darstellung * 1000.0 + 0.5)) / 1000.0; // nur zur Veranschaulichung in der Ausgabe
    		kommazahl_darstellung -= (int) kommazahl_darstellung; // nur zur Veranschaulichung in der Ausgabe
    
    		i++;
    		j++;
    //	} while ( ( i < genauigkeit ) || !(!(loop == 0 && kommazahl != 0.0 ) && !(loop == 0 && kommazahl != 0.0 )) ); // (4) + Logisches XOR
    	} while ( !(!(loop == 0 && kommazahl != 0.0 ) && !(loop == 0 && kommazahl != 0.0 )) ); // (4) + Logisches XOR
    
    	return(0);
    }[/cpp]
    

Anmelden zum Antworten