Forum: PC-Programmierung SUDOKU (python) nach #C portieren.


You were forwarded to this site from EmbDev.net. Back to EmbDev.net
von Peter W. (pe_wi)


Angehängte Dateien:

Lesenswert?

Hallo
Ich mache gerade den Versuch ein SUDOKU Programm (python) nach #C zu 
portieren.
Ich bin Hobby Programmierer. Es funktioniert schon ein wenig.
In der einen for Schleife gibt es Probleme. Manchmal wird die Variable 
nicht mit dem Startwert 1 belegt, sondern geht z.B mit 11 weiter.

Vielen Dank für eure Hilfe
Peter

: Verschoben durch Moderator
von Programmierer (Gast)


Lesenswert?

Was ist #C?

von re (Gast)


Lesenswert?

Peter W. schrieb:
> In der einen for Schleife gibt es Probleme

Mag das daran liefgen, dass Du alle Schleifenvariablen global 
deklarierst, aber die Funktion, in der Du sie benutzt, moch innerhalb 
der Schleife rekusiv aufrufst. So benutzt Du die gleiche Instanz der 
Schleifenvariablen gleichzeitig mehrfach Das kann eigentlich nur 
schiefgehen.

hint: for (int i=0; i<9; i++){...}

HTH
(re)

von IT-Abteilung (Gast)


Lesenswert?

Peter W. schrieb:
> Ich mache gerade den Versuch ein SUDOKU Programm (python) nach #C zu
> portieren.

🤦🤦🤦
Wie kommt man auf so eine Idee?

von Einer (Gast)


Lesenswert?

Peter W. schrieb:
> Ich mache gerade den Versuch ein SUDOKU Programm (python) nach #C zu
> portieren.

Das ist falsch. Du musst avaJ nehmen.

von Peter W. (pe_wi)


Angehängte Dateien:

Lesenswert?

#re

In der Funktion werden jetzt keine Variablen mehr übergeben, sind ja 
global. Leider ist die Ausgabe immer noch genau so falsch (Werte bis 
14).

Peter

von re (Gast)


Lesenswert?

Peter W. schrieb:
> Leider ist die Ausgabe immer noch genau so falsch

Die Schleifenvariablen sind ja auch immer noch global definiert.

| #include <stdio.h>
|
| #define FALSE 0
| #define TRUE !(FALSE)
|
| char zeile=0, spalte=0, zahl=0, x=0, y=0, xi=0, yi=0, xLO, yLO, xD, yD;

Als erstes sollten die lokal definiert sein, so wie oben vorgeschlagen.
Dann kann man weitersehen.

(re)

von Peter W. (pe_wi)


Angehängte Dateien:

Lesenswert?

Ich weiß nicht wie ich das mit zahl, x und y in der funktion loesung 
machen soll, damit das nicht kollidiert! x, y lokal klappt so einfach 
auch nicht.
Hat jemand noch einen Tip für mich?

Danke Peter

von re (Gast)


Lesenswert?

Peter W. schrieb:
> Ich weiß nicht wie ich das mit zahl, x und y in der funktion loesung
> machen soll

... indem man für die Schleife keine globale Variable nimmt, wie in

| #include <stdio.h>
|
| char zeile=0, spalte=0, zahl=0, x=0, y=0, xi=0, yi=0, xLO, yLO, xD, yD;

sondern die schleifenvariable nur innerhalb der Schleife deklariert:

| void loesung()
| :
| for (int x=0;x<9;x++){
|    :
|    for(int y=0;y<9;y++){
|       :
|       for (int zahl=1;zahl<10;zahl++){
|         :
|         loesung();
|       }
|    }
| }
und außerhalb unzugänglich lässt. Ich hoffe, das ist jetzt klarer.


Nebenbei aber noch für unser Verständnis:

(a) Welche Sprache wird das nun eigentlich? Weil:
* Du schreibst von "#C", aber zu "C#" passt die Syntax nicht so recht, 
und
* die Dateiendung deutet aber auf "C++", aber
* der Code selbst ist weder c++/cpp noch C#, sondern eher 
"Kernigham-Ritchie-C (1978)", wozu die Dateiendung aber nicht passt.

Die drei Kandidaten haben bis auf das "C" im Namen nur recht wenig 
gemeinsam.
Könntest Du das aufklären?



(b) Die Funktion "loesung ()" wird rekursiv aufgerufen, jedoch jedesmal 
mit den gleichen Aufrufparametern (nämlich keinen). Das deutet 
normalerweise auf einen Programmierfelher hin. Ist das so gewollt?


