• Hallo Gast, du kaufst gerne günstig ein und erfährst oft vor deinen Freunden von interessanten Angeboten? Dann kannst du dein Talent als Schnäppchenjäger jetzt zu Geld machen und anderen PCGH-Lesern beim Sparen helfen! Schau einfach mal rein - beim Test der Community Deals!

C Programm zum Potenzieren - Fehler

funnymonkey

Komplett-PC-Käufer(in)
Hallo an alle PCGH'ler da drausen,

ich bin gerade dabei mir C beizubringen und habe zum Üben ein Programm geschrieben, dass aus der Eingabe zweier Zahlen (base & exponent) die Potenz daraus berechnet. Eigentlich wollte ich damit ausprobieren, was passiert, wenn man die pow() Funktion mit negativen Eingaben füttert.
Mein Programm sieht bis jetzt so aus:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
    double base;
    double exponent;
    double result;
    int temp;

    printf("Geben Sie die Basis ein, zu der potenziert werden soll:\n");
    temp = getchar();
    base = atof(temp);
    printf("Geben Sie den Exponenten ein:\n");
    temp = getchar();
    exponent = atof(temp);

    result = pow(base,exponent);

    printf("Ergebnis: %0.f", result);

    return 0;
}
Nun passiert folgendes: Wenn ich für die Basis ein Zahl eingebe und Enter drücke kommt die Windows 7 Fehlermeldung: Das Programm (hier: Potenzieren.exe) funktioniert nicht mehr. Es wird nach einer Lösung gesucht. Wieso kommt diese Fehlermeldung bzw. warum stürzt diese Programm ab? Vielen Dank schon mal im Voraus.

LG funnymonkey
 

crusherd

Komplett-PC-Aufrüster(in)
Hi,

Da du anscheinend mit Visual Studio arbeitest, würde ich dein Programm mit dem Debugger starten.

Edit:

Mit was kompilierst du das Programm?
Wenn ich deinen Code in VS2012 werfe, bekomme ich Compilier-Fehler und zwar für die Funktion atof().
Was erwartet atof()?
 
Zuletzt bearbeitet:
TE
funnymonkey

funnymonkey

Komplett-PC-Käufer(in)
Ich arbeite mit Code::Blocks und mingw-Compiler. Eine Fehlermeldung erhalte ich nicht.

Laut C++ Reference erwartet atof() einen String. Ich glaube so langsam dämmerts. Meine Eingabe ist durch getchar() ein Integer. Ich werde es gleich ausprobieren, muss davor aber noch was erledigen. Danke für den Wink.

LG funnymonkey
 

crusherd

Komplett-PC-Aufrüster(in)
Kein Problem. Jeder fängt mal klein an und dazu gehören auch nun mal Fehler. ;)

Falls du nicht weiterkommen solltest, habe ich eine Lösung, mit der du Zahlen ohne Probleme potenzieren kannst. (Basiert auf deinem Code) :)

Gruß
crusherd
 

DarkMo

Lötkolbengott/-göttin
getchar liest ein einziges zeichen ein. ein 3.5 könntest du also nie einlesen, sondern nur integer zahlen zw 0 und 9 ^^ probier doch mal eher scanf aus - das ließt ne zeichenkette ein bis du enter drückst. natürlich kann atof (char zu float) "hallo" dann nich umwandeln ^^
 
TE
funnymonkey

funnymonkey

Komplett-PC-Käufer(in)
Das kam in meinem Buch ("C für Dummies") auch schon vor, nur war ich mir nicht mehr sicher, welche der beiden Funktionen das Enter mit ausliest. Deshalb hab ich zum Ausprobieren getchar() genommen.
Ich habe den Code wie folgt abgeändert:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
    double base;
    double exponent;
    double result;
    char temp [20];

    printf("Geben Sie die Basis ein, zu der potenziert werden soll:\n");
    scanf("%s", temp);
    base = atof(temp);
    printf("Geben Sie den Exponenten ein:\n");
    scanf("%s", temp);
    exponent = atof(temp);

    result = pow(base,exponent);

    printf("Ergebnis: %2.f", result);

    return 0;
}
Jetzt funktionierts. :D Aber nur mit den Zahlen von 0-9. Wenn ich z.B. 1536 und 1256 eingebe kommt als Ergebnis 1 raus. Wieso? Hat float nur eine Stelle vor dem Komma?

