Analysing and explaining my source code.
26/12/2015
Let's face it, my blog is stale - rarely new content, and whenever there is new content it is often short and boring.
I've decided to try something different, I'm going to being walking you through snippets of my code, explaining what I'm doing and my though process, just for fun.
I'm going to start today with my latest mini project, the number storage program.
The first section of my value recording program is simple.
I first include some C standard libraries that I need:
stdio.h - used for standard IO such as printf etc
string.h - used for comparing strings
time.h - pretty simple, I use this library to determine the systems time
I then proceed to define two functions that I use later on, this is to ensure that the C compiler knows the functions exists - compilers are dumb.
/* database like program to record values */
#include stdio.h
#include string.h
#include time.h
/* functions */
void addRecord(char* value);
void readRecord();
Next up, just like every other C program in existence I define a main function and add code inside of it. The main function in any program is the first place any compiler looks for code - without the presence of this function your program WILL NOT compile.
To attempt to keep things slightly less complicated I shall post the source first and then explain it.
int main(int argc, char* argv[])
{
if (argc < 2)
{
printf("Utility for recording and monitoring values\n");
printf("This utility requires arguments.\nusage: %s -l [list records] -i [insert record]\n", argv[0]);
return 0;
}
int i;
for (i = 1; i < argc; i++)
{
if (strcmp("-l", argv[i]) == 0)
{
readRecord();
break;
}
if (strcmp("-i", argv[i]) == 0)
{
addRecord(argv[i+1]);
break;
}
}
return 0;
}
Now, this is about the time those of whom don't know at least a little programming should leave - I'm not here to teach you how to program, just to explain what I do!
I define the main function as an int - as you should know this is due to passing the OS an exit code upon completion. I also use the common "int argc, char* argv" to obtain CLI arguments as this is, of course a CLI only program.
I follow the definition by checking for arguments, if this program does not receive at least one argument I print to the screen usage instruction and end the program.
Once it has been confirmed that at least one argument has been passed I check them incrementally for specific key triggers - -l and -i. If none of these are found, the program ends silently - I could have told the user they didn't input a correct argument, but why bother.
If the correct arguments are found, I call the relating function (the same ones we defined earlier) and let them take over - after passing the correct values of course, which in -i's case is anything AFTER the -i (-i was to INSERT, -l was to LIST).
Once the functions are complete, we break out of the for loop and end the program - our job is done.
The final parts to be explained are the two functions we use.
void addRecord(char* value)
{
printf("Adding record: %s\n", value);
/* before we open our file, we want to get our date and time setup which we will also write */
time_t rawtime;
struct tm *timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
/* open file for writing */
FILE *fp;
fp = fopen("values", "a"); /* a to append, not w - would overwrite */
if (fp == NULL)
{
printf("Can't open the file for writing.");
}
else /* file open, write data */
{
fprintf(fp, "%s - %s\n", asctime(timeinfo), value);
fclose(fp);
}
}
Oh my, if you are new to programming close your eyes and run, this looks scary.
This function labelled "addRecord" does just that, it adds a record to the file we are using to store our data.
Now, I have to be honest, this is a simple ass way of storing values. I use no database, I just take whatever a user enters and append it to the end of a file - lazy, yes, but very convenient as I don't expect anyone to actually use this script, except myself.
I begin by informing the user of what record is being appended to the file. I follow it by some nice copy-pasta code for retrieving and converting the time and date to a human readable format that will also be appended to file.
At this point we are ready to append our data to file, so I generically create a FILE pointer and fopen the file we are using to store data. I open it with 'a' access to allow the data to be appended - using 'w' for write mode WILL OVERWRITE the file, we don't want this.
I then check to see if the file was opened successfully, if not I inform the user and the function ends there. If it was however opened correctly, I fprintf the data into the file we opened and then, of course then close it. The function then ends. Also note how I never delete the fp pointer, sue me.
The next function is awfully similar and just reads and displays the entire file to the screen.
void readRecord()
{
/* open file for reading */
FILE *fp;
fp = fopen("values", "r");
if (fp == NULL)
{
printf("Can't open the file for reading.\n");
}
else /* file open, read data */
{
char buff[1000];
while (fgets(buff, 1000, fp) != NULL)
printf("%s", buff);
fclose(fp);
}
}
I use fgets to retrieve the files data into a buffer and then print it, etc
Awfully simple, yet quite nifty and useful.
Should I bother doing more of these? Probably not.