Monday, June 10, 2013

Summer Break

Summer break has started and now its time to get cracking on making new apps for the appstore!

My C++ File IO tutorial is doing very well in drawing hits to my site, which helps motivate me to make more posts and be more active. Look for the next tutorial in the series next week sometime! Right now I'm just finishing up the program and preparing to write about it!

Future Android Game releases will be coming to the Google Store, so stay alert for that! I am very interested in receiving feedback and getting me feet on the ground so I can start to release bigger projects.

Internship! Yes I have an internship which will be keeping me busy, but also giving me an opportunity to put my skills to work!

Monday, May 27, 2013

File IO in C++ Part 5 [Tutorial]

Need I say more? Part 5 of my File IO tutorial here, covering the basics of binary files, data structures and other advanced applications of File IO.


Monday, May 13, 2013

File IO in C++ Part 4 [Tutorial]

We have come quite far now in our File IO, having made a fully workable program based off reading files - but we still aren't done! Today we are going to take another step forward and start looking at the fstream class, which allows both reading and writing. Furthermore, we are going to finally take a look at the bit-flags, before next week when we move on with reading and writing data structures. Finally, in the week after that, we will complete this tutorial series by creating a ToDo list program using everything we have learned!

So without further ado, here is part 4 of my tutorial for File IO in C++!

Monday, April 29, 2013

Straying Off-Topic Again

My birthday has come around again, which usually calls for me to think back to how I spent the last year of my life. While this usually means contemplating some of the major discussions I've made of the past year, I've realized I could also apply some analysis to CollegeGameDev. And so when I start looking back over the past few months posts, I have become very off-topic, for better or for worse.

Monday, April 15, 2013

File IO in C++ Part 3 [Tutorial]

Over the past two weeks, we have worked through opening, closing, reading, and writing files. This tutorial will now show how these concepts can be put to use in order to make a simple flash-card like program. Furthermore, this program will highlight the need for more dynamic uses of the fstream class in order to ease data storage and retrevial.

Here it is, part 3 of my tutorial for File IO in C++!


File IO in C++ Part 3

The Flash-Card Program


Overview

In the first week, we covered what a file is, and the basics of writing to a file. In week two, we examined reading from a file, and completed a simple program to read and write text from a file. This week we are going to build on those concepts to create a simple program that will do 4 things:
  1. Load a text file containing up to 100 questions and answers.
  2. Display all the questions/answer combos inside the file.
  3. Display individual question/answer combos from the file.
  4. Allow the user to add questions to the file.
  5. Allow the file to be saved.
So, lets get to work!

Prototypes and Structures

Now that we know what we want our program to do, lets create some prototypes for each of these functions. We will need:
  • A loadQuestions() function for loading the text file.
  • A displayAllQuestions() function for displaying all the questions.
  • A displayQuestion(int) function for displaying a singular question.
  • A createNewQuestion() function for adding a question. Were also going to want a firstTimePopulate() method for adding questions to a blank file.
  • A writeQuestions() function for saving to the text file.
Furthermore, I made one big design choice for simplicity in this program - Most of the key variables will reside globally, simplifying parameter passing. This tutorial is meant for simplicity, not style, which puts this strategy as the logical choice.

Our questions will reside in a struct for them, and we will keep track of the number of questions and filename in respective variables. At the moment, this means we roughly have something that looks like:
//Load and Display Functions
void loadQuestions();
void displayQuestion(int);
void displayAllQuestions();

//Write and Create Functions
void firstTimePopulate();
void createNewQuestion();
void writeQuestions();


//Global Variables
struct Question{
 char *question;
 char *answer;
} questions[100];

char * fileName;
int numQuestions;

There we go, making progress! Lets start things from the bottom up, working through the write functions back to the load functions.

Write and Create Functions

As you can see, the first thing we have is writeQuestions(). This function is meant to output all of our questions into the text file specified at fileName. We are going to accomplish this following our 4 step strategy, Instantiate, Open, Write, Close - Let's see how this works out:
void writeQuestions(){
 ofstream writeFile; //Step 1 - Instantiate
 
 writeFile.open(fileName); //Step 2 - Open

 int i = 0; //Step 3 - Write
 while (i < numQuestions){//*
  if (*questions[i].question != '\0'){ //**
   writeFile<<questions[i].question<<"\n";
   writeFile<<questions[i].answer<<"\n";
  }
  i++;
 }

 writeFile.close(); //Step 4 - Close
}

There are a few things to take note of in here during our write step:
  • * = Since questions is an array, we keep track of the number of used elements in numQuestions. Thus, when we write from questions, we need to check that we aren't writing unfilled elements, so we do a loop to ensure this doesn't happen.
  • ** = Since we have the potential to accidentally write a blank question into the database, but there would be no sense keeping it, we filter out and skip writing any questions that have the '\0' character as their content ( meaning empty line).