@crusherd: Ist das ungefähr so, wie du es gelöst hast?

Nochmals danke an alle.
Eine Frage hätte ich noch, ist zwar Off-Topic, aber egal: Kennt ihr eine populäre Anwendung, die auf C basiert?

LG funnymonkey
 

nay

PC-Selbstbauer(in)
1. Warum nutzt du scanf nicht, um direkt in die double Variable zu lesen?? scanf("%lf", &base)
2. Das Ergebnis 1536 hoch 1256 ist zu groß, um von double dargestellt zu werden.
 
TE
funnymonkey

funnymonkey

Komplett-PC-Käufer(in)
1. Ich weiß nicht wie das geht. Zu was ist das & vor base?
2. Ok. Aber das Komma lässt sich verschieben, oder? Wie kann ich so große Zahlen darstellen?

Edit: Ich habe das jetzt so abgeändert:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
    long double base;
    long double exponent;
    long double result;

    printf("Geben Sie die Basis ein, zu der potenziert werden soll:\n");
    scanf("%Lf", &base);
    printf("Geben Sie den Exponenten ein:\n");
    scanf("%Lf", &exponent);

    result = pow(base,exponent);

    printf("Ergebnis: %2.Lf", result);

    return 0;
}
Geht aber trotzdem nicht. Auch nicht mehr mit Zahlen <9.
 
Zuletzt bearbeitet:

crusherd

Komplett-PC-Aufrüster(in)
Hey,

Wie nay schon geschrieben hat, du kannst mit scanf direkt ein double einlesen. Das & wird benötigt, da scanf einen Zeiger auf Speicher erwartet, in den es schreiben kann. Du lieferst mit &base quasi einen Zeiger ( genau genommen die Adresse von base) wohin scanf schreiben soll.

So eine ähnliche Lösung wie du habe ich. ;-)
Morgen kann ich dir meine Lösung und paar hilfreiche Tipps geben, wo man sucht. Bin leider imo nur mobil hier. :-(

Eine erste Anlaufstelle ist www.cplusplus.com und die dortige C-Bibliothek.


Gruß
crusherd
 

DarkMo

Lötkolbengott/-göttin
nuja, wies scheint lernt er grade erstmal puristisches c ^^ kann mich natürlich auch irren. aber dann gäbe es kein cin :D
 

nay

PC-Selbstbauer(in)
Für Zahlen, die die Länge von double überschreiten gibt es keinen Standarddatentyp. Es gibt sicher Bibliotheken, die du einbinden könntest, um größere doubles zu bekommen.
Das "&" vor dem Parameter steht in diesem Fall dafür, dass die Variable durch die Funktion verändert wird. In deinem C Buch wird das sicher in den nächsten Kapiteln genauer behandelt.

Was meinst du mit "geht nicht"???
 

crusherd

Komplett-PC-Aufrüster(in)
Hi,

So wie versprochen mal der Code. Dies ist nur eine mögliche Lösung:
Code:
[COLOR=black]#include <stdio.h>[/COLOR]
[COLOR=black]#include <stdlib.h>[/COLOR]
[COLOR=black]#include <math.h>[/COLOR]

[COLOR=black]int main(){[/COLOR]
[COLOR=black]double base = 0;[/COLOR]
[COLOR=black]double exponent = 0;[/COLOR]
[COLOR=black]double result = 0;[/COLOR]

[COLOR=black]printf("Geben Sie die Basis ein, zu der potenziert werden soll:\n");[/COLOR]
[COLOR=black]scanf("%lf", &base);[/COLOR]
[COLOR=black]printf("Geben Sie den Exponenten ein:\n");[/COLOR]
[COLOR=black]scanf("%lf", &exponent);[/COLOR]

[COLOR=black]result = pow(base,exponent);[/COLOR]

[COLOR=black]printf("Ergebnis: %.2f\n", result);[/COLOR]

[COLOR=black]return 0;[/COLOR]
[COLOR=black]}[/COLOR]

Anleitungen, wie man scanf() und printf() verwendet:
scanf - C++ Reference

printf - C++ Reference

Außerdem ist die Seite sehr hilfreich beim Programmieren:
Stack Overflow

Wenn dein Programm nicht das tut, was es soll, solltest du mal dein Programm debuggen. Damit hast du die Möglichkeit zu sehen, was dein Programm macht und welche Werte deine Variablen haben bzw. bekommen.
Wie das mit Code::Blocks und mingw geht, weiß ich leider auf die Schnelle nicht, da müsstest du mal die Anleitung dazu lesen.

Gruß
crusherd
 
TE
funnymonkey

funnymonkey

Komplett-PC-Käufer(in)
@crusherd: Cool, sieht fast so aus wie mein Quellcode. Warum initalisierst du die Variablen am Anfang mit 0? Falls die Speicheradresse noch nicht gelöscht ist?

Am Anfang konnte ich noch Zahlen, die kleiner als 9 waren, potenzieren.
Mittlerweile (Code geändert wie in Post #9) ist es so, dass ich auch bei 9 hoch 9 als Ergebnis -2 bekomme. Obwohl die Datentypen allesamt vom Typ long double. Ich habe im Quellcode zum Ausprobieren die Datentypen in double umgewandelt. Dann funktioniert es, ich kann aber nicht die Vorteile von long double nutzten. Stimmt es, dass man um mit scanf() einen long double in die entsprechende Variable zu speichern, man das kleine l durch ein große ersetzen muss?

Und ja, ich lerne puristisches, einfachstes C. Aber www.cplusplus.com hilft gerade als Nachschlagewerk schon extrem.

LG funnymonkey
 
Zuletzt bearbeitet:
TE
funnymonkey

funnymonkey

Komplett-PC-Käufer(in)
@crusherd: Typisch Mircosoft, tztztz... .

Danke @ all. Jetzt funktioniert das so, wie ich es mir gedacht habe. Ihr habt mir echt geholfen.

LG funnymonkey
 

crusherd

Komplett-PC-Aufrüster(in)
kein Thema. ;)

Falls du irgendwann mit Linux arbeiten willst, empfehle ich dir den clang compiler zu holen und mit dem zu arbeiten, da er gesprächiger und hilfsbereiter ist als der gcc. :)

