#include #include #include #include #include // Because forever { } looks wayyyy cooler than for(;;) { } #define forever for(;;) /* * By: Sir/Joe Gillotti * * Date: 11/27/2011 * * Purpose: Take 5 letters of inputted text * and convert them to really poorly drawn * ascii art, because I'm a terrible artist even when * literal drawing isn't involved. */ /* * Flow: * * 1) Ask user if they want to read their ten letters from a file or enter them in * 2) Ask user if they want to save the outputted ascii art to a file or just * print it out to screen * 3) Deal with the given letters according to the previous two points. */ // Store our string and output file handle here, so we can pass it between // functions possibly easier, and more importantly to demonstrate use of a struct struct values { char *string; FILE *outFile; }; // Print our letters, to the screen and optionally to a file void printLetters(struct values *state); // Get our letters, from the user or optionally from a file void getLetters(struct values *state); // Start us off by calling above functions and setting the ground int main () { // Our state struct struct values *state = (struct values*) malloc(sizeof(struct values)); // Did that fail? if (state == NULL) { printf("Couldn't allocate ram for our values struct..\n"); system("pause"); return 0; } // Room enough for 11 characters to print to screen or file state->string = (char*) malloc(sizeof(char)*11); // Did that fail? if (state->string == NULL) { printf("Couldn't allocate ram for our string..\n"); system("pause"); return 0; } // Get our letters! getLetters(state); // Print our letters in terribly drawn ascii art! printLetters(state); // Free that ram... free(state->string); // Close it if we need to if (state->outFile != NULL) fclose(state->outFile); // Free ram our pointer to struct took up free(state); // That's it! system("pause"); return 0; } // Get our letters! void getLetters(struct values *state) { // How we communicate with the user char resp = '\0'; int i; size_t len; // Ask as many times as we need to to get a proper answer while (resp != 'f' && resp != 'h') { printf( "Hai! Would you prefer to get the letters to turn into art\n" "from a file or enter them in here? type f for file or h for here.\n" "Your response: " ); scanf("%c", &resp); } // We may end up using this to read letters from a file FILE *inFile = NULL; // Name of it, if they feel like it char fileName[40] = {'\0'}; // A file to read from? if (resp == 'f') { forever { printf("\nOkay, type the name of the file you want to read from, up to 40 characters.. \nResponse: "); scanf("%s", fileName); if (strlen(fileName) == 0) { printf("You didn't give me a valid file name. I'm asking again, then.\n"); continue; } // Try opening it for reading.... if ((inFile = fopen(fileName, "r")) == NULL) { printf("That didn't work. I'm asking again until you can give me name of a valid file! :P\n"); continue; } // We got it! Try reading for at most the first 10 characters from the file. if (fread(state->string, sizeof(char), 11, inFile) == 0) { printf("I was unable to properly get some letters out of your file. \n I think I'll just restart this process..."); if (inFile != NULL) fclose(inFile); return getLetters(state); } // We probably have it open; close it if (inFile != NULL) fclose(inFile); // We received our letters. Stop asking for crap. break; } } // Or are we getting our letters directly from the user? else if (resp == 'h') { printf("\nOkay, please type at most 10 letters and I'll make them sexy for you!\n"); printf("Your response: "); scanf("%s", state->string); } // Length of our letters! len = strlen(state->string); // Validate whatever the user gave us, be it from a file or whatever. if (len == 0) { printf("The letters you gave me had no letters! I think I'll ask again...\n"); return getLetters(state); } // Make sure they're all actual letters! My font only has letters! for (i = 0; i < len; ++i) { // Firstly, it's probably a letter and if so make it lowercase state->string[i] = tolower(state->string[i]); // If we got some letters already and hit a snag like end of file or similar, just // stop there if (i > 0 && (int)state->string[i] < 28) { // Truncate string to this position state->string[i] = '\0'; // End break; } // Make sure we got letters regardless if ((int)state->string[i] < 97 || (int)state->string[i] > 122) { printf("Ugh, those letters you gave me had some none alphatebitc characters! I'ma ask again!\n\n\n"); return getLetters(state); } } resp = '\0'; // Looks like we have valid letters. Now let's determine if we should also write them to a file while (resp != 'y' && resp != 'n') { printf( "\nNow that I have your letters [%s] to output, would you also like me to write the ascii art to a file?\n" "y for yes; n or no; Your response: ", state->string ); scanf(" %c", &resp); } // Looks like we want to write them to a file too. Ask for filename... if (resp == 'y') { printf( "\nOkay, apparently you'd like me to write the ascii art to a file too. \n" "File name? " ); scanf("%s", fileName); // Try opening that state->outFile = fopen(fileName, "w"); // Yeah? if (state->outFile == NULL) printf("I couldn't open your file. Oh, well. Printing to screen only it is!"); else printf("\nWriting art to [%s] as well as screen!", fileName); } } // Pint out the letters, to the screen and possibly also outFile. void printLetters(struct values *state) { // Our terribly drawn, sloppy ascii art letters. Each is composed // of up to 5 lines of text, hence this 26 size array of 5 character // arrays. char *letters[26][5] = { // A { " / \\", " /---\\", "/ \\" }, // B { "|===)", "|=|", "|===)" }, // C { "/----", "|", "\\----" }, // D { "|--\\", "| )", "|--/" }, // E { "|====]", "|[", "|====]" }, // F { "|===]", "|", "|===]", "|", "|" }, // G { "------\\", "|", "| ---/", "| /", "|---/" }, // H { "|| ||", "||==||", "|| ||" }, // I { "======", " ||", " ||", "======", }, // J { "======", " ||", " ||", "==//", }, // k { "| /", "|/", "|\\", "| \\" }, // L { "|", "|", "|", "|----" }, // A ridiculously sloppy 'M' { " /\\ /\\", " / \\ / \\ ", "/ \\ / \\", " / \\" }, // N { "|\\ |", "| \\ |", "| \\ |", "| \\|" }, // A rather boxy 'O' indeed { "|=====|", "| |", "| |", "|=====|" }, // P { "|--\\", "| |", "|--/", "|", "|" }, // Q { "/----\\", "|| ||", "|| ||", "/----/", " \\" }, // R { "|-----\\", "| |", "|-----/", "| \\", "| \\" }, // S { "/-----", "\\", " \\", " \\", "------/" }, // T { "======", " ||", " ||", " ||" }, // U { "| |", "| |", "| |", "\\----/", }, // V { "\\ /", " \\ /", " \\-/" }, // W, essentially the V duplicated { "\\ /\\ /", " \\ / \\ /", " \\-/ \\-/" }, // X { "\\ /", " \\ /", " / \\ ", "/ \\", }, // Y { "\\ /", " \\ /", " \\ /", " |", }, // Z { "=====", " /", " /", " /", "=====" } }; // A little message printf("\n\nYour letters (%s) in asci art:\n\n", state->string); // Some things we use to iterate with unsigned short int i, j; size_t len; // Temp placeholder for the current line char *letterRow; // Each of the 3 rows for the letters... for (j = 0; j < 5; ++j) { // Each letter's row for this position for (i = 0, len = strlen(state->string); i < len; i++) { letterRow = letters[(int)state->string[i]-97][j]; // Certain letters are wider than others and thus need to be // padded differently switch ((char)state->string[i]) { // Wider letters case 'm': case 'w': printf("%-17s", letterRow != NULL ? letterRow : ""); if (state->outFile != NULL) fprintf(state->outFile, "%-17s", letterRow != NULL ? letterRow : ""); break; // Usual possibly skinny letters default: printf("%-8s", letterRow != NULL ? letterRow : ""); if (state->outFile != NULL) fprintf(state->outFile, "%-8s", letterRow != NULL ? letterRow : ""); break; } } // New line at the end of each row printf("\n"); if (state->outFile != NULL) fprintf(state->outFile, "\n"); } }