Τα πάντα για την C

...του ubuntu και έργων ΕΛ/ΛΑΚ (Έργα-Οδηγοί-Προτάσεις)

Συντονιστής: konnn

Re: Τα πάντα για την C

Δημοσίευσηαπό Ilias95 » 09 Μαρ 2012, 16:17

Τελείωσα και το κεφάλαιο 9 με τις συναρτήσεις.

Ορίστε μια λύση για το 8ο programming project στην σελίδα 217:
Μορφοποιημένος Κώδικας: Επιλογή όλων
#include <stdio.h>
#include <stdbool.h> // bool, true, false
#include <stdlib.h> // srand(), rand()
#include <time.h> // time()

#define LOSE_POINT 7

#define FIRST_ROLL_WIN(sum) ((sum) == 7 || (sum) == 11)
#define FIRST_ROLL_LOOSE(sum) ((sum) == 1 || (sum) == 2 || (sum) == 12)

int roll_dice(void)
{
int a = (rand() % 6) + 1, b = (rand() % 6) + 1;
return a + b;
}

bool play_game(void)
{
int roll = 0, point, sum;

while (1) {
sum = roll_dice();
roll++;
printf("You rolled: %d\n", sum);

if (roll == 1) {
if (FIRST_ROLL_WIN(sum))
return true;
else if (FIRST_ROLL_LOOSE(sum))
return false;
else {
point = sum;
printf("Your point is %d.\n", point);
}
}
else {
if (sum == point)
return true;
if (sum == LOSE_POINT)
return false;
}
}
}

int main(void)
{
int wins = 0, losses = 0;
srand((unsigned) time(NULL));

while (1) {
bool play = play_game();
printf(play ? "You win!\n\n" : "You lose!\n\n");
play ? wins++ : losses++;

printf("Play again? ");
char answer = getchar();
if (answer != 'y' && answer != 'Y') {
printf("Wins: %d Losses: %d", wins, losses);
break;
}
getchar(); // catch '\n'
putchar('\n');
}

return 0;
}

Θέλω να ρωτήσω κάτι σχετικά με την παραπάνω λύση.
Στην συνάρτηση play_game() στα σημεία όπου έχουμε νίκη ή ήττα επέλεξα να φεύγω κατευθείαν απ' την συνάρτηση με την return επιστρέφοντας true ή false ανάλογα.
Έτσι όμως έχω 4 σημεία εξόδου απ' την συνάρτηση (τα οποία άλλη φορά μπορεί να ήταν περισσότερα).

Θα ήταν καλύτερα μήπως να θέσω μία μεταβλητή τύπου bool η οποία όπου έχουμε νίκη ή ήττα να γίνεται true ή false, να φεύγω απ' τον βρόχο με break και τελικά να επιστρέφω την μεταβλητή;
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό migf1 » 09 Μαρ 2012, 17:10

Ilias95 έγραψε:Τελείωσα και το κεφάλαιο 9 με τις συναρτήσεις.

:)

έγραψε:Ορίστε μια λύση για το 8ο programming project στην σελίδα 217:
...
Θέλω να ρωτήσω κάτι σχετικά με την παραπάνω λύση.
Στην συνάρτηση play_game() στα σημεία όπου έχουμε νίκη ή ήττα επέλεξα να φεύγω κατευθείαν απ' την συνάρτηση με την return επιστρέφοντας true ή false ανάλογα.
Έτσι όμως έχω 4 σημεία εξόδου απ' την συνάρτηση (τα οποία άλλη φορά μπορεί να ήταν περισσότερα).

Θα ήταν καλύτερα μήπως να θέσω μία μεταβλητή τύπου bool η οποία όπου έχουμε νίκη ή ήττα να γίνεται true ή false, να φεύγω απ' τον βρόχο με break και τελικά να επιστρέφω την μεταβλητή;

Άλλοι λένε να αποφεύγεις τα πολλά σημεία επιστροφής, άλλοι λένε να τα χρησιμοποιείς. Είναι καθαρά τι σε εξυπηρετεί καλύτερα ή μάλλον ποιο θεωρείς πως κάνει πιο ευανάγνωστο τον κώδικά σου.

Σε αυτό που συμφωνεί όμως η πλειοψηφία είναι πως μετά από return ή break μέσα σε if, το else αυτού του if είναι τελείως περιττό (και κάνει πιο δυσανάγνωστο τον κώδικα). Συνεχόμενα if (με break ή return) χωρίς else είναι πιο ευανάγνωστα.

Δες και μια εναλλακτική υλοποίηση του κώδικά σου (χωρίς να πειράζει καθόλου τη λογική σου)...