Gruß
crusherd
 

DarkMo

Lötkolbengott/-göttin
noch eine simple (und nicht immer nutzbare) debugmethode ist das "echo debugging". ich habs in zusammenhang mit php (ausgaben per echo-befehl) kennengelernt. besagt nix anderes, als dass man zur überprüfung der werte zur laufzeit, diese einfach ausgeben lässt ^^ wie gesagt, simpel aber oft dennoch nützlich.
 

Triniter

PC-Selbstbauer(in)
noch eine simple (und nicht immer nutzbare) debugmethode ist das "echo debugging". ich habs in zusammenhang mit php (ausgaben per echo-befehl) kennengelernt. besagt nix anderes, als dass man zur überprüfung der werte zur laufzeit, diese einfach ausgeben lässt ^^ wie gesagt, simpel aber oft dennoch nützlich.
Jepp, typisches printf-debugging. Wird teilweise während der Entwicklung sogar in Embedded Projekten eingesetzt, da ist dann halt die Standardausgabe nicht ein Monitor sondern z.B. eine serielle Schnittstelle. Wenn du also dein Projekt von vorhin hernimmst kannst du folgendes machen:

Code:
[COLOR=black]#include <stdio.h>[/COLOR] 
[COLOR=black]#include <stdlib.h>[/COLOR] 
[COLOR=black]#include <math.h>[/COLOR]  
[COLOR=black]int main()
{
[/COLOR]   [COLOR=black]double base = 0;
[/COLOR]   [COLOR=black]double exponent = 0;
[/COLOR] [COLOR=black]  double result = 0;
[/COLOR]   [COLOR=black]printf("Geben Sie die Basis ein, zu der potenziert werden soll:\n");[/COLOR] [COLOR=black]
   scanf("%lf", &base);[/COLOR]
   printf("Debugausgabe Basis: %f/* oder %e*/\n", base);
   [COLOR=black]printf("Geben Sie den Exponenten ein:\n");[/COLOR] 
   [COLOR=black]scanf("%lf", &exponent);[/COLOR] 
   printf("Debugausgabe Exponent: %f/* oder %e*/\n", [COLOR=black]exponent[/COLOR]); 
   [COLOR=black]result = pow(base,exponent);[/COLOR]  
   [COLOR=black]printf("Ergebnis: %.2f\n", result);[/COLOR]  
   [COLOR=black]return 0;[/COLOR] 
[COLOR=black]}[/COLOR]

