Funzione con bug e funzione senza

di il
9 risposte

Funzione con bug e funzione senza

Salve, spero qualcuno sia in grado (o almeno abbia la voglia) di aiutarmi : all'interno dell'algoritmo di un esercizio ho creato questa funzione, che purtroppo non funziona come dovrebbe. Ho guardato allora la soluzione che, sebbene abbia qualche dettaglio differente dalla mia, mi sembra equivalente nel contenuto, eppure la mia non è corretta, l'altra si. Scovare i bug mi è veramente difficile!!

Questa è la mia:

#include <stdbool.h>   /* solo C99 */
#include <stdio.h>
#include <stdlib.h>

#define NUM_RANKS 13
#define NUM_SUITS 4
#define NUM_CARDS 5
#define NUM_INFO  2

/* external variables */
int card[NUM_CARDS][NUM_INFO];
bool straight, flush, four, three;
int pairs;   /* can be 0, 1, or 2 */

/* Funzione */
void read_cards(void)
{
  char ch, rank_ch, suit_ch;
  int rank, suit, card_num, card_type;
  bool bad_card;
  int cards_read = 0;

  for (card_num = 0; card_num < NUM_CARDS; card_num++) {
    for (card_type = 0; card_type < NUM_INFO; card_type++)
      card[card_num][card_type] = 0;
  }

  while (cards_read < NUM_CARDS) {
    bad_card = false;

    printf("Enter a card: ");

    rank_ch = getchar();
    switch (rank_ch) {
      case '0':           exit(EXIT_SUCCESS);
      case '2':           rank = 0; break;
      case '3':           rank = 1; break;
      case '4':           rank = 2; break;
      case '5':           rank = 3; break;
      case '6':           rank = 4; break;
      case '7':           rank = 5; break;
      case '8':           rank = 6; break;
      case '9':           rank = 7; break;
      case 't': case 'T': rank = 8; break;
      case 'j': case 'J': rank = 9; break;
      case 'q': case 'Q': rank = 10; break;
      case 'k': case 'K': rank = 11; break;
      case 'a': case 'A': rank = 12; break;
      default:            bad_card = true;
    }

    suit_ch = getchar();
    switch (suit_ch) {
      case 'c': case 'C': suit = 0; break;
      case 'd': case 'D': suit = 1; break;
      case 'h': case 'H': suit = 2; break;
      case 's': case 'S': suit = 3; break;
      default:            bad_card = true;
    }

    while ((ch = getchar()) != '\n')
      if (ch != ' ') bad_card = true;

    if (bad_card) {
      printf("Bad card; ignored.\n");
    } else if (cards_read == 0) {
      card[cards_read][0] = rank;
      card[cards_read][1] = suit;
      cards_read++;
    } else {
      for (int i = 0; i < cards_read; i++) {
        if ( (card[i][0]) == rank && (card[i][1]) == suit ) {
          printf("Duplicate card; ignored.\n");
          break;
        } else if (i == (cards_read - 1)) {
          card[cards_read][0] = rank;
          card[cards_read][1] = suit;
          cards_read++;
        }
      }
    }
 }
}
Questa è la soluzione corretta, che a me sembra equivalente, ma evidentemente non lo è:

#include <stdbool.h>   /* C99 only */
#include <stdio.h>
#include <stdlib.h>

#define NUM_CARDS 5
#define RANK 0
#define SUIT 1

/* external variables */
int hand[NUM_CARDS][2];
bool straight, flush, four, three;
int pairs;   /* can be 0, 1, or 2 */