Lets now take a look at createNewQuestion(). This function is going to be far easier then the last:
void createNewQuestion(){
 cout<<"What would you like your question to be?"<<endl;
 cin.getline(questions[numQuestions].question = new char[128], 128);
 cout<<"What would you like your answer to be?"<<endl;
 cin.getline(questions[numQuestions].answer = new char[128], 128);
 numQuestions++;
 writeQuestions();
}

Creating a question is easy - First we prompt the user for input using cout. Then, we use the cin.getline(char, int) function in order to capture the input. It is important to note here that the char pointers in question[numQuestions] are uninitialized, thus we need to initialize them for the getline() function to work.
At the end of this function, we just update the numQuestions variable and write out the new file with the extra question.

firstTimePopulate() is going to be our last function here, and all it does is expand on the createNewQuestion() function. It looks like this:
void firstTimePopulate(){
 cout<<"It looks like you have zero questions in your question file!"<<endl;
 cout<<"Lets add a new question..."<<endl;
 createNewQuestion();
}

Reading and Display Functions

So with writing out of the way, lets tackle our 3 read functions: loadQuestions(), displayQuestion(), and displayAllQuestions().

With loadQuestions() being the most vital, and the most difficult, lets work on it first:
void loadQuestions(){
 ifstream readFile; //Step 1 - Instantiate

 readFile.open(fileName); //Step 2 - Open

 if (readFile.is_open() == false){ //* - This means the file was just created, and that it never existed!
  readFile.close(); //We wont be reading anything, so skip step 3 and do step 4 - close
  numQuestions = 0; //Set Number of Questions to 0
  firstTimePopulate(); //Create a new Question (which will inc numQuestions once)
  return;
 }

 //Step 3 - Read
 numQuestions = 0; //We do not know how many questions we will read, so lets assume its 0
 while(!readFile.eof() && numQuestions < 100){ //We cant read past eof, and our question array is only 100 elements
  readFile.getline(questions[numQuestions].question = new char[128], 128);
  readFile.getline(questions[numQuestions].answer = new char[128], 128);

  if (*questions[numQuestions].question != '\0') //** - If this loaded question is not empty, add it
   numQuestions++;
 }

 readFile.close(); //Step 4 - Close
}

So, what is this big confusing function? Well, lets pay attention to a few things:
  • We keep our 4 step structure, Instantiate, Open, Read, Close
  • At *, we correct for the fact that the file may not exist - in this case, it did not open, so the is_open() call will allow us to correct for this... how? By creating a question inside of it of course!
  • At step 3, we read through the file getting data from each line. Just like in the create functions, we need to ensure we create space for question[x]'s pointers.
  • At **, we check to see if the question loaded actually has any content by comparing it with '\0'. If its blank, then we skip incrementing numQuestions, causing the next read to overwrite the current question.
  • There is a potential memory leak in here, but its not too big of deal so long as loadQuestions() is only called at the start of the program.

Also now that our questions have been loaded, displaying a question is just a matter of outputting 2 lines. cin.get() is used to force the user to get the next line, essentially flipping a card. Here's displayQuestion(int questionNumber):
void displayQuestion(int questionNumber){
 cout<<"Q: "<<questions[questionNumber].question<<endl;
 cin.get();
 cout<<"A: "<<questions[questionNumber].answer<<endl;
 cin.get();
}

Displaying all the questions in a file works quite similarly, just using a for loop to ensure each question is read. Instead of this being a flashcard like flip, we are going to just stream them out at once for reference:
void displayAllQuestions(){
 cout<<"Questions in "<<fileName<<endl;
 for (int i = 0; i < numQuestions; i++){
  cout<<"Q: "<<questions[i].question<<endl;
  cout<<"A: "<<questions[i].answer<<endl<<endl;
 }
}

Main

Lets put our code to use now by creating a main that allows us a looping menu to decide what to do with it all!
int main() {
 cout<<"Specify your questions file:";
 cin.getline(fileName = new char[128], 128);
 loadQuestions();

 int choice;
 while(choice != 4){
  cout<<"\n\nWhat would you like to do?\n"
    "0. Display All Questions\n"
    "1. Add Questions\n"
    "2. Ask 10 Questions\n"
    "3. Questions File Info\n"
    "4. Exit"<<endl;
  cin>>choice;
  cin.get();

  if (choice == 0){
   displayAllQuestions();
  } else if (choice == 1){
   createNewQuestion();
  } else if (choice == 2){
   for (int reps = 0; reps < 10; reps++)
    displayQuestion(rand() % numQuestions);
  } else if (choice == 3)
   cout<<"You have "<<numQuestions<<" questions in your file "<<fileName<<endl;

 }

 cout<<"Exiting...";
 return 0;
}

This shouldn't be too bad to figure out - We get an input for file name, load our questions, then loop through a menu executing the choices based off of our six functions!

