FubarPA,
You said a mouthful!
I taught my self to program in BASIC and severly embrased goto's, badly named variables, and general spaghetti string code. I learned enough Pascal to help someone else pass a college course and then on July 11th, 2002 - I found Perl. I have taken far too many things for granted and decided to teach myself C. This was so that I could better understand Perl internals and also make a meaningful contribution to Parrot.

What you see below is my attempt at porting one of my very first Perl programs to C.

animals.c #include <stdlib.h> #include <stdio.h> #include <string.h> #include <ctype.h> #include <_config.h> struct record { char vlevel[8]; char hlevel[8]; char type; char text[MAXTEXT]; }; FILE* Open_DB (char *argv[], char mode[1]) { FILE *file; file = fopen( argv[1] , mode ); if ( file == NULL ) { if ( argv[1] == NULL ) { file = fopen( "animals.db" , mode ); if ( file == NULL ) { printf("Unable to open default database\n"); exit (1); } } else { printf("Unable to open %s\n", argv[1]); exit (1); } } return (file); } void Build_DB ( FILE *db_file, struct record db[ MAXRECORDS ], int *to +tal_p, int *animals_p ) { char line[ LINELENGTH ], *token; short counter = 0; while ( ! feof( db_file ) ) { if ( (fgets( line, sizeof(line), db_file )) != NULL ) { /* Will crash a horrible and painful death if db file is c +orrupt */ token = strtok(line, SEPARATOR); strcpy( db[ counter ].vlevel, token ); token = strtok(NULL, SEPARATOR); strcpy( db[ counter ].hlevel, token ); token = strtok(NULL, SEPARATOR); db[ counter ].type = *token; if ( db[ counter ].type == 'G' ) { ++(*animals_p); } token = strtok(NULL, SEPARATOR); strcpy( db[ counter ].text, token ); token = strtok(NULL, SEPARATOR); } else { break; } ++counter; } fclose( db_file ); *total_p = counter - 1; } int DB_Lookup (int vlevel, int hlevel, struct record db[ MAXRECORDS ], + int total ) { int i; for (i = 0; i <= total; i++) { if ( atoi( db[ i ].vlevel ) != vlevel ) { continue; } if ( atoi( db[ i ].hlevel ) != hlevel ) { continue; } break; } if ( atoi( db[ i ].hlevel ) != hlevel ) { printf("Something went terribly wrong - end of databse\n"); exit (1); } return (i); } void Print_Intro (int animals) { char dummy; printf("Hello, my name is AI! I love animals and guessing games.\ +n"); printf("I have currently learned %d animals.\n\n", animals); printf("Please think of an animal and I will try to guess it\n"); printf("Press enter when ready\n"); scanf("%c", &dummy); } char Ask_Questions( struct record db[ MAXRECORDS ], int total ) { int current, vlevel = 1, hlevel = 1; char response[MAXTEXT]; current = DB_Lookup(vlevel, hlevel, db, total); while ( db[ current ].type == 'Q' ) { printf("%s", db[ current ].text); fgets(response, sizeof(response), stdin); if ( tolower( response[0] ) == 'y' ) { hlevel = hlevel * 2 - 1; } else { hlevel *= 2; } vlevel++; current = DB_Lookup(vlevel, hlevel, db, total); } return ( current ); } char Make_Guess( struct record db[ MAXRECORDS ], int guess ) { char response[MAXTEXT]; printf("Is the animal you are thinking of a(n) %s", db[ guess ].te +xt); fgets(response, sizeof(response), stdin); return ( tolower( response[0] ) ); } void Update_DB( struct record db[ MAXRECORDS ], int guess, int *total_ +p, int *animals_p ) { char new_question[ MAXTEXT ], new_animal[ MAXTEXT ], new_answer[ M +AXTEXT ]; printf("\n\nOk - I give up, what animal were you thinking of?\n"); fgets(new_animal, sizeof(new_animal), stdin); printf( "What y/n question, including the question mark would differen +tiate between a(n)\n\t%sand a(n)\n\t%s\n", new_animal, db[ guess ].text ); fgets(new_question, sizeof(new_question), stdin); printf("\nAnd what would the correct answer to that question for y +our animal be?\n"); fgets(new_answer, sizeof(new_answer), stdin); snprintf(db[ *total_p + 1 ].vlevel, 8, "%d", atoi(db[ guess ].vlev +el) + 1); snprintf(db[ *total_p + 2 ].vlevel, 8, "%d", atoi(db[ guess ].vlev +el) + 1); if ( tolower( new_answer[0] ) == 'y' ) { snprintf(db[ *total_p + 1 ].hlevel, 8, "%d", atoi(db[ guess ]. +hlevel) * 2 - 1); snprintf(db[ *total_p + 2 ].hlevel, 8, "%d", atoi(db[ guess ]. +hlevel) * 2); strcpy( db[ *total_p + 1 ].text, new_animal ); strcpy( db[ *total_p + 2 ].text, db[ guess ].text ); } else { snprintf(db[ *total_p + 1 ].hlevel, 8, "%d", atoi(db[ guess ]. +hlevel) * 2); snprintf(db[ *total_p + 2 ].hlevel, 8, "%d", atoi(db[ guess ]. +hlevel) * 2 - 1); strcpy( db[ *total_p + 1 ].text, db[ guess ].text ); strcpy( db[ *total_p + 2 ].text, new_animal ); } db[ *total_p + 1 ].type = 'G'; db[ *total_p + 2 ].type = 'G'; db[ guess ].type = 'Q'; strcpy( db[ guess ].text, new_question ); (*total_p) += 2; (*animals_p)++; } void Write_DB ( FILE *db_file, struct record db[ MAXRECORDS ], int tot +al ) { int i; for (i = 0; i <= total; i++) { fputs( strcat(db[ i ].vlevel, ":"), db_file); fputs( strcat(db[ i ].hlevel, ":"), db_file); fputs(db[ i ].type == 'G' ? "G:" : "Q:" , db_file); fputs(db[ i ].text, db_file); } fclose( db_file ); } int main (int argc, char *argv[]) { struct record db[ MAXRECORDS ]; FILE *db_file; int guess, total, *total_p = &total, animals, *animals_p = &animal +s; char response, answer[ MAXTEXT ] = "yes"; db_file = Open_DB( argv , "r" ); Build_DB( db_file, db, total_p, animals_p ); while ( tolower( answer[0] ) == 'y' ) { Print_Intro(animals); guess = Ask_Questions(db, total); response = Make_Guess(db, guess); if ( response == 'y' ) { printf("Yeah, I got it right\n"); } else { Update_DB(db, guess, total_p, animals_p); } printf("Would you like to play again?\n\n"); fgets(answer, sizeof(answer), stdin); } db_file = Open_DB( argv , "w" ); Write_DB( db_file, db, total ); return (0); } starter animals.db 1:1:Q:Does your animal live in the water? 2:1:Q:Is your animal a mammal? 2:2:Q:Can your animal fly? 3:1:Q:Does your animal get caught in tuna nets? 3:2:Q:Does your animal have tentacles? 3:3:Q:Is your animal nocturnal? 3:4:Q:Can your animal be domesticated as a house pet? 4:1:G:dolphin 4:2:G:whale 4:3:G:octapus 4:4:G:shark 4:5:G:bat 4:6:G:parrot 4:7:G:dog 4:8:G:lion sample _config.h #define MAXTEXT 256 /* Length of question or guess */ #define MAXRECORDS 4096 /* Includes questions and guesses */ #define SEPARATOR ":" /* Delimiter in DB */ #define LINELENGTH 260 /* MAXTEXT + length of 2 ints */

Cheers - L~R


In reply to Re: Perl: Quite a workhorse by Limbic~Region
in thread Perl: Quite a workhorse by FubarPA

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.