*/ Funzione */
void read_cards(void)
{
  char ch, rank_ch, suit_ch;
  int i, rank, suit;
  bool bad_card, duplicate_card;
  int cards_read = 0;

  while (cards_read < NUM_CARDS) {
    bad_card = false;

    printf("Enter a card: ");

    rank_ch = getchar();
    switch (rank_ch) {
      case '0':           exit(EXIT_SUCCESS);
      case '2':           rank = 0; break;
      case '3':           rank = 1; break;
      case '4':           rank = 2; break;
      case '5':           rank = 3; break;
      case '6':           rank = 4; break;
      case '7':           rank = 5; break;
      case '8':           rank = 6; break;
      case '9':           rank = 7; break;
      case 't': case 'T': rank = 8; break;
      case 'j': case 'J': rank = 9; break;
      case 'q': case 'Q': rank = 10; break;
      case 'k': case 'K': rank = 11; break;
      case 'a': case 'A': rank = 12; break;
      default:            bad_card = true;
    }

    suit_ch = getchar();
    switch (suit_ch) {
      case 'c': case 'C': suit = 0; break;
      case 'd': case 'D': suit = 1; break;
      case 'h': case 'H': suit = 2; break;
      case 's': case 'S': suit = 3; break;
      default:            bad_card = true;
    }

    while ((ch = getchar()) != '\n')
      if (ch != ' ') bad_card = true;

    if (bad_card) {
      printf("Bad card; ignored.\n");
      continue;
    }

    duplicate_card = false;
    for (i = 0; i < cards_read; i++)
      if (hand[i][RANK] == rank && hand[i][SUIT] == suit) {
        printf("Duplicate card; ignored.\n");
        duplicate_card = true;
        break;
      }

    if (!duplicate_card) {
      hand[cards_read][RANK] = rank;
      hand[cards_read][SUIT] = suit;
      cards_read++;
    }
  }
}

