Rob
Rob

Reputation: 45

PHP - Parsing a *.TXT File

I have a text file that has the info below:

1. What color is the water?
Red
*Blue
Green
Orange

2. Stack Overflow is awesome.
*True
False

3. Explain why you love code:

I'd like for the output to be something like this:

MC What color is the water? Red Incorrect Blue Correct Green Incorrect Orange Incorrect
TF Stack Overflow is awesome. True
ES Explain why you love code:

The * in question 1 and 2 symbolize the correct answer. Basically I'm trying to create PHP code that can identify the type of question and tag it with either MC for multiple choice, TF for True/False, and ES for essay.. I'm not sure how to approach this. Any assistance would be greatly appreciated.

Upvotes: 0

Views: 360

Answers (3)

zedfoxus
zedfoxus

Reputation: 37059

Here's a little more description as to how you could do it along with some code that you can modify. Note that this is not a production grade code.

Theory

  • Read file line by line
  • If line begins with (i.e. matches) digits followed by dot followed by space, remember the question in an array as a key
  • If line does not match, remember each line in an answers array
  • When we hit the next line that matches, associated all the answers collected so far to the prior question
  • After looping is done, we may still have an array full of answers. If we do, associate it with the last question we read

At this point we have our quiz questions and answers populated as an associated array that looks like this:

Array
(
    [1. What color is the water?] => Array
        (
            [0] => Red
            [1] => *Blue
            [2] => Green
            [3] => Orange
        )

    [2. Stack Overflow is awesome.] => Array
        (
            [0] => *True
            [1] => False
        )

    [3. Explain why you love code:] =>
)

Now we loop through the questions and get whether the answer are of type ES, TF or MC. We also format the answers nicely. And then display it.

Practice

Create a function that reads a file and creates this kind of array for us.

/**
 * Get questions and answers from file
 *
 * @param $filename string Name of the file along with relative or absolute path
 *
 * @returns array Associated array of 'question1'=>array-of-answers, 'question2'=>array2-of-answers
 */
function getQuestionsAndAnswers($filename)
{
    $file = @fopen($filename, 'r');

    $quiz = array();        // associated array containing '1. question1'=>answer array
    $answers = array();     // temporarily holds answers
    $question = '';         // temporarily holds questions

    while (($line = fgets($file)) != null) 
    {
        $line = trim($line);
        if ($line === '') continue;

        if (preg_match('/^\d+\. /', $line) === 1) 
        {
            if (count($answers) > 0) 
            {
                $quiz[$question] = $answers;
                $answers = array();
            }
            $question = $line;
            $quiz[$question] = '';
        } 
        else 
        {
            $answers[] = $line;
        }
    }

    if (count($answers) > 0)
    {
        $quiz[$question] = $answers;    
    }

    return $quiz;
}

Create a function that takes answers and tells us what type of answer that is.

/**
 * Get answer type short code from answer array
 *
 * @param $answer array Answers
 *
 * @returns string Short code answer type (e.g. ES for Essay, TF for True/False, MC for multiple choice)
 */
function answerType($answer) 
{
    if (!is_array($answer)) return 'ES';
    $flattenedAnswer = implode(',', $answer); 
    if (stripos($flattenedAnswer, 'true') !== false) return 'TF';
    return 'MC';
}

Create a function that formats our answers nicely

/**
 * Format answers based on answer type
 *
 * @param $answer array      Answers
 * @param $answerType string Short code of answer type
 *
 * @returns string Formatted answer
 */
function answers($answer, $answerType)
{
    if ($answerType === 'ES') return $answer;

    if ($answerType === 'TF') 
    {
        foreach ($answer as $x)
        {
            if (strpos($x, '*') === 0) return substr($x, 1);
        }
        return '';
    }

    $flattenedAnswer = '';
    foreach ($answer as $x) 
    {
        if (strpos($x, '*') === 0)
        {
            $flattenedAnswer .= ' ' . substr($x, 1) . ' Correct';
        }
        else
        {
            $flattenedAnswer .= " $x Incorrect";
        }
    }
    return $flattenedAnswer;
}

Now that we have our foundational pieces, let's put it all together.

// $quiz will be populated as an array that looks like this
// 'question1'=>array('answer1', 'answer2')
// 'question2'=>array('answer1', 'answer2') etc
$quiz = getQuestionsAndAnswers('./questions.txt');

// loop through all questions and use functions to format the output
foreach ($quiz as $question=>$answer)
{
    $answerType = answerType($answer);
    echo sprintf("%s %s %s\n",
        $answerType,
        $question,
        answers($answer, $answerType)
    );
}

Let's run the code and see the output:

$ php questions.php
MC 1. What color is the water?  Red Incorrect Blue Correct Green Incorrect Orange Incorrect
TF 2. Stack Overflow is awesome. True
ES 3. Explain why you love code:

Great. Looks like it all worked out well. I hope the code is self commented, but if you have questions, feel free to ask.

Upvotes: 1

Rob Walker
Rob Walker

Reputation: 11

Ideally, it should be in a database with two tables question and answers where the relation is question number. You can use file_get_contents() but, there is a lot of coding needed. If you want to use a flat file, you should plan to use: delimited format where each question is divide by ":" (for example) and each parts of the question divided by "," and each answer divide by ";" with the first answer is the correct one and file_get_contents() to load the text file and explode() divide the question, parts, and answers into arrays and use "for" statement to loop each array. eg. What color is the water?,Blue;Red;Green;Orange:Stack Overflow is awesome.,True;False:Explain why you love code:

Upvotes: 0

Elias Nicolas
Elias Nicolas

Reputation: 775

To answer your question; you could use .ini files, instead of .txt files. Check this parse_ini_file it return an array. Or if you really need .txt you could use file_get_contents (it return a string)...

Or you could try; a database. Which is better.

Upvotes: 1

Related Questions