It is my firm belief that success correlates with strong internal motivation. What does that mean in this instance? My reason in opting for this independent study was to see if I'm capable of grasping these fundamental concepts with my own devices. I've been extremely pleased with the results.
Over the last three months, I've explored various concepts of C programming. In my studies I explored syntactical structures, various logical operations, and principals that make up a C program. The following projects demonstrate what I've explored.
I've developed two projects that solve simplex problems in a very fun way. The first is a drinking game called “Power Hour” that works with loop incrementing that adds up to one hour. The loop wait 60 seconds using the sleep function via time.h:
#include <stdio.h> #include <time.h> int main() { printf("Begin power hour!\n\a"); int minute; for(minute = 0; minute <= 60; ++minute) { printf("Minute Number: %d\n",minute); sleep(60); printf("Drink!\n\a"); } printf("Congratulations, you've survived power hour!"); return 0; }
The second fun project involves using a raspberry pi's General Purpose I/O to connect to solid state relay switch that powers a coffee machine. I call it “Lair Brew.” The program makes heavy use of a library that gives the Pi Arduinio like I/O functions:
/* Lair_Brew ~ Caffeine ~ Version 0.2 */ #include <wiringPi.h> #include <stdio.h> void loopback(void) { char ch; ch = getchar(); while( ch != '\n' ) ch = getchar(); } int main (void) { int pin = 7; char ch; int exit_flag = 0; printf("welcome to Lair Brew\n"); if (wiringPiSetup() == -1) return(1); pinMode(pin, OUTPUT); printf("Brew on\n"); digitalWrite(pin, 1); while( exit_flag == 0 ) { printf("Wish to exit? (Y)\n"); scanf(" %c", &ch ); ch = toupper( ch ); if((ch == 'Y')){ printf("\nBrew Off\n"); digitalWrite(pin, 0); delay(250); printf("\nEnjoy Your Coffee, Sir!\n"); } else { printf("\nType (y) to exit.\n"); loopback(); } if( ch == 'Y' ) exit_flag = 1; } return 0; }
Playing with simple structs:
#include <stdio.h> #include <string.h> typedef struct { int a; int b; int c; char abc[]; }node; int main() { node n; n.a = 1; n.b = 2; n.c = 3; strcpy(n.abc, "abc"); printf("Now I know my %s's, they are easy as %d, %d, %d\n", n.abc, n.a, n.b, n.c); return 0; }
The following projects were assigned by Matt in chronological order.
This project went over different data types and the storage capabilities of those types.
The following code demonstrates the storage range of a signed and unsigned char:
/* * range.c - A program to display information for signed and unsigned data types * * * Compile with: gcc -o range range.c -lm * Execute with: ./range */ #include <stdio.h> #include <math.h> int main() { // Variables unsigned long long int quantity = 0; unsigned char uc = 0; signed char sc = 0; // Display information for unsigned char data type printf("An unsigned char is %d bytes\n", sizeof(uc)); printf("The range of an unsigned char is %hhu to %hhu\n", uc, (uc-1)); quantity = (unsigned char)(uc-1) + 1; // What does this line do? printf("An unsigned char can store %llu unique values\n\n", quantity); // Display information for signed char data type printf("A signed char is %d bytes\n", sizeof(sc)); quantity = (unsigned long long int)pow(2, (sizeof(sc)*8)); // What is happening? printf("The range of a signed char is %hhd to %hhd\n", (sc-(quantity/2)), (sc+(quantity/2)-1)); printf("A signed char can store %llu unique values\n\n", quantity); return(0); }
The cipher project entails taking a string value that is either entered or within a file and shifting it to another value. the shift uses ascii as its base.
encipher.c
/* * encipher.c - program that encodes a message according to a key * * * Compile with: gcc -o encipher encipher.c * * Place key value in: key.txt * Place message to encipher in: plain.txt * Enciphered message placed in: cipher.txt * * Execute with: ./encipher KEYVAL * */ #include <stdio.h> #include <math.h> #include <stdlib.h> int main(int argc, char **argv) { printf("Greetings Agent\n"); FILE *in, *out; int cipher; int key; in = fopen("plain.txt", "r"); out = fopen("enciphered.txt", "w"); if(argv[1] == NULL) //if program called without argument { printf("\nNo argument provided, execute with key argument.\nexample: ./encipher 1\n"); exit(1); } char *plain; plain = (char*) malloc (sizeof(char) * 127); //memory allocate for ascii int count = 0; //when text file is empty if(in == NULL) { printf("\nFile empty, enter some text to encipher\n"); fgets(plain, 127, stdin); while(plain[count] != '\0') //loop stdin characters { count = count+1; } int cipher = atoi(argv[1]); //ascii to integer; cipher key count = 0; //begining while(plain[count] != '\0') //loop until end of characters { key = 1; if(plain[count] >= 65 && plain[count] <= 90) //upper case letters { key = plain[count] + cipher; while(key > 90) { key = key - 26; //cipher shift } } if(plain[count] >= 97 && plain[count] <= 122) //lower case letters { key = plain[count] + cipher; while(key > 122) { key = key - 26; //cipher shift } } if(key == 1) { key = 32; } fprintf(out, "%c", key); count = count+1; } printf("\nEnciphered text is loated in enciphered.txt\n"); } else //if file is present { fgets(plain, 127, in); //get file printf("\nText before cipherication: "); while(plain[count] != '\0') //loop to print file { printf("%c", plain[count]); count = count+1; } int cipher = atoi(argv[1]); //get cipher key value from initial argument count = 0; //begining printf("\nCiphered text output: "); while(plain[count] != '\0') //loop { key = 1; if(plain[count] >= 65 && plain[count] <= 90) //uppercase characters { key = plain[count] + cipher; while(key > 90) { key = key - 26; //cipher shift } } if(plain[count] >= 97 && plain[count] <= 122) //lowercase characters { key = plain[count] + cipher; while(key > 122) { key = key - 26; //cipher shift } } if(key == 1) { key = 32; } printf("%c", key); fprintf(out, "%c", key); //write to file count = count+1; } printf("\nEnciphered text is located in enciphered.txt\n\n"); fclose(in); fclose(out); } return 0; }
decipher.c
/* * decipher.c - program that encodes a message according to a key * * * Compile with: gcc -o encipher encipher.c * * Place key value in: key.txt * Place message to encipher in: plain.txt * Enciphered message placed in: cipher.txt * * Execute with: ./decipher KEYVAL * */ #include <stdio.h> #include <math.h> #include <stdlib.h> int main(int argc, char **argv) { FILE *in, *out; int key; in = fopen("enciphered.txt", "r"); //read enciphered text file out = fopen("plain.txt", "w"); //write deciphered text file if(argv[1] == NULL) //if program called without arguments { printf("Execute with key argument.\nExample: ./decipher 1\n"); exit(1); } char *enciphered; enciphered = (char*)malloc(sizeof(char) * 127); //memory allocate for ascii int count = 0; fgets(enciphered, 127, in); //get characters to decipher from enciphered.txt printf("\nEnciphered text being deciphered: "); //display text before decipher while(enciphered[count] != '\0') { printf("%c", enciphered[count]); count = count+1; } int cipher = atoi(argv[1]); //argument from ascii to integer count = 0; printf("\nDeciphered text: "); while(enciphered[count] != '\0') //while loop deciphers text { key = 1; if(enciphered[count] >= 65 && enciphered[count] <= 90) //for upper case letters { key = enciphered[count] - cipher; while(key < 65) { key = key + 26; //cipher shift } } if(enciphered[count] >= 97 && enciphered[count] <= 122) //for lower case letters { key = enciphered[count] - cipher; while(key < 97) { key = key + 26; //cipher shift } } if(key == 1) { key = 32; } printf("%c", key); fprintf(out, "%c", key); //print to file count = count+1; } printf("\nDeciphered text written to plain.txt\n\n"); fclose(in); // fclose(out); //close files return (0); }
Bignum is an array based calculator program. The the two values are stored as character strings and compared against an integer length array. Each aggregate function is placed within a header file and called in an if/else if loop that's nested in a while loop. The struct really serves no purpose and was an experiment at the end.
bignum.c
#include <stdlib.h> #include <stdio.h> #include <math.h> #include "add.h" // #include "multiply.h" // #include "sub.h" // #include "divide.h" //each aggregate function placed in header file struct { char *first; // char *second; // int length; // int count; // int div; //experimental struct for datatypes (not necessary for logic) }n; int main() { int select=1; printf("Welcome to BigNum!\n"); printf("select a length for your array size: "); scanf("%u", &n.length); // n.length = n.length-1; //get length n.first = (char*)malloc(sizeof(char)*n.length); //first number size of length printf("\nFirst number: "); fgetc(stdin); for(n.count = n.length; n.count >= 0; -- n.count) //get first number, compare it to length { n.first[n.count] = fgetc(stdin); n.first[n.count] = n.first[n.count] - 48; } n.second = (char*)malloc(sizeof(char)*n.length); //second is the size of length printf("\nSecond number: "); fgetc(stdin); for(n.count = n.length; n.count >= 0; -- n.count) //get second number, compare it to length { n.second[n.count] = fgetc(stdin); n.second[n.count] = n.second[n.count] - 48; } while(select != 0 ){ //aggregate function selection menu printf("_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n"); printf("|Please choose an Option(1-5): |\n"); printf("|Option 1: Add |\n"); printf("|Option 2: Subtract |\n"); printf("|Option 3: Multiply |\n"); printf("|Option 4: Divide |\n"); printf("|Option 5: Exit |\n"); printf("-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-\n"); scanf("%d", &select); if (select == 1){ printf("\nYou selected addition.\nThe answer is: "); n.first = add(n.first, n.second, n.length); for (n.length; n.length>=0; --n.length) { printf("%hhu", n.first[n.length]); } printf("\n"); break;} else if (select == 2){ printf("\nYou selected subtraction.\nThe answer is: "); n.first = sub(n.first, n.second, n.length); for (n.length; n.length>=0; --n.length) { printf("%hhu", n.first[n.length]); } printf("\n"); break;} else if (select == 3){ printf("\nYou selected multiplication.\nThe answer is: "); multiply(n.first, n.second, n.length); for (n.length; n.length>=0; --n.length) { printf("%hhu", n.first[n.length]); } printf("\n"); break;} else if (select == 4){ printf("\nYou selected division.\nThe answer is: "); divide(n.first, n.second, n.length, &n.div); printf("%hhu", n.div); printf("\n"); break;} else if (select == 5){ printf("\nYou selected to exit.\nThe answer is: Tom's mom"); //inside joke break;} else{ printf("Incorrect in.\n"); //account for undesired input } } printf("\nGoodbye!\n"); return(0); }
add.h
#ifndef _ADDITION_H // #define _ADDITION_H //define header file for use in main char * add(char * first, char * second, int length) //function prototype { int count = 0; char carry = 0; for(count; count <= length; ++count) //loop until no more remaining numbers, end of length { int holder = (first[count] + second[count])+carry; // addition of numbers if (holder > 9) // { // first[count] = holder-10; // carry=1; // account for carry } // else // { // first[count] = holder; // carry=0; // discount for carry } } return first; //return to main for printing } #endif
sub.h
#ifndef _SUB_H #define _SUB_H char * sub(char *first, char *second, int length) //function prototype { char count = 0; for(count; count <= length; ++count) //loop until no more remaining numbers, end of length { if (first[count] < second[count]) //if the second number is greater than the first { first[count+1] = first[count+1] - 1; // first[count] = first[count] + 10; //carry for subtraction } first[count] = first[count] - second[count]; //simple subtraction } return first; //return to main for printing } #endif
multiply.h
#ifndef _MULTIPLY_H #define _MULTIPLY_H #include <math.h> #include "sub.h" void multiply(char * first, char * second, int length) //function prototype { int count = 0; int holder = 0; char *third; third = (char*)malloc(sizeof(char)*length); //memory allocate for length for (count; count <= length; ++count) //loop until no more numbers { third[count] = first[count]; //copy first into third } for(count=0; count <= length; ++count) //account for leading zero { holder = (second[count]*pow(10, count)); //second (10^count) for(holder; holder > 0; --holder) //loop until no more in holder { first = add(first, third, length); //add function } } first = sub(first, third, length); //return to main for printing } #endif
divide.h
#ifndef _DIVIDE_H #define _DIVIDE_H void divide(char * first, char * second, int length, int *div) //function prototype { int count = 0; char *fourth; fourth = (char*)malloc(sizeof(char)*length); //allocate memory for fourth, size of length for (count; count <= length; ++count) //loop until count matches length { fourth[count] = first[count]; //copy first into fourth } for(count=length; count>=0; --count) //count equals length, run each number until all the way through. { while(first[count] > 0) { ++*div; first = sub(first, second, length); //return to main for printing } } } #endif
Overall I've been pleased with what I've explored over this semester. I'm excited to further explore concepts of C and C++ in systems programming next semester.