9 Risposte

  • Re: Funzione con bug e funzione senza

    Magari se spieghi cosa vuol dire "non funziona come dovrebbe": dovresti specificare i dati in input e cosa ottieni in output e quello che invece ti saresti aspettato. Dare due pezzi di codice così non è di nessun aiuto!
  • Re: Funzione con bug e funzione senza

    Ok allora scrivo l'intero esercizio con l'algoritmo e inserisco più dettagli. Pensavo che inserire solo il pezzo interessato fosse meglio ma mi sbagliavo

    Intanto grazie per l'interessamento.
  • Re: Funzione con bug e funzione senza

    In pratica l'esercizio chiede di modificare un programma (inserito di seguito), che prende in input 5 carte (i valori sono 2 3 4 5 6 7 8 9 t j q k a mentre i semi sono c d h s) e calcola il valore in base ai punti del poker.
    La modifica da effettuare è rimuovere i vettori num_in_rank, num_in_suit e card_exists dal programma originale e salvare le carte in un vettore 5x2 (ogni riga contiene il valore nella colonna 0 e il seme nella colonna 1). Il programma originale è questo:
    
    /*********************************************************
     * From C PROGRAMMING: A MODERN APPROACH, Second Edition *
     * By K. N. King                                         *
     * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. *
     * All rights reserved.                                  *
     * This program may be freely distributed for class use, *
     * provided that this copyright notice is retained.      *
     *********************************************************/
    
    /* poker.c (Capitolo 10, pag. 244) */
    /* Classifica una mano di poker */
    
    #include <stdbool.h>   /* solo C99 */
    #include <stdio.h>
    #include <stdlib.h>
    
    #define NUM_RANKS 13
    #define NUM_SUITS 4
    #define NUM_CARDS 5
    
    /* external variables */
    int num_in_rank[NUM_RANKS];
    int num_in_suit[NUM_SUITS];
    bool straight, flush, four, three;
    int pairs;   /* can be 0, 1, or 2 */
    
    /* prototypes */
    void read_cards(void);
    void analyze_hand(void);
    void print_result(void);
    
    /**********************************************************
     * main: Chiama ripetutamente read_cards, analyze_hand    *
     *       e print_result                                   *
     **********************************************************/
    int main(void)
    {
      for (;;) {
        read_cards();
        analyze_hand();
        print_result();
      }
    }
    
    /***********************************************************
     * read_cards: Salva le carte lette nelle varibili esterne *
     *             num_in_rank e num_in_suit. Esegue il        *
     *             controllo per le carte errate               *
     *             e per quelle duplicate.                     *
     ***********************************************************/
    void read_cards(void)
    {
      bool card_exists[NUM_RANKS][NUM_SUITS];
      char ch, rank_ch, suit_ch;
      int rank, suit;
      bool bad_card;
      int cards_read = 0;
    
      for (rank = 0; rank < NUM_RANKS; rank++) {
        num_in_rank[rank] = 0;
        for (suit = 0; suit < NUM_SUITS; suit++)
          card_exists[rank][suit] = false;
      }
    
      for (suit = 0; suit < NUM_SUITS; suit++)
        num_in_suit[suit] = 0;
    
      while (cards_read < NUM_CARDS) {
        bad_card = false;
    
        printf("Enter a card: ");
    
        rank_ch = getchar();
        switch (rank_ch) {
          case '0':           exit(EXIT_SUCCESS);
          case '2':           rank = 0; break;
          case '3':           rank = 1; break;
          case '4':           rank = 2; break;
          case '5':           rank = 3; break;
          case '6':           rank = 4; break;
          case '7':           rank = 5; break;
          case '8':           rank = 6; break;
          case '9':           rank = 7; break;
          case 't': case 'T': rank = 8; break;
          case 'j': case 'J': rank = 9; break;
          case 'q': case 'Q': rank = 10; break;
          case 'k': case 'K': rank = 11; break;
          case 'a': case 'A': rank = 12; break;
          default:            bad_card = true;
        }
    
        suit_ch = getchar();
        switch (suit_ch) {
          case 'c': case 'C': suit = 0; break;
          case 'd': case 'D': suit = 1; break;
          case 'h': case 'H': suit = 2; break;
          case 's': case 'S': suit = 3; break;
          default:            bad_card = true;
        }
    
        while ((ch = getchar()) != '\n')
          if (ch != ' ') bad_card = true;
    
        if (bad_card)
          printf("Bad card; ignored.\n");
        else if (card_exists[rank][suit])
          printf("Duplicate card; ignored.\n");
        else {
          num_in_rank[rank]++;
          num_in_suit[suit]++;
          card_exists[rank][suit] = true;
          cards_read++;
        }
      }
    }
    
    /**************************************************************
     * analyze_hand: Determina se la mano contiene una scala,     *
     *               un colore, un poker e/o un tris; determina   *
     *               il numero delle coppie e salva il risultato  *
     *               all'interno nelle variabili esterne straight *
     *               flush, four, three e pairs.                  *
     **************************************************************/
    void analyze_hand(void)
    {
      int num_consec = 0;
      int rank, suit;
    
      straight = false;
      flush = false;
      four = false;
      three = false;
      pairs = 0;
    
      /* check for flush */
      for (suit = 0; suit < NUM_SUITS; suit++)
        if (num_in_suit[suit] == NUM_CARDS)
          flush = true;
    
      /* check for straight */
      rank = 0;
      while (num_in_rank[rank] == 0) rank++;
      for (; rank < NUM_RANKS && num_in_rank[rank] > 0; rank++)
        num_consec++;
      if (num_consec == NUM_CARDS) {
        straight = true;
        return;
      }
    
      /* check for 4-of-a-kind, 3-of-a-kind, and pairs */
      for (rank = 0; rank < NUM_RANKS; rank++) {
        if (num_in_rank[rank] == 4) four = true;
        if (num_in_rank[rank] == 3) three = true;
        if (num_in_rank[rank] == 2) pairs++;
      }
    }
    
    /**********************************************************
     * print_result: Stampa la classificazione della mano     *
     *               basandosi sui valori delle variabili     *
     *               esterne straight, flush, four, three,    *
     *               e pairs.                                 *
     **********************************************************/
    void print_result(void)
    {
      if (straight && flush) printf("Straight flush");
      else if (four)         printf("Four of a kind");
      else if (three &&
               pairs == 1)   printf("Full house");
      else if (flush)        printf("Flush");
      else if (straight)     printf("Straight");
      else if (three)        printf("Three of a kind");
      else if (pairs == 2)   printf("Two pairs");
      else if (pairs == 1)   printf("Pair");
      else                   printf("High card");
    
      printf("\n\n");
    }
    
    La mia modifica mi dà i risultati corretti...per la verità ho provato solo alcuni valori in quanto mi compare un bug (che non intacca il funzionamento del resto del programma).
    Il bug credo appartenga alla funzione read_cards(). Quando inserisco le carte, a partire dalla seconda, mi compare la scritta "Duplicate card; ignored." che dovrebbe comparire solo se viene inserita una carta già inserita in precedenza. La cosa strana è che la chiamata a quella printf è seguita dall'istruzione break che esclude che la carta duplicata venga salvata, quindi la condizione che permette la chiamata alla printf (stampando il messaggio di carta duplicata) dovrebbe chiamare anche l'istruzione di break interrompendo il salvataggio della carta... ma ciò non avviene! In pratica se la carta non è un doppione, mi compare il messaggio (che non dovrebbe comparire) ma effettivamente non salva la carta (e qui fa la cosa corretta permettendo al programma di proseguire); nel caso in cui si inserisce un doppione fa quello che dovrebbe fare.

    Il codice del mio programma è questo:
    
    /*********************************************************
     * From C PROGRAMMING: A MODERN APPROACH, Second Edition *
     * By K. N. King                                         *
     * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. *
     * All rights reserved.                                  *
     *********************************************************/
    
    /* Progetto di programmazione 3 */
    /* Classifica una mano di poker */
    
    #include <stdbool.h>   /* solo C99 */
    #include <stdio.h>
    #include <stdlib.h>
    
    #define NUM_RANKS 13
    #define NUM_SUITS 4
    #define NUM_CARDS 5
    #define NUM_INFO  2
    
    /* external variables */
    int card[NUM_CARDS][NUM_INFO];
    bool straight, flush, four, three;
    int pairs;   /* can be 0, 1, or 2 */
    
    /* prototypes */
    void read_cards(void);
    void analyze_hand(void);
    void print_result(void);
    
    /**********************************************************
     * main: Chiama ripetutamente read_cards, analyze_hand    *
     *       e print_result                                   *
     **********************************************************/
    int main(void)
    {
      for (;;) {
        read_cards();
        analyze_hand();
        print_result();
      }
    }
    
    /***********************************************************
     * read_cards: Salva le carte lette nelle varibili esterne *
     *             num_in_rank e num_in_suit. Esegue il        *
     *             controllo per le carte errate               *
     *             e per quelle duplicate.                     *
     ***********************************************************/
    void read_cards(void)
    {
      char ch, rank_ch, suit_ch;
      int rank, suit, card_num, card_type;
      bool bad_card;
      int cards_read = 0;
    
      for (card_num = 0; card_num < NUM_CARDS; card_num++) {
        for (card_type = 0; card_type < NUM_INFO; card_type++)
          card[card_num][card_type] = 0;
      }
    
      while (cards_read < NUM_CARDS) {
        bad_card = false;
    
        printf("Enter a card: ");
    
        rank_ch = getchar();
        switch (rank_ch) {
          case '0':           exit(EXIT_SUCCESS);
          case '2':           rank = 0; break;
          case '3':           rank = 1; break;
          case '4':           rank = 2; break;
          case '5':           rank = 3; break;
          case '6':           rank = 4; break;
          case '7':           rank = 5; break;
          case '8':           rank = 6; break;
          case '9':           rank = 7; break;
          case 't': case 'T': rank = 8; break;
          case 'j': case 'J': rank = 9; break;
          case 'q': case 'Q': rank = 10; break;
          case 'k': case 'K': rank = 11; break;
          case 'a': case 'A': rank = 12; break;
          default:            bad_card = true;
        }
    
        suit_ch = getchar();
        switch (suit_ch) {
          case 'c': case 'C': suit = 0; break;
          case 'd': case 'D': suit = 1; break;
          case 'h': case 'H': suit = 2; break;
          case 's': case 'S': suit = 3; break;
          default:            bad_card = true;
        }
    
        while ((ch = getchar()) != '\n')
          if (ch != ' ') bad_card = true;
    
        if (bad_card) {
          printf("Bad card; ignored.\n");
        } else if (cards_read == 0) {
          card[cards_read][0] = rank;
          card[cards_read][1] = suit;
          cards_read++;
        } else {
          for (int i = 0; i < cards_read; i++) {
            if ( (card[i][0]) == rank && (card[i][1]) == suit ) {
              printf("Duplicate card;ignored\n");
              break;
            } else if (i == (cards_read - 1)) {
              card[cards_read][0] = rank;
              card[cards_read][1] = suit;
              cards_read++;
            }
          }
        }
      }
    }
    /**************************************************************
     * analyze_hand: Determina se la mano contiene una scala,     *
     *               un colore, un poker e/o un tris; determina   *
     *               il numero delle coppie e salva il risultato  *
     *               all'interno nelle variabili esterne straight *
     *               flush, four, three e pairs.                  *
     **************************************************************/
    void analyze_hand(void)
    {
      straight = true;
      flush = true;
      four = false;
      three = false;
      pairs = 0;
    
      /* check for flush */
      for (int i = 0; i < NUM_CARDS; i++) {
        if (card[i][1] != card[0][1]) {
          flush = false;
          break;
        }
      }
    
      /* ordina le carte dalla più piccola alla più grande */
      int r = NUM_CARDS;
      while (r > 0) {
        for (int i = 0; i < (r - 1); i++) {
          if (card[i][0] > card[i+1][0]) {
            int temp;
            temp = card[i][0];
            card[i][0] = card[i+1][0];
            card[i+1][0] = temp;
            temp = card[i][1];
            card[i][1] = card[i+1][1];
            card[i+1][1] = temp;
          }
        }
      r -= 1;
      }
    
      /* controlla coppie, tris e poker */
      int cont = 0;
      for (int i = 1; i < NUM_CARDS; i++) {
        if (card[i-1][0] == card[i][0]) {
          cont += 1;
          pairs += 1;
        } else {
          cont = 0;
        }
        if (cont == 2) {
          three = true;
          pairs -= 2;
        } else if (cont == 3) {
          pairs -= 1;
          three = false;
          four = true;
        }
      }
    
      /* controlla se c'è una scala */
      for (int i = 1; i < NUM_CARDS; i++) {
        if ((card[i][0] - card[i-1][0]) != 1) {
          straight = false;
          return;
        }
      }
    }
    
    /**********************************************************
     * print_result: Stampa la classificazione della mano     *
     *               basandosi sui valori delle variabili     *
     *               esterne straight, flush, four, three,    *
     *               e pairs.                                 *
     **********************************************************/
    void print_result(void)
    {
      if (straight && flush) printf("Straight flush");
      else if (four)         printf("Four of a kind");
      else if (three &&
               pairs == 1)   printf("Full house");
      else if (flush)        printf("Flush");
      else if (straight)     printf("Straight");
      else if (three)        printf("Three of a kind");
      else if (pairs == 2)   printf("Two pairs");
      else if (pairs == 1)   printf("Pair");
      else                   printf("High card");
    
      printf("\n\n");
    }
    
    Quindi il risultato è corretto ma mi stampa quei messaggi che non capisco da dove escono.

    Il pezzo di codice che contiene l'istruzione di stampa è:
    
    for (int i = 0; i < cards_read; i++) {
            if ( (card[i][0]) == rank && (card[i][1]) == suit ) {
              printf("Duplicate card; ignored.\n");
              break;
            } else if (i == (cards_read - 1)) {
              card[cards_read][0] = rank;
              card[cards_read][1] = suit;
              cards_read++;
            }
          }
    
    A me sembra che dovrebbe accedere alla printf all'istruzione break contemporaneamente, senza possibilità che acceda al break senza passare per la printf o viceversa.

    Edit: aggiungo che mi sono reso conto che c'è un bug anche nel conteggio di coppie, tris, e poker, al quale devo dare un'occhiata
  • Re: Funzione con bug e funzione senza

    Aggiornamento: il presunto bug della parte che trovava coppie, tris e poker in pratica non esisteva, cioè il codice era scritto bene, ma era come se non venisse letta quella porzione di file (mah), ho semplicemente spostato quel pezzo in un altro punto e magicamente il bug era scomparso.

    Rimane però il problema iniziale: come fa il programma a chiamare la printf in quel punto?
    Se vi fa piacere potete cercare di risolvere questo bug. Io ci rinuncio.
  • Re: Funzione con bug e funzione senza

    Da una rapida lettura del codice è immediatamente evidente (in mezzo a molto altro) la presenza di una bomba logica innescata.
    
          for (int i = 0; i < cards_read; i++) {
            if ( (card[i][0]) == rank && (card[i][1]) == suit ) {
              printf("Duplicate card;ignored\n");
              break;
            } else if (i == (cards_read - 1)) {
              card[cards_read][0] = rank;
              card[cards_read][1] = suit;
              cards_read++;
            }
          }
    
    Stai modificando nella for() il valore della variabile usata nella condizione di permanenza (i < cards_read). In tale modo, quando si verifica la condizione if (i == (cards_read - 1)) la carta viene regolarmente aggiunta con i valori correnti di rank e suit. Ma viene modificato anche il valore di cards_read senza forzare l'uscita dal loop, il che causa l'esecuzione di una iterazione non necessaria in più, durante la quale sostanzialmente i valori della carta appena immessa vengono confrontati con se stessi ossia con le variabili rank e suit appena assegnate, provocando un falso positivo.
    Questa è ovviamente una recipe for disaster.
    Se vuoi davvero usare quell'idioma, dovresti assolutamente aggiungere una break nel ramo else, ovviamente dopo l'istruzione cards_read++. Ma in realtà, il ramo else non ha alcun senso scritto in tal modo. La for() deve scorrere linearmente tutte le carte e impostare semplicemente un flag booleano se la carta è già presente: il flag verrà poi controllato a valle, in una if() separata, in modo tale da evitare l'inserimento se non necessario.

    Vi sarebbe poi molto da discutere sulla validità dell'impianto didattico di codesto codice, sull'uso delle switch per la codifica della carta, sulla codifica stessa (si veda per curiosità questo post), sulle bizzarre scelte di refactoring imposte dall'esercizio... e più in generale sulla qualità del testo di King che fa ottima compagnia ai vari pessimi Deitel, Malik, Schildt. Per il momento stendiamo un pietoso velo, per carità di Patria.
  • Re: Funzione con bug e funzione senza

    Ciao M.A.W..

    Intanto ti ringrazio per la risposta. Mi credi che partendo dalla convinzione che quell'"else if" fosse l'ultimo accesso al ciclo non mi ero reso minimamente conto che stavo modificando la condizione di partenza XD ? Mi ha tratto in inganno il fatto che inizialmente avevo previsto un impostazione con l'incremento della cards_read fuori dal ciclo e quando poi l'ho messa lì dentro la convinzione che il ciclo terminasse in quel punto non mi ha fatto rendere conto dell'errore. Errore da principiante come del resto sono.

    Non è che volessi usare per forza quell'idioma, avevo risolto anche con l'uso di una variabile booleana come hai suggerito (e come suggerisce la soluzione fornita dall'autore), ma visto che mi interessa imparare, vorrei capire gli errori, soprattutto perchè personalmente mi è MOLTO più difficile individuare un errore che creare un'impostazione alternativa e (potrei sbagliarmi) credo sia anche utile che io impari ad individuarli stando attento ai dettagli. Magari sono pippe mentali, non lo so (me lo puoi dire tu che sei più esperto di me). Era più che altro per esercitarmi con strade diverse e stare attento ai dettagli.

    Comunque al di là della questione del post, se mi è permesso, vorrei riprendere il tuo piccolo OT che ora mi interessa molto di più del messaggio iniziale. Premetto che, incuriosito dalla tua risposta, ho cercato un po' nel forum, ho trovato anche un tuo messaggio in cui consigliavi la lettura di questo "articolo" sulla didattica http://www.ioprogrammo.it/index.php?topic=14799. ma in ogni caso più che chiarirmi le idee mi sorgono ulteriori domande (relative al mio caso specifico).

    Se ho capito bene trovandoti d'accordo con quell'articolo, dovendo iniziare mi consiglieresti di studiare direttamente il C++ con i testi consigliati lì. Qui però mi viene da farmi qualche problema, visto che mi trovo già ad un terzo del libro di King.
    Il fatto è questo: essendo meticoloso prima di mettermi a studiare ho cercato di farmi un'idea su quale fosse l'opzione migliore per iniziare, ma credimi che questo consiglio mi era sfuggito, avevo letto discussioni infinite sul tema "C vs C++ per iniziare" (non ero iscritto a nessun forum quindi si trattava di informazioni trovate cercando su google), alla fine ho concluso che se anche avessi voluto studiare entrambi contasse poco la scelta, ma comunque per prendere una decisione e tagliare la testa al toro ho preso in mano il piano di studi di informatica dell'università della mia città e ho visto come era impostato. Da qui la scelta di studiare il C (e il libro di King è il libro usato al primo corso di programmazione), scelta che non mi sembrava malvagia volendo studiare il C a scopo didattico e poi passare alla programmazione orientata agli oggetti con Java... insomma mi sembrava una scelta condivisibile (da profano).

    A questo punto per me è controproducente lasciare a metà quello che ho iniziato e passare all'altro approccio (se il motivo per cui sconsigliavi l'uso del testo di King è "quale dei due linguaggi vada studiato per primo", s'intende), se però mi dici che volendo proprio studiare il C, il testo di King è comunque una delle scelte peggiori e che ci sono testi migliori, potrei magari valutare l'idea di passare ad un altro testo, se questo non mi richiede degli sforzi enormi.

    Da qui la domanda, volendo proseguire lo studio del C, mi consigli di passare ad un altro testo o secondo te l'uno vale l'altro e continuo con il King? Almeno per sapere la tua opinione.

    PS: ti sto dando con disinvolutura del tu data la natura generalmente informale dei forum, spero di non fare cosa sgradita!
    PPS: sulle scelte di refactoring credo l'intento sia puramente quello di esercitarsi con determinate conoscenze riguardo la sintassi facenti parte del capitolo al quale fa riferimento l'esercizio. In effetti, didatticamente parlando, credo che un esercizio pratico debba tenere in considerazione il "buon uso" (inteso come stile) della sintassi, ma riguardo a questo non posso far altro che affidarmi al testo che seguo dando per scontato che ci pensi "lui" ad insegnarmelo.
  • Re: Funzione con bug e funzione senza

    Per l'apprendimento del linguaggio C (ben diverso da C++), la bibliografia di riferimento convalidata da decenni di insegnamento a studenti laureati e post-doctoral è questa.

    Personalmente suggerisco di accantonare il King, in altri forum ho un numero preoccupante di studenti e autodidatti che continuano a porre domande sconsolanti ed a commettere errori di codifica, stile ed engineering per il fatto di studiare su tale testo. Sicuramente è vero che si diventa "esperti" commettendo almeno una volta tutti gli errori possibili, ma certi esercizi appartengono di diritto alla sfera delle pratiche masochistiche che difficlmente riescono nell'intento di una crescita del discente.

    Riguardo ai motivi per cui tutti si danno del tu su internet, puoi leggere questo.
  • Re: Funzione con bug e funzione senza

    Per il C la risposta non è difficile, ed è K&R, più che sufficiente in praticamente tutti i casi, dal livello base a intermedio.

    Quando si raggiunge il livello intermedio (che è già equivalente a livello "divino", per la media di oggi di università & forum, TRANNE certi forum specialistici, anche mooooolto specialistici,), a mio parere, i testi iniziano ad essere poco utili a favore dell' "olio di gomito" (di meninge).
  • Re: Funzione con bug e funzione senza

    Ringrazio entrambi per i consigli.
    Stavo proprio leggendo quella bibliografia che avevo trovato dopo averti riempito di domande .

    Assodato che [u]il K&R lo devo avere[/u] e che il King fa schifo, documentandomi sui libri di quella bibliografia, vedo che il Kelley & Pohl, "C - Didattica e programmazione" ha un approcio simile al King (nel senso che si tratta di una guida didattica), mi consigliate di studiare direttamente prima sul K&R oppure usare di pari passo il Kelley? Chiedo conferma perchè capii inizialmente (basandomi su recensioni ecc.) che il K&R non andava bene come primo approccio, in quanto da considerarsi un manuale di puro riferimento (per tutti i livelli) e non un corso/guida di programmazione in C per chi inizia.
Devi accedere o registrarti per scrivere nel forum
9 risposte