Μορφοποιημένος Κώδικας: Επιλογή όλων
#include <stdio.h>
#include <stdbool.h> // bool, true, false
#include <stdlib.h> // srand(), rand()
#include <time.h> // time()
#include <ctype.h> // tolower()

#define LOSE_POINT 7

#define FIRST_ROLL_WIN(sum) ((sum) == 7 || (sum) == 11)
#define FIRST_ROLL_LOOSE(sum) ((sum) == 1 || (sum) == 2 || (sum) == 12)

int roll_dice( void )
{
// int a = (rand() % 6) + 1, b = (rand() % 6) + 1;
return ( 1 + rand() % 6 ) + ( 1 + rand() % 6 );
}

bool play_game( void )
{
int roll = 0, point, sum;

for (;;)
{
sum = roll_dice();
printf("You rolled: %d\n", sum);
roll++;

if ( roll != 1 ) {
if ( sum == point )
return true;
if ( sum == LOSE_POINT )
return false;
}

if ( FIRST_ROLL_WIN(sum) )
return true;
if ( FIRST_ROLL_LOOSE(sum) )
return false;

point = sum;
printf("Your point is %d.\n", point);
}
}

int main( void )
{
int wins = 0, losses = 0;
srand( (unsigned) time(NULL) );

for (;;)
{
bool play = play_game();
printf( "You %s!\n\n", play ? "win" : "loose" );

play ? wins++ : losses++;

printf("Play again? ");
if ( 'y' != tolower(getchar()) )
break;
getchar(); // catch '\n'
}
printf("Wins: %d Losses: %d\n", wins, losses);

return 0;
}
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό Ilias95 » 09 Μαρ 2012, 17:46

@migf1
Η λογική του προγράμματος που παρέθεσες δεν είναι σωστή.
Πχ. αν το roll έχει γίνει 4, το point είναι 6 και έρθει το sum 2 το δικό σου πρόγραμμα θα σταματήσει και θα πει στον παίκτη ότι έχασε, ενώ θα έπρεπε να συνεχίσει κανονικά.
Τα macros FIRST_ROLL_WIN και FIRST_ROLL_LOSS πρέπει να ελέγχονται μόνο όταν είμαστε στον πρώτο γύρο.

Επίσης μπερδεύτηκα στο macro FIRST_ROLL_LOSS. Πρέπει να γίνει:
Κώδικας: Επιλογή όλων
#define FIRST_ROLL_LOOSE(sum) ((sum) == 2 || (sum) == 3 || (sum) == 12)
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό Ilias95 » 09 Μαρ 2012, 17:50

migf1 έγραψε:Σε αυτό που συμφωνεί όμως η πλειοψηφία είναι πως μετά από return ή break μέσα σε if, το else αυτού του if είναι τελείως περιττό (και κάνει πιο δυσανάγνωστο τον κώδικα).

Επίσης εδώ πέρα δεν κατάλαβα ακριβώς τι εννοείς.
Αν θέλεις δώσε κάποιο παράδειγμα ανεξάρτητο της άσκησης.
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό migf1 » 09 Μαρ 2012, 18:08

Ilias95 έγραψε:@migf1
Η λογική του προγράμματος που παρέθεσες δεν είναι σωστή.
Πχ. αν το roll έχει γίνει 4, το point είναι 6 και έρθει το sum 2 το δικό σου πρόγραμμα θα σταματήσει και θα πει στον παίκτη ότι έχασε, ενώ θα έπρεπε να συνεχίσει κανονικά.
Τα macros FIRST_ROLL_WIN και FIRST_ROLL_LOSS πρέπει να ελέγχονται μόνο όταν είμαστε στον πρώτο γύρο.

Επίσης μπερδεύτηκα στο macro FIRST_ROLL_LOSS. Πρέπει να γίνει:
Κώδικας: Επιλογή όλων
#define FIRST_ROLL_LOOSE(sum) ((sum) == 2 || (sum) == 3 || (sum) == 12)

Βασικά δεν ασχολήθηκα καθόλου με την εκφώνηση (δεν τη διάβασα καν)... απλώς άλλαξα απευθείας τον κώδικα, οπότε είναι πολύ πιθανό κάτι να χάλασα :)

έγραψε:
Επίσης εδώ πέρα δεν κατάλαβα ακριβώς τι εννοείς.
Αν θέλεις δώσε κάποιο παράδειγμα ανεξάρτητο της άσκησης.

Π.χ....

Μορφοποιημένος Κώδικας: Επιλογή όλων
void printIfPositive( const int x )
{
if ( x < 0 )
return;

printf("%d", x);
return;
}

αντί για...

Μορφοποιημένος Κώδικας: Επιλογή όλων
void printIfPositive( const int x )
{
if ( x < 0 )
return;
else {
printf("%d", x);
return;
}
}


