User Tools

Site Tools


opus:fall2013:mpotapen:journal

C/C++ Programming Journal

August 30, 2013

Things Learned About Programming this Week

Include Statements

Include statements are preprocessor directives that essentially place the contents of a file into the specified place. By convention, the files have the “.h” suffix and usually contain function declarations. The file stdio.h is necessary in order to use functions such as printf(), scanf() and other input/output functions that come with C.

Main Function

int main(int a, argc char **argv) is the function that is called upon execution of a bin file and is the start of the program flow.

Some Tools

The Mercurial Repository is a way of keeping files backed up and accesible from different places. GCC(GNU Compiler Collection) is a compiler for C. The -Wall option shows all compilation warnings. The -o option allows the user to specify the name of the bin file. Bash is a shell used to communicate with the operating system(I think?) and do terminally things. Ya I don't really understand what Bash is.

Code Written This Week

#include <stdio.h>\\

   int main(int a, char**b){\\
    	printf("Hello, World\n");\\
      	printf(b[1]);\\ 
     	printf("\n");\\
    	return a;\\
        }
Notes

This program prints “Hello world” and “e” on seperate lines.

September 6, 2013

Things Learned About Programming this Week

Data Types
  1. char=1 byte
  2. short int=2 bytes
  3. int = 4 bytes
  4. long int = 8 bytes
  5. long long int = 8 bytes

The above are the names of the C integer dataypes. They vary in the size of the number that they can store. On my computer and for most operating systems the sizes listed correspond to how much information they can store. Each type also comes in the signed and unsigned variety.

Code Written this Week

Wrote a program to ascertain the upper bounds, lower bounds and sizeof each data type on the system the program is run on.

        signed char sc=0;
        unsigned char uc=0;
        printf("an unsigned char is %lu bytes\n", sizeof(uc));
        printf("lower bound is %hhu\n",uc);
        printf("upper bound is %hhu\n",(uc-1));
        printf("signed char is %ld bytes\n", sizeof(sc));
        printf("lower bound is %hhd\n", ((unsigned char)(uc-1)/2)+1);
//      printf("upper bound is %hhd\n\n", ((unsigned char)(uc-1)/2));
        printf("upper bound is %hhd\n\n", 0xFFFF&0x7F);
notes

