Creating a Multiple Choice Quiz System, Part 2
So far, we have dealt with ways in which the QuizQuestions object can handle syntax errors within the quiz file. But many syntax errors are created simply by mistake or by users unfamiliar with the defined file format.
One solution is to provide users with tools for creating quiz files with fewer errors. Given the amount of time we spend writing CGI programs and HTML forms, it makes sense to create a short program that takes the contents of an HTML form and saves it to disk.
An example of one such form is shown in Listing 4. Upon submission, the form's contents are handed to create-quizfile.pl, which then creates a properly formatted quiz file.
In order to implement this feature, we need to add two new methods to QuizQuestions. One, addQuestion, takes a six-element list and adds it to questions, the instance variable containing fields from the quiz file. The second method, saveFile, does the opposite of loadFile, taking the current questions and saving them.
Here is one possible implementation of addQuestion:
sub addQuestion
{
# Get ourselves
my $self = shift;
# Get our arguments
my ($question, $a1, $a2, $a3, $a4,
$correct) = @_;
# Turn our arguments into a string
my $new_question = join(" ", @_);
# Get our instance variable
my @questions = @{$self->{"questions"}};
# Add the new question
push (@questions, $new_question);
# Reset the instance variable
$self->{"questions"} = \@questions;
# Return successfully (= 0)
return 0;
}
This version of addQuestion is fairly simple, if not very robust. For instance, it doesn't check to make sure the correct answer is one of A, B, C or D. But it does let us add new questions to the QuizQuestions object. Notice that addQuestion both retrieves and sets values for the instance variable questions.
If we were interested in extending our quiz on Emacs, we could use addQuestion in the following way:
my $error = $questions->loadFile; &log_and_die($error) if $error; $questions->addQuestion( "What term describes the cursor's current location?", "mark", "point", "cursor", "mouse", "B");
Immediately after executing this code, $questions contains one more question. However, this question is lost upon the program's exit, because we have not yet saved the new question to the quiz file. In order to save the questions to a quiz file, define saveFile like this:
sub saveFile
{
# Get ourselves
my $self = shift;
# Open the questions file for writing
open (QUESTIONS, ">$questionDir" .
$self->{"quizname"}) ||
return "Could not open " .
$self->{"quizname"} . " for writing";
# Loop through the questions
my @questions = @{$self->{"questions"}};
my $question;
for each $question (@questions)
{
print QUESTIONS $question, "\n";
}
close(QUESTIONS);
return 0;
}
This code iterates through the questions, and writes them to the
quiz file. Since we are writing all of the questions to disk rather
than appending them, we use the > when
opening the file, thereby overwriting any data that existed
previously.
Since saveFile saves only the contents of the questions instance variable, it effectively obliterates comments and white space in the file. Of course, anyone creating the quiz file using a program is unlikely to look at the comments. Nonetheless, a more refined version of saveFile and the QuizQuestions object might let users add comments and white space to the file, as well as questions. (Obviously, the HTML form would also have to allow for this.)
Our version of saveFile uses the same system for reporting errors as loadFile--by returning a string, while the lack of an error is indicated by returning 0. This lets us use the following code:
$error = $questions->saveFile; &log_and_die($error) if $error;
Now that you have seen the skeleton for create-quizfile.pl, you should have a good understanding of the program shown in Listing 5. This version of create-quizfile.pl is fairly straightforward. It checks to see if the user entered a question; if there is text for a question, it takes the remaining parameters from the HTML form submitted.
Now is a good time to remember that CGI programs that write user-defined strings to your file system are potentially dangerous, and thus must be placed in locations that are restricted to authorized users, either by using your HTTP server's built-in protection or by placing such programs behind a firewall. No matter how unlikely this may seem, a user may eventually discover that you have a program named create-quizfile.pl, and create quizzes on your system, possibly overwriting your creations.
This month, we made our quiz engine friendlier for non-programmers by checking the integrity of the quiz file and by allowing users to create quiz files using HTML forms. What happens when users want to edit quiz files? For now, they are stuck modifying the file on disk, which again opens Pandora's box of potential syntax problems. While we can discover these problems with our simple error-checking code, it might be a good idea to create a program that can edit quiz files as well as create them. Next month, we will modify create-quizfile.pl to do just that, making our quiz system easier for everyone to handle.
Reuven M. Lerner is an Internet and Web consultant living in Haifa, Israel, who has been using the Web since early 1993. In his spare time, he cooks, reads and volunteers with educational projects in his community. He can be reached via e-mail at reuven@netvision.net.il.
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
| Trying to Tame the Tablet | May 08, 2013 |
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Using Salt Stack and Vagrant for Drupal Development
- New Products
- Validate an E-Mail Address with PHP, the Right Way
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- Home, My Backup Data Center
- New Products
- Tech Tip: Really Simple HTTP Server with Python
- RSS Feeds
Enter to Win an Adafruit Prototyping Pi Plate Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Prototyping Pi Plate Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- Next winner announced on 5-21-13!
Free Webinar: Linux Backup and Recovery
Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.
In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.




20 min 50 sec ago
1 hour 49 min ago
2 hours 58 min ago
3 hours 44 min ago
4 hours 5 min ago
10 hours 20 min ago
15 hours 58 min ago
21 hours 58 min ago
22 hours 21 min ago
22 hours 31 min ago