(c) Der Rückgabewert von "char loesung()" ist nur für bestimmte Pfade 
fefiniert ("return 0;"), im allgemeinen Fall jedoch von Zufall abhängig. 
Das deuet normalerweise auf einen Programmierfehler hin, aber

(d) Der Rückgabewert von "char loesung()" wird überhaupt nirgends 
ausgewertet, auch nicht beim rekursiven Aufruf. Auch das deutet 
normalerweise auf Programmierfehler hin. Hat diese Konstruktion einen 
besonderen Hintergrund?

HTH;
(re)

von cppbert3 (Gast)


Lesenswert?

Bitte

nimm int anstatt char, das ist geläufig, char ist sehr ungewöhnlich

die Variable in der for Schleife definieren, weniger fehleranfällig und 
nicht style von vor 30 jahren

Also for(int x = ...

Nicht immer erst die variable definieren und dann x Zeilen darunter 
initalisieren, einfach

int blub = 32;

Und KEINE globalen variablen!

Nach der Korrektur können wir über Logikfehler diskutieren

von Rolf M. (rmagnus)


Lesenswert?

re schrieb:
> eher "Kernigham-Ritchie-C (1978)"

Ich sehe da kein K&R C, sondern bis auf die Zeilenkommentare C89.

von Peter W. (pe_wi)


Angehängte Dateien:

Lesenswert?

Erst mal vielen Dank für die Antworten

Ich habe jetzt alle Variablen als lokal geändert. In der Funktion 
loesung "return" berichtigt.
Jetzt erhalte ich als Ausgabe das ungelöste sudoku!
Wie gesagt, ich versuche die datei sudoku.py zu portieren. Ich arbeite 
mit DevC++. Die Kommentare in sudok12.cpp sind die vom pyhton Programm.

mfG
Peter

von re (Gast)


Lesenswert?

Prima, schon ein wenig Fortschritt.

Ich würde in Zeile 99, kurz vor der letzten schließenden Klammer von 
'loesung()' mal versuchsweise ein "ausgabe();" plazieren. Nur zum 
Testen, Erklärung weiter unten.



Die Fragen nach dem Hintergrund von (b) und (d) waren übrigens durchaus 
ernst gemeint. Das Beheben des "seltsamen Aussehens" ist zwar auch schon 
ein Fortschritt, behebt aber nicht den eventuellen Denkfehler, der einen 
dazu gebracht hat, dieses Konstrukt so zu formulieren, sondern nur den 
Hinweis auf den Denkfehler.



Aber weiter mit konkreteren Dingen: In Zeile 88 hast Du das Konstrukt

| zahlen[x][y] = zahl;
| loesung();
| zahlen[x][y] = 0;

welches sich mir nicht direkt erschließt.
Wo immer in "zahlen[x][y]" eine Zahl eingetragen wird, wird sie direkt 
nach dem Aufruf wieder auf "0" gesetzt.

Deswegen bekommst Du immer wieder die originale Besetzung heraus.



Deswegen die Frage (b) nach der Sinnhaftigkeit des rekursiven Aufrufs.
Der soll vermutlich dazu dienen, die weiteren fehlenden Zahlen 
einzusetzen.

In Zeile 82 prüft "loesung()" jede Zelle ab, ob sie noch zu besetzen 
ist. Nun hätte ich erwartet, dass der entweder terminiert oder ein 
"fertig" ausgibt, wenn er findet, dass alle Zellen besetzt sind - das 
würde man daran erkennen, dass er bis zur letzten schließenden Klammer 
von loesung() in Zeile 99 kommt.

Da hätte ich jetzt entweder sowas wie ein "return TRUE;" erwartet.
Oder ein aufruf von ausgabe(), bevor die Funktion verlassen wird.
Die würde dann in jedem Fall ein gelöstes Sudoku ausgeben, bevor es 
wieder mit Nullen überschrieben wird.


Besser würde man es natürlich mit einem Rückgabewert machen, so wie es 
vorher schon in Fragmenten angefangen war, aber der Rückgabewert muss 
dann auch 1.) in jedem Zweig zurückgegeben werden und 2.) nach dem 
Aufruf ausgewertet werden.


Funktioniert das bei Dir, mit dem "ausgabe()"?

HTH
(re)

von re (Gast)


Lesenswert?

Im Übrigen @TO: Du hast doch vorher überprüft, ob das ungelöste Sudoku 
überhaupt mindestens eine Lösung hat, oder?

(re)

von Peter W. (pe_wi)


Angehängte Dateien:

Lesenswert?

re schrieb:
> Ich würde in Zeile 99, kurz vor der letzten schließenden Klammer von
> 'loesung()' mal versuchsweise ein "ausgabe();" plazieren. Nur zum
> Testen, Erklärung weiter unten.