Δεν έχει νόημα το else μετά από if που κάνει return/break;
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό Ilias95 » 09 Μαρ 2012, 18:21

migf1 έγραψε:Δεν έχει νόημα το else μετά από if που κάνει return/break

Έχεις δίκιο.

Οπότε το:
Μορφοποιημένος Κώδικας: Επιλογή όλων
if (roll == 1) {
if (FIRST_ROLL_WIN(sum))
return true;
else if (FIRST_ROLL_LOOSE(sum))
return false;
else {
point = sum;
printf("Your point is %d.\n", point);
}
}
else {
if (sum == point)
return true;
if (sum == LOSE_POINT)
return false;
}

Θα γίνει:
Μορφοποιημένος Κώδικας: Επιλογή όλων
if (roll == 1) {
if (FIRST_ROLL_WIN(sum))
return true;
else if (FIRST_ROLL_LOOSE(sum))
return false;
point = sum;
printf("Your point is %d.\n", point);
}
else {
if (sum == point)
return true;
if (sum == LOSE_POINT)
return false;
}
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό migf1 » 09 Μαρ 2012, 18:27

Όχι ακριβώς, πάλι έχεις αφήσει else μετά το return, το συνηθισμένο στυλ είναι να γραφτεί έτσι...

Μορφοποιημένος Κώδικας: Επιλογή όλων
if (roll == 1) {
if (FIRST_ROLL_WIN(sum))
return true;
if (FIRST_ROLL_LOOSE(sum))
return false;
point = sum;
printf("Your point is %d.\n", point);
}
...
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό Ilias95 » 09 Μαρ 2012, 20:09

@migf1
Σωστά. Το είχα διορθώσει στο μυαλό μου, αλλά όχι στον κώδικα. :P

Star_Light έγραψε:
Ilias95 έγραψε:
Ναι έχεις δίκιο. Διαιρετέο εννοούσα, το διόρθωσα.
Αφού όμως είναι language και implementation dependent, ενδιαφέρον έχει να δούμε πως υπολογίζεται στα ίδια τα μαθηματικά. :)


http://en.wikipedia.org/wiki/Modular_arithmetic

Πιστευω την απάντηση θα την βρούμε στην Modular αριθμητική.

Το μονο μου προβλημα ειναι τα "αγγλικα" καθως σε αυτο το λημμα έχω αρκετες άγνωστες λέξεις.

Off topic:
Ρώτησα από περιέργεια τον καθηγητή μαθηματικών μου.

Λοιπόν, η ταυτότητα της ευκλείδειας διαίρεσης είναι: Δ = δ * π + υ
Το -9 μπορεί να γραφεί: -9 = 7 * (-1) - 2

Άρα στα μαθηματικά το υπόλοιπο της διαίρεσης -9 / 7 είναι -2.
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό Star_Light » 09 Μαρ 2012, 20:11

Ilias95 έγραψε:
Off topic:
Ρώτησα από περιέργεια τον καθηγητή μαθηματικών μου.

Λοιπόν, η ταυτότητα της ευκλείδειας διαίρεσης είναι: Δ = δ * π + υ
Το -9 μπορεί να γραφεί: -9 = 7 * (-1) - 2

Άρα στα μαθηματικά το υπόλοιπο της διαίρεσης -9 / 7 είναι -2.


yep :P και αν υ = 0 είναι τέλεια ενω με υ ! = 0 ατελής. Απλα το 5 με παραξένεψε προχθες που διάβαζα.
Άσχετο χθες διάβασα πως το ρολόι μας βασίζεται στην modular αριθμητικη και συγκεκριμενα στο modulo 12. :D

btw και στην C το ιδιο αποτέλεσμα δινει

Κώδικας: Επιλογή όλων

#include<stdio.h>
int main(void)
{
int x=-9 , y=7;

printf(" %d " , x % y);

return 0;
}
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό Star_Light » 09 Μαρ 2012, 20:52

Εν παση περιπτωση διαβασα στην αμεσως επομενη σελιδα οτι το αν θα δώσει -1 ή -2 το 9/7 ειναι θεμα πλατφορμας. Αν θυμαμαι καλα παντως απο τα καθαρα μαθηματικα το 9/7 θα δινει 1 λογω στρογγυλοποίησης. Νομιζω λεει πως πρεπει να τεκμηριωνεται κατι τετοιο στην C αν δεν εχεις αποφυγει να γράψεις Implementation-Defined κώδικα. ;) Oτα λεμε τεκμηριωση εννοουμε να το γραψει ο προγραμματιστης σαν σχολια ετσι?
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

ΠροηγούμενηΕπόμενο

Επιστροφή στο Ανάπτυξη Λογισμικού / Αλγόριθμοι