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
0test - [2][1] - 0.400000
test - [2][2] - 0.800000
1test - [3][1] - 0.400000
test - [3][2] - 0.800000
test - [3][3] - 1.600000
1test - [4][1] - 0.400000
test - [4][2] - 0.800000
test - [4][3] - 1.600000
test - [4][4] - 1.200000
0Der "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
0test - [2][1] - 0.000000
test - [2][2] - 0.000000
1test - [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]