Das war der richtige Tip - jetzt funktioniert es, aber warum?

DevC++ in der Fehlersuche ist total Fehleranfällig, und nervt total! 
Gibt es ein alternatives einfaches Programm, welches funktioniert?

re schrieb:
> Aber weiter mit konkreteren Dingen: In Zeile 88 hast Du das Konstrukt
>
> | zahlen[x][y] = zahl;
> | loesung();
> | zahlen[x][y] = 0;
>
> welches sich mir nicht direkt erschließt.
> Wo immer in "zahlen[x][y]" eine Zahl eingetragen wird, wird sie direkt
> nach dem Aufruf wieder auf "0" gesetzt.

Die Zahlen werden nur gelöscht, wenn zahl = 10 ist. Dann wird aus: 
for (int zahl= 1; zahl< 10; zahl++) rausgesprungen und durch return 
gelangt man zur zeile: zahlen[x][y] = 0;

Es funktioniert!

Vielen Dank für die Unterstützung

mfG
Peter

von re (Gast)


Lesenswert?

Peter W. schrieb:
> aber warum?

Naja, auf die Gefahr hin, mich zu wiederholen: Die Funktion "loesung()" 
in Deinem Programm ruft sich selbst rekursiv auf, wenn noch etwas zu tun 
ist (also ein Feld noch 0 enthält) und sie läuft nur dann (ohne weitere 
Rekursion) bis zum Ende durch, wenn die Lösung fertig ist, also kein 
einziges Feld mehr "0" enthält.

Davon, dass die Lösung fertig ist und die Funktion bis zum Ende gelangt, 
merkt aber niemand etwas, wenn dort nicht sowas wie "ausgabe()" oder 
"return FERTIG" steht, oder sonstwas mit dieser Bedeutung.

HTH ;-)



Peter W. schrieb:
> Die Zahlen werden nur gelöscht, wenn zahl = 10 ist. Dann wird aus:
> for (int zahl= 1; zahl< 10; zahl++) rausgesprungen und durch return
> gelangt man zur zeile: zahlen[x][y] = 0;

Mit Verlaub, da bist Du aber schwer auf dem Holzweg:

(a) Die Zahlen werden immer "gelöscht". Ansonsten müsste da ein if 
oder sowas stehen. Durch "return" gelangt man nicht zu irgendwelchen 
Zeilen, sondern nur aus dem aktuellen Funktionkontext heraus.
(b) Wenn "loesung()" mit "return" verlassen wird, bist du in jedem Fall 
hinter dem Aufruf von "loesung()" (Zeile 89) und danach geht es in jedem 
Fall mit "zahlen[x][y]=0;" weiter.
(c) Im Übrigen wird "zahl" niemals "10" - schließlich ist es ja nur 
innerhalb der Schleife sichtbar und dort wird auf "zahl<10" geprüft, 
bevor der Schleifenkörper durchlaufen wird.

Aber egal, es geht ja nun.



Peter W. schrieb:
> DevC++ in der Fehlersuche ist total Fehleranfällig, und nervt total!
> Gibt es ein alternatives einfaches Programm, welches funktioniert?

Meinst Du Compiler oder IDE? Und warum benutzt Du es denn, wenn es so 
nervt?
Und ja, gibt es. Tausende. Welches für Dich passt, hängt davon ab, was 
Du von ihm erwartest.

Davon abgesehen, ich denke, bevor man Werkzeuge zum Debugging anwirft, 
sollte man für sich selbst erstmal klargestellt haben, wie die 
Funktionsweise des eigenen Programms und seiner Teile sein soll.

Wenn das nicht steht, dann bastelt man meist nur an den Symptomen, aber 
nicht am eigentlichen Problem.



my2ct
(re)

von Peter W. (pe_wi)


Lesenswert?

Also der Test im debugger läuft das so:

1.wenn eine zahl (beginnend von 1 bis 9) an der freien Position paßt, 
wird  sie geschrieben - und wieder rekursiv loesung() aufgerufen.
2. dann wird die nächste freie Position gesucht u.s.w
3. paßt keine zahl 1 bis 9 wird for (int zahl= 1; zahl< 10; zahl++) 
durch return verlassen und man gelangt zur letzten berechneten Position: 
nach loesung() zur zeile zahlen[x][y]=0;
4. die zahl der letzte Position wird gelöscht und von der letzten 
gespeicherten zahl weiter geteste, ob sie geht.

Sehe ich das alles falsch?

Kannst Du eine "einfache" IDE für C# empfehlen?

mfG
Peter