The commented out line is a pretty straightforward way of getting the upper bound of a signed data type (dividing the upper range by two and adding one. The line below that utilizes a bitwise AND. 0xFFFF is a 16 bit number with all bits set to 1. When “anded” with 0x7F, the same result is obtained.

September 13, 2013

Thing Learned About Programming this Week

Pointers

A pointer is a variable whose value is a memory address. Pointers are used to handle arrays. In C, a string is actually just an array of chars and pointers are generally “pointed” at the start of the string. To declare a pointer a star is placed before the name of the pointer (ex. char *pointer). The * operator dereferences a pointer and returns the value stored at the address contained in the pointer. & is the inverse operator and returns the address of a variable. A pointer can point to another pointer which is how two (and more) dimensional arrays are handled.

Memory allocation

In order to use memory, you first have to tell the computer how much memory you want to use and where that memory is. This is called allocation and can be done using the malloc() function. malloc() allocates a specified number of bytes and returns a pointer to a memory block at the start (whatever that means) of that region of memory.

scanf

Scanf is an input function that takes input from STDIN and stores that input in memory pointed to by the second argument. The first argument of scanf specifies the format in which the data is stored.

argc/argv

The main() function has two arguments, int argc and char **argv. argc is the number of tokens in the command line while arv is the string of characters in the command line when the bin file is run. argc and argv are just conventional names and the variables may be named with any valid variable name.

Code Written

Wrote a program that makes use of scanf()

        char *name, fi;             //declaring a pointer
        name=NULL;
        fi=0;
        unsigned char age=0;

        printf("Please enter your name:");          //asking for input
        name=(char*)malloc(sizeof(char)*20);        //allocating memory
        scanf("%s", name);                          //getting input
        printf("%s, what is your age?", name);
        scanf("%hhu", &age);
        fi=*(name+0);
        printf("%s, your intitial is %c (%hhu) and you are %hhu years old\n", name, fi, age);  //output data back to user
        return(0);

Wrote program that demonstrates various formatting tricks.

  int x,y;

        if(argc>7)
        {
                printf("%d...argument count\n", argc);
                printf("%8d...argument count\n", argc);
                printf("%8.8d...argument count\n", argc);
                printf("%-8.4d...argument count\n", argc);
                printf("%X(16)...argument count\n", argc);
        }
        else
        {
                printf("must have more than 7 arguments\n");
        }
                

Wrote program that outputs number and value of arguments entered in command line during the program call.

      
        int i;
        printf("There are %d arguments.\n They are:\n", argc);
        for(i=0; i<argc; i++)
        {
                printf("\targv[%d]: %s\n", i, argv[i]);
        }
        return(0);

September 20, 2013

Things learned about Programming this week

Gd library

This week we were introduced to the GD library. The GD library allows the programmer to write code which creates .png image files among other things. It includes functions that draws points, polygons, lines, font handling functions and more. Images are created using GdImageCreate(int wide, int high) which returns a gdImagePtr which points to that image. Most other GD functions take the gdImagePtr as an argument so the program knows which image to modify.

Arrays

I have been using the word array a lot but this week Matt taught us what it actually means. Arrays are homogeneous composite variable modifier types. This means they can hold more than one variable but all variables must be of the same data type. Arrays allow us to use a pointer and an offset to access any particular element of the array. The offset does not necessarily refer to one byte but one block of memory that contains a single instance of that particular datatype. For instance an int is bytes so (intarray+1) is actually 4 bytes over from (intarray+0).

September 27, 2013

The GD library was used to create a snowman, a house, a CCC logo, and a checkerboard pattern.

Checkerboard

#include <stdio.h>
#include <gd.h>
#include "polygons.h"
#include <stdlib.h>
#define BLUE 0
#define RED 1
#define GREEN 2
#define BLACK 3
 
int main()
{
	FILE *out=NULL;
	char *outfile;
	gdImagePtr img;
	unsigned short int wide=800, high=800, x, y;  //size of image
	unsigned int colors[3];
	int i=1;
	img=gdImageCreate(wide, high);                 //create image
 
	colors[BLUE]=gdImageColorAllocate(img, 0, 0, 255);     //allocate colors
	colors[RED]=gdImageColorAllocate(img, 255, 0, 0);
	colors[GREEN]=gdImageColorAllocate(img, 0, 255, 0);
	colors[BLACK]=gdImageColorAllocate(img, 0, 0, 0);
 
	for(y=0;y<8;y++)                                      //loop through image and place recangles
	{
		for(x=0;x<8;x++)
		{
			gdImageFilledRectangle(img, x*100, y*100, (x+1)*100, (y+1)*100, colors[RED]);
 
			if(((x+y)/2)*2==(x+y))
                                gdImageFilledRectangle(img, x*100, y*100, (x+1)*100, (y+1)*100, colors[BLUE]);
 
                        if(i==17)
                                gdImageFilledRectangle(img, x*100, y*100, (x+1)*100, (y+1)*100, colors[GREEN]);
 
			gdImageRectangle(img, x*100, y*100, (x+1)*100, (y+1)*100, colors[BLACK]);
			i++;
		}
	}
 
	outfile=imgPath();                                   //save image to file
	out=fopen(outfile,"wb");
        gdImagePngEx(img, out, -1);
        fclose(out);
        gdImageDestroy(img);
        return(0);
}

Notes
  • This project introduced me to the idea of using multiple loops to move through lists with more than one index which is a very useful concept.
#include <stdio.h>
#include <gd.h>
#include "polygons.h"

#define BLACK 0
#define TAN 1
#define GREEN 2
#define BLUE 3
#define WHITE 4
#define DRED 5
#define RED 6

int main()
{
	FILE *out;
	char *outfile;
	gdImagePtr img;
	unsigned int color[6];
	unsigned short int wide=1024, high=768, x;
	gdPoint points[3];

	img=gdImageCreate(wide, high);

	color[BLACK]=gdImageColorAllocate(img, 0, 0, 0);
	color[TAN]=gdImageColorAllocate(img, 189, 183, 107);
	color[GREEN]=gdImageColorAllocate(img, 0, 255, 0);
	color[BLUE]=gdImageColorAllocate(img, 135, 206, 250);
	color[WHITE]=gdImageColorAllocate(img, 254, 254, 253);
	color[DRED]=gdImageColorAllocate(img, 165, 42, 42);
	color[RED]=gdImageColorAllocate(img, 255, 0, 0);

	points[0].x = 10;                            //populate array of "points" structs
	points[0].y = high/3;
	points[1].x = 790/2;
	points[1].y = 0;
	points[2].x = 800;
	points[2].y = high/3;

	gdImageFilledRectangle(img, 0, 0, wide-1, high-1, color[WHITE]);

	gdImageFilledRectangle(img, 10, 758, 800, high/3, color[TAN]);  //house rectangle
	gdImageFilledRectangle(img, (790/2)-100, 758, (790/2)+100, high*2/3, color[DRED]); //door
	gdImageFilledPolygon(img, points, 3, color[DRED]);//roof
	gdImageFilledEllipse(img, 875, 768-50, 100, 100, color[BLUE]);
	gdImageFilledEllipse(img, 875, 768-125, 50, 50, color[BLUE]);
	gdImageFilledEllipse(img, 875, 768-162, 25, 25, color[BLUE]);
	gdImageFilledArc(img, (1024*2)/3, 50, 90, 100, 90, 270, color[RED], gdArc);
	gdImageFilledArc(img, ((1024*2)/3)+45, 50, 90, 100, 90, 270, color[RED], gdArc);
	gdImageFilledArc(img, ((1024*2)/3)+90, 50, 90, 100, 90, 270, color[RED], gdArc);

	outfile=imgPath();
	out=fopen(outfile,"wb");
	gdImagePngEx(img, out, -1);
	fclose(out);
	gdImageDestroy(img);
	return(0);
}

Notes

Used Points struct from Gd library to make a polygon.

October 4th, 2013

Things Learned About Programming this Week

Functions

Functions in programming are like functions in math. They take inputs, manipulate them, and return output. Functions are useful for packaging code and making it look clean and organized. Functions can take and return values or pointers. passing an argument by value creates a copy of that variable and the copy is manipulated whereas passing an argument using a pointer(or by reference) results in manipulation of the data the pointer references to rather than a copy of the data. Like anything, this can be useful or detrimental.

Code Written this Week

I wrote a program in GD that creates a house with windows and a clock which shows the time of execution. I also wrote a function that creates an n-sided polygon using the GD library which I made use of in drawing.

Polygon Function
void createPol(gdImagePtr image, int x, int y, double rx, double ry, int n, double f, unsigned int col) 
{
        gdPoint pol[n]; //create the gdPoint struct to be used
        unsigned int i; 
        double m=2*M_PI/n;     //angle increment
        for(i=0; i<n; i++)
        {
                pol[i].x=x+(int)rint(rx*sin(f+i*m));   //populating the struct with points
                pol[i].y=y+(int)rint(ry*cos(f+i*m));   
        }
        gdImageFilledPolygon(image, pol, n, col);  //creating the polygon
}
notes

x and y are the center of the polygon. rx and ry are eccentricity factors in the x and y direction. n is the number of sides. f is a phase constant that determines orientation of the polygon. The last argument is the color of the polygon.

Clock Hands Function
void createHands(gdImagePtr image, gdPoint p, int length, double angle, double wangle, unsigned int col)
{
        gdPoint hand[6];                                   //the shape of the hand is relative to the wangle parameter

        double r1, r2;                                     //distance to outermost points of hand, length of beginning segments of clock ha$
        double a1=wangle/2.;

        r1=length/6.;
        r2=3*r1/(3.*cos(a1));       

        hand[0]=p;                                         //populate structs with points of hand
        hand[1].x=p.x+rint(r1*sin(a1+angle));
        hand[1].y=p.y-rint(r1*cos(a1+angle));
        hand[2].x=p.x+rint(r2*sin(wangle+angle));
        hand[2].y=p.y-rint(r2*cos(wangle+angle));
        hand[3].x=p.x+rint(length*sin(angle));
        hand[3].y=p.y-rint(length*cos(angle));
        hand[4].x=p.x+rint(r2*sin(-wangle+angle));
        hand[4].y=p.y-rint(r2*cos(-wangle+angle));
        hand[5].x=p.x+rint(r1*sin(-a1+angle));
        hand[5].y=p.y-rint(r1*cos(-a1+angle));

        gdImageFilledPolygon(image, hand, 6, col);
}
notes

hand[0] refers to the middle of the clock. If the hand is pointing to 12 o'clock then hand[1] is counterclockwise from hand[0]. See picture below for more clear understanding. Angle is the angle of the bisecting line of the clock. wangle is the angle between the two initial line segments.

Main Function
#include <gd.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include "polygons.h"
#include <gdfontt.h>
#include <string.h>
#include <gdfontl.h>
#include <gdfontg.h>

#define WHITE 0
#define BLACK 1
#define TAN 2
#define GREEN 3
#define LIGHTRED 4
#define BLUE 5
#define BRIGHTRED 6
#define BROWN 7



int main()
{
	FILE *out;
	unsigned int color[6];
	char *outfile;
	unsigned char num[12][3];
	struct tm *info=NULL;
	time_t rawtime;
	int a,b,c;
	gdImagePtr img;
	gdPoint roof[3];
	gdPoint house[4];
	unsigned int wide=1024, high=1000;
	unsigned int rwide=((2*wide)/3);                //width of roof
	unsigned int hwide=rwide*7/8;           	//width of house
	unsigned int hleft=rwide/16;            	//left wall of house
	unsigned int hright=hleft+hwide;        	//right wall of house
	unsigned int hhigh=(7*high)/10;         	//heighth of house
	unsigned int hup=high-hhigh;            	//ceiling of house
	unsigned int col=3;                     	//number of window columns
	unsigned int ro=3;                      	//number of window rows
	unsigned int windx=0;
	unsigned int windy=0;
	unsigned short int ic=0;
	unsigned short int ir=0;
	double angle=0;
	double handlen=(wide-hright)/2.5;
	unsigned int clockx=0;
	unsigned int clocky=0;
	double radx;
	double rady;
	unsigned int windoffx=0;
	unsigned int windoffy=0;
	int sleft=0;
	int sup=0;
	int minute=0;
	int hour=0;
	int sec=0;
	double hangle, mangle, sangle;

	img=gdImageCreate(wide, high);

	color[WHITE]=gdImageColorAllocate(img, 255, 255, 255);
	color[BLACK]=gdImageColorAllocate(img, 0,0,0);
	color[TAN]=gdImageColorAllocate(img, 143, 188, 143);
	color[GREEN]=gdImageColorAllocate(img, 84,139,84);
	color[LIGHTRED]=gdImageColorAllocate(img, 200, 0, 0);
	color[BLUE]=gdImageColorAllocate(img, 65, 105, 255);
	color[BRIGHTRED]=gdImageColorAllocate(img, 170, 17, 17);
	color[BROWN]=gdImageColorAllocate(img, 153, 0, 0);

	roof[0].x=rwide/2;
	roof[0].y=high/6;
	roof[1].x=0;
	roof[1].y=hup;
	roof[2].x=rwide;
	roof[2].y=hup;

	gdImageFilledPolygon(img, roof, 3, color[BRIGHTRED]);

	house[0].x=hleft;
	house[0].y=high;
	house[1].x=hleft;
	house[1].y=hup;
	house[2].x=hright;
	house[2].y=hup;
	house[3].x=hright;
	house[3].y=high;

	gdImageFilledPolygon(img, house, 4, color[TAN]);

	windoffx=hwide/6;
	windoffy=hhigh/(ro+1);

	for(ic=0; ic<col; ic++)                                             //make windows using polygon functions
	{
		windx=(ic*(hwide-2*windoffx))/(col-1)+windoffx+hleft;
		for(ir=0; ir<ro; ir++)
		{
			if(ir==2&&ic==1)
			{
				createPol(img, hleft+(hwide/2), hup+5*hhigh/6, hwide/5, 2*hup/3, 4, M_PI/4, color[BRIGHTRED]);
			}
			else
			{
				windy=windoffy+ir*(hhigh-2*windoffy)/(ro-1)+hup;
				createPol(img, windx, windy, hwide/8, hup/6, 6, M_PI/6, color[BLUE]);
			}
		}
	}

	clockx=wide-(wide-hright)/2;                                //set middle of clock
	clocky=(wide-hright)/2;

	gdImageFilledEllipse(img, clockx, clocky, wide-hright, wide-hright, color[BLACK]);        //body of clock

	radx=(wide-hright)/24;
	rady=radx;

	 for(a=0; a<12; a++)                            //create string of numbers 1 to 12
        	{
                	b=0;
	                if(a<9)
        	                c=a+49;
	                else
	                        c='1';
	                num[a][b]=c;
	                b++;
	                if(a<9)
	                        c='\0';
	                else
	                        c=a+39;
	                num[a][b]=c;
	                b++;
	                c='\0';
	                num[a][b]=c;
	                printf("%s\n", num[a]);
	        }
	a=0;

	while(angle<2*M_PI)                                         //put clock face on
	{	
		printf("%d %f", a, angle);
		sleft=clockx+(int)rint(handlen*sin(angle+M_PI/6.))-(strlen((const char *)num[a])*gdFontGetGiant()->w / 2);
		sup=clocky-(int)rint(handlen*cos(angle+M_PI/6.))-gdFontGetGiant()->h / 2;
		createPol(
			img, 
			(int)rint(clockx+handlen*sin(angle+M_PI/6.)), 
			(int)rint(clocky-handlen*cos(angle+M_PI/6.)), 
			radx, 
			rady, 
			8, M_PI/8, color[WHITE]
		);
		gdImageString(img, gdFontGetGiant(), sleft, sup, *(num+a), color[BLACK]);
		angle+=M_PI/6;
		a++;
	}

	time(&rawtime);                                  //get time struct
	info=localtime(&rawtime);

	hour=info->tm_hour;
	minute=info->tm_min;
	sec=info->tm_sec;
	
	sangle=sec*M_PI/30.;                                //calculate angles of hands
	mangle=M_PI*(minute+sec/60.)/30.;
	hangle=M_PI*(hour+(minute+sec/60.)/60.)/6.;

	gdPoint p={clockx, clocky};
	
	createHands(img, p, 2*handlen/3, hangle, M_PI/6., color[BRIGHTRED]);            //place the hands
	createHands(img, p, handlen, mangle, M_PI/9., color[BRIGHTRED]);
	createHands(img, p, handlen, sangle, M_PI/24, color[BLUE]);

	outfile=imgPath();
	out=fopen(outfile,"wb");
        gdImagePngEx(img, out, -1);
        fclose(out);
        gdImageDestroy(img);
        return(0);
}

October 11th, 2013

Things Learned About Programming this Week

We took a test knowledge assessment this week. In preparation for the knowledge asessment we became completely sidetracked and learned about header files and typedefs! Typedefs are preprocessor commands which can give an alternate name to data types.

October 18th

Things Learned About Programming this Week

Structs

A struct is a heterogeneous composite type. It can contain variables of different types. gdPoint from the GD library is an example of a struct with a member named x and a member named y. A struct can be defined, declared, and initialized in the following way.

struct awesomestruct         //defining a struct
{
      int something;
      char somethingelse;
};

awesomestruct instanceofstruct;   //declare instance of the struct

instanceofstruct.something=48;     //initialize member of struct

A “.” is used to access a variable member of a struct and a “→” is used to access a pointer member of a struct.

C++

C++ is a language closely related to C. Almost everything that compiles with a C compiler will compile with a C++ compiler. However C++ is an object oriented language. This means it uses objects very similar to structs to organize code. These objects are called classes. Classes are essentially structs that can have functions as members rather than just pointers to functions. Classes are not the best solution to every problem but can be very useful in some situations such as when an abstract link can be made between various “objects” in a piece of code. If god had created people using object oriented principles instead of procedural ones things could have been a lot simpler for all of us.

A class is defined, declared, and used in the same way as a struct is. Another important difference however is the private, public and protected distinction between members of the class. Members that are declared as private can only be accessed from within the class. Protected members can only be accessed from within the class and by classes inheriting from that class. Public members can be accessed by anyone. This allows for the important inner machinery of the class to be kept away from meddling users of the class.

October 25th, 2013

Things Learned About Programming this Week

Organizing Code into Multiple Files

Code is often organized between three different file types. A “.h” file contains the prototypes for all classes, structs and function. There is also a file that contains the source code for said functions, classes, and structs which can be compiled but not linked with any other files. The third file type is the file that contains the main function which calls and uses the classes and functions and structs and controls the program flow. the main file and source code file both must include the “.h”, or header, file. The main file is then compiled and linked to the already compiled source files.

It is good practice to put #ifndef statements in header files. The prevent the content of the header file from being defined more than once.

Code Written

In class we wrote a program that returns the area of a square, rectangle, and triangle given the length of the sides.

header file
#ifndef _SQUARE_H
#define _SQUARE_H
class rectangle
{
        public:
                rectangle();
                void setside(int, int);
                int getside(int index);
                int area();
                int perimeter();
        private:
                int sides[2];
};

class triangle
{
        public:
                triangle();
                void setside(int, int, int);
                int getside(int);
                float area();
                int perimeter();
        private:
		bool tricheck();
                float sides[3];
                float lside;
                float arsides[2];
};

class square
{
        public:
                square();
                void setside(int);
                int getside();
                int area();
                int perimeter();
        private:
                int x;
};
#endif
source file
#include <cstdio>
#include <cmath>
#include "square.h"

rectangle::rectangle()
{

}

void rectangle::setside(int side1, int side2)
{
	sides[0]=side1;
	sides[1]=side2;
}

int rectangle::getside(int index)
{
	return(sides[index]);
}

int rectangle::area()
{
	return(sides[0]*sides[1]);
}

int rectangle::perimeter()
{
	return(2*sides[0]+2*sides[1]);
}

triangle::triangle()
{

}

bool triangle::tricheck()                    //check if sides make up valid triangle
{
        bool c1=false, c2=false, c3=false;

        if(sides[0]+sides[1]>sides[2])
                c1=true;
        if(sides[1]+sides[2]>sides[0])
                c2=true;
        if(sides[2]+sides[0]>sides[1])
                c3=true;

        return(c1&&c2&&c3);
}

void triangle::setside(int side1, int side2, int side3)   //set side members of the triangles based on user input
{
	int i, j, k=0;
	bool t;

	sides[0]=(float)side1;
	sides[1]=(float)side2;
	sides[2]=(float)side3;
	t=tricheck();

	if(t==true)
	{
		lside=0;

		for(i=0; i<3; i++)
		{
			if(sides[i]>=lside)
				lside=sides[i];
				j=i;
		}

		for(i=0; i<3; i++)
		{
			if(i==j)
				continue;

			arsides[k]=sides[i];
			k++;
		}
	}
	else
	{
		printf("that is not a valid triangle\n");
	}
}

int triangle::getside(int index)
{
	return(sides[index]);
}

float triangle::area()                       //calculate area using heron's formula
{
	float theta;
	float h;
	float a;

	theta=acos((pow(arsides[0], 2)-pow(arsides[1], 2)-pow(lside, 2))/(-2*lside*arsides[1]));
	h=arsides[1]*sin(theta);
	a=0.5*h*lside;
	return(a);
}

int triangle::perimeter()
{
	return((int)(sides[0]+sides[1]+sides[2]));
}

square::square()
{
	x=0;
}

void square::setside(int side)
{
	x=side;
}

int square::getside()
{
	return(x);
}

int square::area()
{
return(x*x);
}

int square::perimeter()
{
	return(4*x);
}
main function
#include "square.h"
#include <cstdio>

int main()
{
        square s1;                 //instantiate classes
        square s2;
        rectangle r1;
        rectangle r2;
        triangle t1;
        triangle t2;

        s1.setside(4);                   //set sides of squares
        s2.setside(12);
        printf("s1's side is %d\n", s1.getside());           //print sides of square
        printf("s1's area is %d\n", s1.area());              //calculate area
        printf("s1's perimeter is %d\n", s1.perimeter());    //calculate perimeter

        printf("s2's side is %d\n", s2.getside());
        printf("s2's area is %d\n", s2.area());
        printf("s2's perimeter is %d\n", s2.perimeter());

        r1.setside(2, 4);
        r2.setside(5, 10);
        printf("r1's sides are %d, %d\n", r1.getside(0), r1.getside(1));
        printf("r1's area is %d\n", r1.area());
        printf("r1's perimeter is %d\n", r1.perimeter());

        printf("r2's sides are %d, %d\n", r2.getside(0), r2.getside(1));
        printf("r2's area is %d\n", r2.area());
        printf("r2's perimeter is %d\n", r2.perimeter());

        t1.setside(4, 3, 5);
        t2.setside(1, 1, 2);
        printf("t1's sides are %d, %d, %d\n", t1.getside(0), t1.getside(1), t1.getside(2));
        printf("t1's area is %f\n", t1.area());
        printf("t1's perimeter is %d\n", t1.perimeter());

        printf("t2's sides are %d, %d, %d\n", t2.getside(0), t2.getside(1), t2.getside(2));
        printf("t2's area is %f\n", t2.area());
        printf("t2's perimeter is %d\n", t2.perimeter());


        return(0);
}

November 1st, 2013

Things Learned About Programming this Week

BigNum

We have started working on a BigNum class. It is a user created datatype that allows manipulation of numbers that are larger than long long ints.

November 8th, 2013

Things Learned About Programming this Week

Debugging

Matt showed us how to use the gdb this week. Where has this been all my life? Including a -g in the compile statement and then running the program with the command gdb runs the debugger. The debugger allows stepping through a program line by line and printing the values of variables at any point in the code. gdb has a lot of commands but the one I use the most is creating breakpoints. This stops the program in the middle of execution at a specified line. This has been extremely helpful in my BigNum programming which I am still working on.

November 15th, 2013

Things Learned About Programming this Week

Inheritance

One way of populating the members of a class is by copying them from another class. This makes the new class a child class and the old one a parent class. In C++ copying the members of a parent class is supported with the inheritance functionality. Inheritance is a way of organizing code that includes objects which are partial cases of other objects.

makefiles

Makefiles are a way to get around the hell that is typing in compilation statements into the commanline. Makefiles contain a script that do the typing for you so that all the user has to type is “make”.

Code written

Matt provided us with a “storage” class and challenged us to implement a “tape” class which inherits from storage. A tape is a form of a storage device so the whole inheritance thing fits very well here.

storage.h
#ifndef _STORAGE_H
#define _STORAGE_H

//
// storage.h - class declaration for the storage class, used for covering
//             "Inheritance".
//
using namespace std;

class storage
{
	public:
		storage();			// constructor
		int getCapacity();
		int getFree();
		int getUsed();
	
	protected:
		int load();
		void store(int);
		bool pos(int);
	
	private:
		int data[256];
		int used;
		int available;
		int loc;
};

#endif
storage.cc
#include "storage.h"

storage :: storage()
{
	int i;
	used = 0;
	available = 255;
	for (i = 0; i < 256; i++)
		data[i] = 0;
	loc = 0;
}

int storage :: getCapacity()
{
	return used + available + 1;
}

int storage :: getFree()
{
	return available + 1;
}

int storage :: getUsed()
{
	return used;
}

#include <iostream>

int storage :: load()
{
	return data[loc];
}

void storage :: store(int value)
{
	if (used < 255)
	{
		data[loc] = value;
		used++;
		available--;
	}
	else
		cout << "Error! Out of space!" << endl;

	if (value == 0)
	{
		used--;
		available++;

		if(used > 255)
			used = 255;

		if(used < 0)
			used = 0;

		if(available > 255)
			available = 255;

		if(available < 0)
			available = 0;
	}
}

bool storage :: pos(int location)
{
	bool retval = true;

	if ((location >= 0) && (location <= 255))
		loc = location;
	else
		retval = false;

	return retval;
}
tape.h
#ifndef _TAPE_H
#define _TAPE_H

//
// tape.h - derived class declaration for the tape class
//

#include "storage.h"
#include <iostream>
class tape : public storage    //inherit from storage
{
	public:
		tape();
		int read();
		void write(int);
		void forward();
		void backward();
		void rewind();
		void setlabel(string);
		string getlabel();
		int getpos();

	private:
		string label;
		int position;
};

#endif
tape.cc
#include "storage.h"
#include "tape.h"
#include <cstdio>

tape::tape()      //initialize label and position
{
	position=0;
	pos(position);
	label="unlabeled";
}

int tape::read()    //read using a function inherited from storage
{
	return(load());
}

void tape::write(int num)    //write
{
	store(num);
}

void tape::forward()      //move forward
{
	bool errcheck;
	position++;
	errcheck=pos(position);
	if(errcheck==false)
	{
		printf("End of tape!\n");
		position--;
		pos(position);
	}
}

void tape::backward()
{
        bool errcheck;
        position--;
        errcheck=pos(position);
        if(errcheck==false)
        {
                printf("End of tape!\n");
                position++;
                pos(position);
        }

}

void tape::rewind()
{
	while(position!=0)
	{
		position--;
	}

	pos(position);
}

void tape::setlabel(string lstr)   
{
	label=lstr;
}

string tape::getlabel()
{
	return(label);
}

int tape::getpos()
{
	return(position);
}
tapemain.cc
#include <cstdio>
#include "tape.h"
#include <iostream>

using namespace std;

int main()
{
	tape t;
	char ans;
	string l;
	int val;
	int i;

	cout << "This is a tape, would you like to label it? (y/n)" << endl;
	cin >> ans;

	if(ans==121)
	{
		cout << "What would you like to label it (no spaces)?" << endl;
		cin >> l;
		t.setlabel(l);
		cout << "The tape is now labeled " << t.getlabel() << endl;
	}

	cout << "The current position is " << t.getpos() << " and it contains " << t.read() <<  endl;

	while(ans!=55)
	{
		cout << "0 - forward" << endl;             //menu
		cout << "1 - backward" << endl;
		cout << "2 - rewind" << endl;
		cout << "3 - read" << endl;
		cout << "4 - write" << endl;
		cout << "5 - forward multiple positions" << endl;
		cout << "6 - backward multiple positions" << endl;
		cout << "7 - quit" << endl;
		cin >> ans;                                     //wait for input

		switch(ans)
		{
			case 48:
				t.forward();
				cout << "position is " << t.getpos() << endl;
				break;
			case 49:
				t.backward();
				cout << "position is " << t.getpos() << endl;
				break;
			case 50:
				t.rewind();
				cout << "position is " << t.getpos() << endl;
				break;
			case 51:
				cout << "value is " << t.read() << endl;
				break;
			case 52:
				cout << "please enter value" << endl;
				cin >> val;
				t.write(val);
				break;
			case 53:
				cout << "how many spaces?" << endl;
				cin >> val;
				for(i=0; i<val; i++)
				{
					t.forward();
				}
                                cout << "position is " << t.getpos() << endl;
				break;
			case 54:
                                cout << "how many spaces?" << endl;
                                cin >> val;
                                for(i=0; i<val; i++)
                                {
                                        t.backward();
                                }
                                cout << "position is " << t.getpos() << endl;
				break;
			case 55:
				return(0);
		}
	}
}

November 22, 2013

Things Learned About Programming this Week

We're spending the rest of the semester working on our end of course experience. Also I Finished BigNum. Well I did what I could. It has functionality for multiplication, addition, subtraction(kind of), increment, decrement, setting the value of the bignum, and lessthan(). The class is also supposed to work in any base up to 36 but I don't think I've tested it enough to say it does for sure. There's a lot of code.

BigNum

BigNum.h
#ifndef _BIGNUM_H
#define _BIGNUM_H

class BigNum
{
	public:
		BigNum();
		BigNum(unsigned char);
		unsigned char getBase();
		unsigned char getLength();
		unsigned char getSign();
		void setBase(unsigned char);
		void setLength(unsigned char);
		void setSign(unsigned char);
		void setVal(unsigned char *, unsigned char, unsigned char l);
		void setVal(unsigned char *, unsigned char l);
		void zero();
		void print();
		int increment(signed int);
		BigNum add(BigNum, BigNum);
		bool lessthan(BigNum *, BigNum *);
		BigNum mult(BigNum, BigNum);

	private:
		unsigned char base;
		unsigned char length;
		unsigned char sign;
		unsigned char *data;
		void allocate(int);
		int lenadjust(BigNum, BigNum);
};
#endif
BigNum.cpp
#include "bignum.h"
#include <cstdio>
#include <climits>
#include <cstring>
#include <cstdlib>


BigNum::BigNum()         //constructor
{
	BigNum(8);       //calls other cobnstructor to set the length
}

BigNum::BigNum(unsigned char length)   //other constructer
{
        this->length=length;
        base=10;
        sign=0;
        data=new unsigned char(this->length);
        this->zero();
}

unsigned char BigNum::getBase()
{
        return(base);
}

void BigNum::setBase(unsigned char base)
{
        this->base=base;
}

unsigned char BigNum::getLength()
{
        return(length);
}

void BigNum::setLength(unsigned char length)
{
        this->length=length;
}

void BigNum::print()                        //prints bignum
{
        for(int i=0; i<length; i++)
        {
		if(*(data+i)>9)                         //account for bases larger than 10
			printf("%c", *(data+i)+87);
		else
			printf("%hhu", *(data+i));
        }
}

unsigned char BigNum::getSign()
{
        return(sign);
}

void BigNum::setSign(unsigned char sign)
{
        this->sign=sign;
}

void BigNum::zero()           //set bignum to zero
{
        for(int i=0; i<length; i++)
        {
                *(data+i)=0;
        }
}

int BigNum::increment(signed int n)
{
	int i=1;

	if(n!=1&&n!=(-1))                      //so that increment can also decrement
		return(1);

	*(data+(length-1))=*(data+(length-1))+n;      //increment/decerement
	while(*(data+(length-i))!=0)                  //change digits based on carries
	{
		if(*(data+(length-i))==base)
		{
			*(data+(length-i))=0;
			*(data+(length-i-1))=*(data+(length-i-1))+n;
			i++;
		}
		else if(*(data+(length-i))==UCHAR_MAX)
		{
			*(data+(length-i))=base+n;
			*(data+(length-i-1))=*(data+(length-i-1))+n;
			i++;
		}
		else
		{
			break;
		}
	}
	return(0);
}

bool BigNum::lessthan(BigNum *bn1, BigNum *bn2)
{
	int i;

	for(i=0; i<bn1->getLength(); i++)               //compare every digit from left to right
		{
			if (*(bn1->data+i)==*(bn2->data+i)) continue;

			else return(*(bn1->data+i)<*(bn2->data+i));
		}
	return(false);
}

BigNum BigNum::add(BigNum n1, BigNum n2)
{
	unsigned char carry=0;
	int i;
	unsigned char nlen=n1.getLength();
	char sfac1=1;
	char sfac2=1;
	bool n1n2;
	bool n2n1;

	if(n1.sign==45)          //for subtraction functionality, not fully implemented
		sfac1=-1;
	if(n2.sign==45)
		sfac2=-1;

	if(n1.length!=n2.length)
		lenadjust(n1, n2);

	BigNum r(nlen);
	r.setBase(n1.base);

	if(n1.sign==n2.sign)       //if signs are same then just add digits together normally
	{
		for(i=n1.length-1; i>-1; i--)
		{
			*(r.data+i)=(*(n1.data+i))+(*(n2.data+i))+carry;  //add normally

			if(*(r.data+i)>=r.base)
			{
				*(r.data+i)=*(r.data+i)-r.base;
				carry=1;
			}
			else
			{
				carry=0;
			}
		}

		r.setSign(n1.sign);
	}
	else                        //if they are opposite then account for case when absolute value of one is larger than the other
	{
	        if(n1.sign==45)
        	        sfac1=-1;
	        if(n2.sign==45)
	                sfac2=-1;

		for(i=n1.length-1; i>-1; i--)
		{

                        *(r.data+i)=(*(n1.data+i))*sfac1+(*(n2.data+i))*sfac2;  //add with sign factors

			if(*(r.data+i)>=UCHAR_MAX-r.base)
			{
				*(r.data+i)=UCHAR_MAX-(*(r.data+i))+1;
				*(r.data+i-1)=(*(r.data+i-1))-1;
			}
		}

		n1n2=lessthan(&n1, &n2);
		n2n1=lessthan(&n2, &n1);

		if((n1n2 && n1.sign==0)||(n2n1 && n1.sign==45))
			r.setSign(45);
		else
			r.setSign(0);
	}

	return(r);
}

void BigNum::setVal(unsigned char *indata, unsigned char baseval, unsigned char l)
{
	int i;

	this->setLength(l);
	if(l!=this->getLength())
		this->allocate(l);

	this->setBase(baseval);

	memcpy((void *)this->data, (const void *)indata, l*sizeof(unsigned char));  //copy array to BigNum array
	for(i=0; i<l; i++)
	{
		if(*(data+i)>=48&&*(data+i)<=57)                                   //account for various bases
			*(data+i)=*(data+i)-48;

		if(*(data+i)>=97&&*(data+i)<=122)
			*(data+i)=*(data+i)-87;
	}
}

void BigNum::setVal(unsigned char *indata, unsigned char l)
{
	setVal(indata, this->base, l);
}

void BigNum::allocate(int len)
{
	delete this->data;
        this->data=new unsigned char(len);
        this->zero();
}

BigNum BigNum::mult(BigNum num1, BigNum num2)
{
	BigNum numr(num1.length*num2.length);
	BigNum numa(num1.length*num2.length);
	numr.base=numa.base=num1.base;
	int i, j;
	int carry=0;
	unsigned char **addends;                   //double pointer for addends
	int a, b;
	int addlen=num1.length+num2.length;

	if(num1.length!=num2.length)
		lenadjust(num1, num2);

	addends=(unsigned char **)malloc(sizeof(unsigned char *)*num1.length);
	for(i=0; i<num1.length; i++)
	{
		*(addends+i)=(unsigned char *)malloc(sizeof(unsigned char)*(int)(addlen));       //allocate memory for addends
	}

	for(i=0; i<num2.length; i++)
	{
		b=*(num2.data+num2.length-1-i);                //current digit of one BigNum

		for(j=0; j<num1.length+1; j++)
		{
			a=*(num1.data+num1.length-1-j);         //current digit of other BigNum
			*(*(addends+i)+addlen-1-j-i)=(unsigned char)(((a*b)%(int)base)+carry);   //multiply and use mod division to get most significant digit
			carry=(a*b)/(int)(base);  
		}
		for(j=0; j<i; j++)
		{
			*(*(addends+i)+addlen-1-j)=0;   //put zeros in placeholders
		}
		numa.setVal(*(addends+i), numa.base, (unsigned char)addlen);    //add addends together
		numr=numr.add(numr, numa);
	}
	return(numr);
}

int BigNum::lenadjust(BigNum a, BigNum b)
{
	unsigned char *temp;
	int i;

	if(a.length==b.length)
		return(1);

	if(a.length>b.length)
	{
		temp=new unsigned char(a.length);
		for(i=0; i<b.length; i++)
		{
			*(temp+a.length-i)=*(b.data+b.length-i);
		}
		delete b.data;
		b.data=new unsigned char(a.length);
		memcpy(temp, b.data, b.length);
	}
	else
	{
                temp=new unsigned char(b.length);
                for(i=0; i<a.length; i++)
                {
                        *(temp+b.length-i)=*(a.data+a.length-i);
                }
                delete a.data;
                a.data=new unsigned char(b.length);
                memcpy(temp, a.data, a.length);
	}

	return(0);
}

THANKSGIVING

December 6th, 2013

How Pacman ate Christmas

opus/fall2013/mpotapen/journal.txt · Last modified: 2013/12/06 22:05 by mpotapen