PHP - Как избежать замены строки замены - PullRequest
1 голос
/ 11 мая 2019

Я работаю над сценарием, который позволяет студентам вводить свои ответы в форму и дает им мгновенную обратную связь по своим ответам.

Я начинаю со строки ($ content), которая содержит завершенную задачу с пробелами в квадратных скобках, примерно так:

There's [somebody] in the room. There isn't [anybody] in the room. Is [anybody] in the room?

Теперь скрипт распознает решения (кто-нибудь, кто-нибудь, кто-нибудь) и сохраняет их в массиве. Ответы студента также в массиве.

Чтобы проверить, верен ли ответ, скрипт проверяет, идентичны ли $ input [$ i] и $ solution [$ i].

Теперь вот проблема: я хочу, чтобы скрипт заменил заполнители на поле ввода, где решение неверное, и решение зеленым, если оно правильное. Эта обновленная версия $ content будет показана на следующей странице. Но если есть два идентичных решения, это приводит к множественным заменам, поскольку замена заменяется снова ...

Я пробовал preg_replace с лимитом 1, но это тоже не помогает, так как не пропускает решения, которые уже были заменены.


$i=0;

while ($solution[$i]){

//answer correct
    if($solution[$i] == $input[$i]){ 

        //replace placeholder > green solution     
            $content = str_replace($solution[$i], $solution_green[$i], $content);  
    }

//answer wrong
    else{ 

        //replace placeholder > input box to try again  
             $content = str_replace($solution[$i], $solution_box[$i], $content);  

    }
    $i++;
}

print $content;  //Output new form based on student's answer

Есть ли способ избежать замены замен?

Надеюсь, я не слишком много болтал ... Я долго ломал голову над этой проблемой и был бы рад любым советам.

Ответы [ 2 ]

0 голосов
/ 12 мая 2019

Вы можете использовать функцию sprintf() / vsrpintf() для замены позиционных заполнителей, но сначала вам необходимо подготовить шаблон предложения для нее. Каждый «заполнитель решения» должен быть заменен на %s, чтобы позже sprintf() мог заменить каждого соответствующей строкой.

Вы можете сделать это в цикле:

$fields = [];
while (isset($solution[$i])) {
    $fields[] = ($solution[$i] === $input[$i])
        ? $solution_green[$i]
        : $solution_box[$i];

    //doesn't matter if you replace more than one here
    $content = str_replace($solution[$i], '%s', $content);
    $i++;
}

print vsprintf($content, $fields);
//or for php>=5.6: sprintf($content, ...$fields);

Это простое решение для текущего состояния вашего кода. Он может быть реорганизован (замена шаблона при синтаксическом анализе правильных слов, массивы green / box могут быть заменены методами получения нужной вам строки и т. Д.)

0 голосов
/ 11 мая 2019

То, как я подошел к этому, состоит в том, чтобы разбить исходное содержимое на сегменты, которые относятся к маркерам в тексте. Итак, вы explode() исходный текст ], в итоге вы ...

Array
(
    [0] => There's [somebody
    [1] =>  in the room. There isn't [anybody
    [2] =>  in the room.
Is [anybody
    [3] =>  in the room?
)

Как видите, каждый элемент массива теперь соответствует номерам ответа / решения. Поэтому при замене текста вместо него меняется $parts[$i]. Также в качестве гарантии он заменяет [text, чтобы убедиться, что есть и другие решения, но это должно сработать.

В конце код перестраивает исходный контент, используя implode() и ], чтобы добавить его обратно.

$parts = explode("]", $content);
$i=0;

while (isset($solution[$i])){
    //answer correct
    if($solution[$i] == $input[$i]){
        //replace placeholder > green solution
        $parts[$i] = str_replace("[".$solution[$i], "[".$solution_green[$i], $parts[$i]);
    }
    //answer wrong
    else{
        //replace placeholder > input box to try again
        $parts[$i] = str_replace("[".$solution[$i], "[".$solution_box[$i], $parts[$i]);
    }
    $i++;
}
$content = implode( "]", $parts);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...