Interessant wird die Aufgabe jetzt noch wenn du hingehst und nicht die Funktion pow() verwendest sondern versuchst die Funktion selbst zu erstellen.
 
Zuletzt bearbeitet:

fadade

BIOS-Overclocker(in)
Interessant wird die Aufgabe jetzt noch wenn du hingehst und nicht die Funktion pow() verwendest sondern versuchst die Funktion selbst zu erstellen.

:D
Nicht unbedingt die performanteste Lösung, aber funktional (Java/C#-Code):

Code:
            /// Berechnet k  ^ n
            /// Negative Potenzen erlaubt
            public static double exp(double k, int n)
            {
                double erg = 1.0;

                if (n == 1)
                {
                    return k;
                }
                else if (n > 1)
                {
                    while (n-- > 0)
                    {
                        erg *= k;
                    }
                }
                else if (n < 0)
                {
                    erg = 1 / exp(k, -n);
                }

                return erg;
            }
 
Zuletzt bearbeitet:
TE
funnymonkey

funnymonkey

Komplett-PC-Käufer(in)
Wenn ich das richtig verstehe wird bei printf-debugging jeder Schritt durche eine printf() Funktion ausgegeben und es lässt sich so feststellen, bei welchem Schritt es hakt. Oder?

@fadade: Was wäre denn performanter? Schon mit vorberechneten Werten arbeiten und in deinem Fall n ungefähr einordnen?
 

DarkMo

Lötkolbengott/-göttin
man muss ned überall ne ausgabe bauen, aber man kann es natürlich ^^ am besten schreibt man dann sowas wie "stelle so und so im code, variable bla hat wert blubb". oder man schreibt einfach nur 1 2 3 4 pro print und kann dann sehen, aha, bis zur 3 is er gekommen, die 4 führt er scho ned mehr aus, also muss irgendwo nach dem print(3) befehl was im argen sein ^^

wie gesagt, stell dir darunter nix kompliziertes oder weltbewegendes vor.
 

fadade

BIOS-Overclocker(in)
Wenn ich das richtig verstehe wird bei printf-debugging jeder Schritt durche eine printf() Funktion ausgegeben und es lässt sich so feststellen, bei welchem Schritt es hakt. Oder?

Sinnvollerweise platziert man die Debug-Ausgaben nur an den Stellen, wo "kritische"/wichtige Aktionen passieren. Darüber hinaus kannst du die Ausgaben auch noch etwas tiefergehend modifizieren, sprich wenn sich eine Variable x aus den Werte 325, y, 2*k, ... zusammensetzt kannst du entweder nur das Ergebnis x ausgeben oder sowas wie "x=[wert], zusammengesetzt aus y=[wert], k=[wert] ...". Das macht die Rückverfolgung einfacher. Ich würde mal sagen, dass man aus dieser Form des "Debuggens" keine so große Wissenschaft machen sollte; man gibt halt aus, was halbwegs sinnvoll ist und zur Fehlerfindung beiträgt :D

@fadade: Was wäre denn performanter? Schon mit vorberechneten Werten arbeiten und in deinem Fall n ungefähr einordnen?
Vorberechnete Werte machen wenig Sinn, dazu ist der kombinatorische Wertebereich zu groß. Allerdings kann man hier gut antworten mit "kommt auf die Eingabedaten an" ;)
Es kann ja sein, dass die Methode seeehr oft, mit eher kleinen Potenzen aufgerufen wird, oder nicht so oft, aber dafür mit höheren Potenzen, oder auch immer nur mit negativen Werten oder oder. Da könnten mehrere separate Methoden dann performanter sein - sind aber auch nicht so flexibel. Auf Ebene des Maschinencodes (wie es wohl bei der verfügbaren pow-methode der Fall sein wird) kann man da natürlich auch noch etwas drehen ... mir war einfach eine funktionale Methode wichtig :)
 
Oben Unten