So, its done - Wrap it all together and there we go! Try experimenting with this code to get a feel for it, and make sure you understand the basics. Next week we will look at a much simpler way of writing/reading data structures (then line by line), and also examine the fstream class!

Here is the full code posting (and here is a link to this code on Github)


#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string>

using namespace std;

//Load and Display Functions
void loadQuestions();
void displayQuestion(int);
void displayAllQuestions();

//Write and Create Functions
void firstTimePopulate();
void createNewQuestion();
void writeQuestions();


//Global Variables
struct Question{
 char *question;
 char *answer;
} questions[100];

char * fileName;
int numQuestions;


int main() {
 cout<<"Specify your questions file:";
 cin.getline(fileName = new char[128], 128);
 loadQuestions();

 int choice;
 while(choice != 4){
  cout<<"\n\nWhat would you like to do?\n"
    "0. Display All Questions\n"
    "1. Add Questions\n"
    "2. Ask 10 Questions\n"
    "3. Questions File Info\n"
    "4. Exit"<<endl;
  cin>>choice;
  cin.get();

  if (choice == 0){
   displayAllQuestions();
  } else if (choice == 1){
   createNewQuestion();
  } else if (choice == 2){
   for (int reps = 0; reps < 10; reps++)
    displayQuestion(rand() % numQuestions);
  } else if (choice == 3)
   cout<<"You have "<<numQuestions<<" questions in your file "<<fileName<<endl;

 }

 cout<<"Exiting...";
 return 0;
}



void loadQuestions(){
 ifstream readFile;

 readFile.open(fileName);

 if (readFile.is_open() == false){
  readFile.close();
  numQuestions = 0;
  firstTimePopulate();
  return;
 }

 numQuestions = 0;
 while(!readFile.eof() && numQuestions < 100){
  readFile.getline(questions[numQuestions].question = new char[128], 128);
  readFile.getline(questions[numQuestions].answer = new char[128], 128);

  if (*questions[numQuestions].question != '\0')
   numQuestions++;
 }

 readFile.close();
}

void displayQuestion(int questionNumber){
 cout<<"Q: "<<questions[questionNumber].question<<endl;
 cin.get();
 cout<<"A: "<<questions[questionNumber].answer<<endl;
 cin.get();
}

void displayAllQuestions(){
 cout<<"Questions in "<<fileName<<endl;
 for (int i = 0; i < numQuestions; i++){
  cout<<"Q: "<<questions[i].question<<endl;
  cout<<"A: "<<questions[i].answer<<endl<<endl;
 }
}

void firstTimePopulate(){
 cout<<"It looks like you have zero questions in your question file!"<<endl;
 cout<<"Lets add a new question..."<<endl;
 createNewQuestion();
}

void createNewQuestion(){
 cout<<"What would you like your question to be?"<<endl;
 cin.getline(questions[numQuestions].question = new char[128], 128);
 cout<<"What would you like your answer to be?"<<endl;
 cin.getline(questions[numQuestions].answer = new char[128], 128);
 numQuestions++;
 writeQuestions();
}

void writeQuestions(){
 ofstream writeFile;

 writeFile.open(fileName);

 int i = 0;
 while (i < numQuestions){
  if (*questions[i].question != '\0'){
   writeFile<<questions[i].question<<"\n";
   writeFile<<questions[i].answer<<"\n";
  }
  i++;
 }

 writeFile.close();
}

Monday, April 1, 2013

1 Week File IO Tutorial Hiatus & Offtopic

I usually like to be consistent on pushing out updates, but this week I think I need a break due to school. As the semester draws near to the midway point, things pick up and get busy for me, keeping me from being able to take the time to polish content. Fortunately, this means spring break is coming too, which will give me a good chance to update some more posts!

Also, some advice on the subject of per-queuing posts: I try to avoid doing it, but I still think its far favorable to pre-queue (write posts and schedule them) then to post-post (posting posts after a date with a false time stamp). While both technically are a form of taking a break/being lazy, I feel like post-posts are more a form of cheating and "faking" then pre-queues are...

Either way, over time I have come to develop my own method which I think works out very nicely - I create very rough drafts of enough posts to cover me for a while, then periodically update each post and polish it in time for my next scheduled post. Through this, I can have consistent updates regardless of my school work, while largely avoiding pre-queues. This also enables me to make random, short posts as frequently, such as covering a large assignment that I wanted to share or to an update to a project, without having to worry about the quality of my content taking a dive.

More content next week, including a continuation of my tutorial series on C++!

Monday, March 18, 2013

File IO in C++ Part 2 [Tutorial]

Last week we worked on loading content from files, and this week we will now focus on reading content. After the completion of this tutorial, we will be ready to move on to advanced topics such as applying read/writes to make simple programs and eventually loading data structures with them.

For now, here is Part 2 of my tutorial for File IO in C++!