von c-hater (Gast)


Lesenswert?

Peter W. schrieb:

> Kannst Du eine "einfache" IDE für C# empfehlen?

Für Windows: VisualStudio (unerreicht im Komfort)
Für Linux: MonoDevelop

Die sind allerdings beide nicht "einfach" im Sinne von "primitiv", 
sondern im Sinne von "erstmal relativ einfach zu benutzen".

Sie sind aber beide doch recht mächtig und deswegen kommt man bei beiden 
früher oder später doch an den Punkt, wo man sich auch mit der IDE 
selber beschäftigen muss.

Dein Projekt kann man aber wohl noch völlig problemlos abfackeln, ohne 
diesen Punkt zu erreichen...

von cppbert3 (Gast)


Lesenswert?

Peter W. schrieb:
> Kannst Du eine "einfache" IDE für C# empfehlen?

Visual stuio community, frei und der geläufigste compiler+ide unter 
windows

Und du programmierst hier C, das andere wäre C++, aber auf keinen Fall 
ist das hier gezeigte C#

von cppbert3 (Gast)


Lesenswert?

Du hast C Code in cpp C++ Dateien und sprichst von C#
Das letztere ist eine völlig andere Programmiersprache von Microsoft
da könntest du auch den Code zeigen und nach einer Java IDE fragen, lös 
dich von dem c#/C-Sharp begriff - ist hier völlig falsch

von re (Gast)


Lesenswert?

Peter W. schrieb:
> 3. paßt keine zahl 1 bis 9 wird for (int zahl= 1; zahl< 10; zahl++)
> durch return verlassen  [...]
>
> Sehe ich das alles falsch?

Nun... sie wird aber auch dann mit return verlassen, wenn doch eine 
oder mehrere Zahlen passen. Die eingesetzte Zahl wird in jedem Fall 
früher oder später im Array wieder "gelöscht", bevor loesung() zu einem 
Ende kommt.

Und deswegen ist es wichtig, dass bei irgendeiner Rekursionstiefe einmal 
signalisiert wird, wenn eine Lösung tatsächlich gefunden wurde, bevor 
sie letztendlich doch wieder mit '0' überschrieben wird - wie Du ...

Peter W. schrieb:
> Jetzt erhalte ich als Ausgabe das ungelöste sudoku!

... ja selbst beobachtet hast.


HTH
(re)

von Peter W. (pe_wi)


Lesenswert?

Ich hab hier einiges durcheinander gebracht!

Ich programmierst natürlich in C.
Visual stuio community wollte ich ausprobieren. Ist mir zu gewaltig und 
läuft so einfach bei mir nicht - man muß vermutlich einige GB 
nachinstallieren.

mfG
Peter

von Dirk K. (merciless)


Lesenswert?

Peter W. schrieb:
> Kannst Du eine "einfache" IDE für C# empfehlen?
https://www.codeblocks.org/

merciless

von re (Gast)


Lesenswert?

Peter W. schrieb:
> [MSVS] läuft so einfach bei mir nicht

Hm. Um da mal einen Ansatzpunkt zu finden:

(a) Welche Kriterien haben denn zur Auswahl des nun schon etwas in die 
jahre gekommenen DevC++ geführt?

(b) Unter welchen Systembedingungen soll das eigentlich laufen?


(re)

von Peter W. (pe_wi)


Lesenswert?

DevC++ ist einfach zu bedienen und deutsch. Eigendlich bin ich damit 
zufrieden. Aber beim debuggern funktioniert es oft nicht. Wenn man dann 
einen Fehler sucht kann man fast verzweifeln!
Windows 7 ist mein Freund.

mfG
Peter

von re (Gast)


Lesenswert?

Peter W. schrieb:
> Visual stuio community [...] läuft so einfach bei mir nicht
>
> Windows 7 ist mein Freund.

Naja, da sind unsere Freudeskreise wohl etwas disjunkt.

Etwas herumfragen in 4ma hat da übrigens einen Rechner zutage gefördert, 
auf dem MSVS(v15) auch unter Win7(64,SP1) auf einem Prozessorkern, etwa 
6GB RAM und insgesamt 60 GB Plattenplatz ganz zufriedenstellend läuft. 
Sollte also auch bei Dir ohne besondere Klimmzüge gehen.


Peter W. schrieb:
> Ist mir zu gewaltig

Ja, "schlank" geht anders. Aber wenn es der GDB nun nicht sein soll und 
teuere kommerzielle Produkte auch nicht infrage komen, dann muss man 
diese Kröte möglicherweise schlucken, wenn man Wert auf komfortables 
Debugging legt.

my2ct
(re)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.