【问题标题】:PHP: i need to examine the words in an input string by user and according to the matchs ouput a responsePHP:我需要检查用户输入字符串中的单词并根据匹配输出响应
【发布时间】:2010-11-26 21:23:16
【问题描述】:

目前我有一个非常简单的自动回复/聊天机器人。为了让它发挥更复杂的作用(如帮助机器人),需要对其进行大量修改。我不是 php 程序员,但我想我知道经过一些研究后需要做什么,我只是不完全理解 php.net 上关于 pregmatch 和 fopen 等的文章。我知道我可以下载现成的帮助机器人,但我的学习曲线在哪里?我也不着急,我喜欢这些小挑战。我在别处问过这个问题,那里的知识分子要么一无所知,要么根本无法被打扰——他们只是不停地告诉我下载一个预制的帮助机器人。

任何帮助将不胜感激,但请不要将我送回 php 手册,因为我已经尝试过使用它。我需要一种全新的方法。

我有一个表格供用户输入(最大长度)50 个字符的文本问题。我认为限制用户可以输入的字符数是一个优势,这样字符串的操作就变得更容易了。 用户提交问题后,需要将其传递给变量。

  1. 我想将字符串中的单词与文件中的单词列表进行比较
  2. 如果文件中不存在这些词,则已将它们添加到其中。
  3. 确定某些关键字(例如:谁;什么;在哪里;何时;如何;为什么;哪个)来分解问题
  4. 识别任何名词以进一步分解问题(名词显然将是一个相当大的列表,我必须手动创建)。
  5. 将结果与响应列表(我将手动创建的另一个列表)进行比较。
  6. 输出最佳匹配响应。

以下代码是基本代码,尚未检查输入字符串中的关键字组合。我已尽我所能对代码进行了注释。

以下是我的responder002.php文件:

/*create the 'question' variable for the users text to be stored in:*/

$question=strtolower($_POST['question']));

/*begin creating the form*/
$ask='<br /><form action="responder002.php" method="POST">Question: <input type="text" name="question">
<input type="submit" value="Ask"></form>';
$answer='<h2>Answer</h2><br />';
/*if the $question variable is empty then ask for input*/
if (empty($question))
{
  print $ask;

  exit;
}
/*otherwise ....*/
else
{

  /*if the variable contains the following strings output to screen the matching response*/
  if ($question=="hello"||$question=="Hello"||$question=="hi"||$question=="Hi"||$question=="G'day"||$question=="hey")
  {
    $answerq="Hello how are you?";
  }
  if ($question=="good"||$question=="good thanks")
  {
    $answerq="Im glad to hear you are good.";
  }
  if ($question=="fine"||$question=="fine thanks") {
    $answerq="Im glad to hear you are fine.";
  }

  echo '<i>You asked me:</i> '.$question.'
    <br />
    <i>I replied:';
  if (empty($answerq)) { 
    echo 'Sorry, I dont know the answer';
  }
  echo '</i>'.$answerq.' '.$ask.;
  exit;
}
echo '</table>';
$h->endpage();
?>

【问题讨论】:

  • 您需要编辑您的问题以解决问题。使用代码101010 按钮同时突出显示这些代码区域以使其正确显示。
  • 我认为/* otherwise ...... */ else { 是我见过的最搞笑的评论。
  • 您的报价不平衡。您在此处打开了一个字符串:echo '&lt;/i&gt;'.$answerq.' '.$ask.';
  • 我很抱歉。带着 4 个孩子的单身父亲,整晚都在从事许多项目。这样做的目的是通过慢慢发展和完善分析用户输入的方法来尝试给用户更准确的答案。一旦我了解了如何将数据传递到文件中的基础知识,与响应文件中的现有数据进行比较,并输出响应,我就可以继续进行实验。
  • 您好 Nick,我想我会帮助您并做一些教学,如果我的介绍性教程过于简单或以某种方式居高临下,我们深表歉意,这不是本意。我不知道你的水平,只是从你现有的代码中猜测。看看有没有帮助。

标签: php string fopen bots


【解决方案1】:

这让我想起了很多个月前我刚开始编程时所做的很多事情。除了我开始问数学问题。编写ELIZA 类型的程序对于初学者来说是一项艰巨的任务!

显然,您现在还不想编写一个获奖的聊天界面,我希望不会,因为这是一项庞大的研究级任务。但我会尝试提供一些 PHP 示例,向您展示如何完成您希望采取的一些步骤,并让您清楚地了解您已采取的步骤。

教程很长,请做好准备……

首先让我们清理现有代码。

我从该文件的最后一行假设您正在使用某种 HTML 生成器,还是尝试使用? $h-&gt;endpage();,这实际上从未被使用过,因为您经常使用exit;,这终止脚本出现在它的位置。除非您希望程序在该点结束,否则您不需要在 if 块的末尾使用它。程序将在右大括号} 之后继续执行下一条语句。

我看到您在代码中经常使用echoprint。将变量写入 HTML 页面需要echo,但有更好的方法来处理将代码和 HTML 分开的主 HTML 页面,这样您就可以在两者上都做得更干净。开始和结束您的 PHP 页面的标签 &lt;?php ?&gt; 可以在页面中的任何位置使用以“插入”和“中断”代码。括号内,PHP,外,HTML。

例如。

<?php
// This is my PHP program

// read the question variable from the Form data
// the form was "post"ed, so we check $_POST
// $_POST is an array (a list) of all the variables sent by the form

$question = strtolower($_POST['question']);

if (empty($question)) {
  // no question, close PHP and start HTML, show the form
?>
<form action="responder002.php" method="POST">
    Question: <input type="text" name="question"> <input type="submit" value="Ask">
</form>
<?php
// back in PHP, if the question was not empty deal with the question
} else {
  // try and find an answer
  if ($question == 'hello' || $question == 'hi') {
    // hello-type question found
    $answerp = "Hello, how are you?";
  } else if ($question == "fine" || $question == "fine thanks") {
    // or a fine-type question
    $answerq = "I am glad to hear you are fine.";
  } else {
    // "else" on its own, no question identified so we do not know
    $answerp = "Sorry, I do not know the answer.";
  }

  // close PHP and display the answer
  // note: opening and closing PHP briefly where we want a variable
  //       using "echo" to output the variable contents
?>
<h2>Answer</h2>

<p><i>You asked me:</i> <?php echo $question; ?></p>
<p><i>I replied:</i> <?php echo $answerp; ?></p>
<?php
  // close the else opening bracket from above
}
// and we are done, close PHP
?>

一旦我们掌握了这种提问和回答的基本方法,我们就可以继续让它变得更加充实。

您说您想存储已看到的单词列表,并在出现新单词时继续添加。大概这样您就可以手动查看被问到的内容并编写新答案;还是你有其他动机?

无论您如何存储数据,如果您正在检查并添加数据,它就是一个数据库。您可以使用文本文件来存储数据,如果您可以决定方法,或者如果数据很复杂,大多数程序员都希望有一个合适的数据库系统,可以轻松存储包含许多字段的记录。

暂时让我们假设您要使用文本文件。

步骤阶段是决定如何存储单词,我的建议是保持简单,每行一个单词。

鉴于我们希望每行一个单词,读取文件的方法有很多种,如果使用file() 命令,这可能是最方便和最简单的方法。

$words = file("words.txt", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

此命令读取整个words.txt,跳过任何空行并且不存储任何行结尾(文件中的每一行都以换行符或字符结尾,将忽略换行选项传递给函数告诉PHP不要保留这些。

$words 现在是文件中每一行的数组,按照它们在文件中出现的顺序排列。

要检查一个单词是否已经在文件中,我们可以使用in_array() 函数,我们想知道我们正在检查的单词是否不在文件中。所以我们可以说:

if (!in_array($currentWord, $words)) {
    // add $currentWord to file
}

! 字符表示不是。那么我们如何将单词添加到文件中呢?好吧,还有另一个函数叫做file_put_contents()(如果你使用的是比v5更早的PHP版本,那么这个函数不存在,告诉我,我会告诉你更旧的更复杂的方法)。 file_put_contents() 要求我们在每个单词后面加上换行符来结束行,所以我们将"\n" 连接到每个单词。

if (!in_array($currentWord, $words)) {
    file_put_contents("words.txt", $currentWord . "\n", FILE_APPEND | LOCK_EX);
}

标志FILE_APPENDLOCK_EX 告诉函数在最后附加到文件,而不是从头重新创建文件并在这样做时独占锁定文件,这样其他人就不能写入文件在我们这样做的时候。

现在这对一个词来说很好,$currentWord,但是我们如何遍历问题中的每个词呢?

第一步是将问题分解为单词。有几种方法可以做到这一点,但用于此目的的简单命令是explode()

explode() 获取一行或文本块,并使用您指定的分隔符将其拆分为单个片段的列表(数组)。

$questionWords = explode(" ", $question);

假设每个单词用空格分隔,这将返回一个单词数组。 explode() 是一个简单的函数,并在每个空格处拆分,因此如果您有两个空格,它会将其拆分并说您在空格之间有一个空字符串。 explode("-", "hello--world")(使用破折号作为空格)会给出一个列表 ('hello', '', 'world') 例如,因为双破折号。为了去掉空的“词”,我们可以在explode上加一个过滤器,这样空的词就会被删除。

$questionWords = array_filter(explode(" ", $question));

现在我们有了问题中的单词列表,我们如何将它与单词文件的读取和新单词的存储放在一起?有一个循环。

$words = file("words.txt", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

$questionWords = array_filter(explode(" ", $question));

foreach ($questionWords as $currentWord) {
    if (!in_array($currentWord, $words)) {
        file_put_contents("words.txt", $currentWord . "\n", FILE_APPEND | LOCK_EX);
    }
}

foreach 循环遍历$questionWords 中的每个单词,每次通过大括号之间的代码设置变量$currentWord

这可行,但效率非常低,因为必须为每个新单词打开、写入和关闭文件。最好把生词列个清单,一次性全部加进去。为此,我们创建了一个新词的空数组(列表),并在找到新词时向其中添加新词。

$words = file("words.txt", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

$questionWords = array_filter(explode(" ", $question));

$newWords = array();
foreach ($questionWords as $currentWord) {
    if (!in_array($currentWord, $words)) {
        // add new word to $newWords
        $newWords[] = $currentWord;
    }
}

// write all the new words at once
file_put_contents("words.txt", implode("\n", $newWords), FILE_APPEND | LOCK_EX);

通过获取$newWords 中的列表并执行与explode() 相反的操作,将新单词一次性添加,将一行分解为单个单词,我们将implode() 单词列表合并为单个单词一段文字,每个单词用换行符分隔"\n"

我认为这足以暂时吸收,仔细阅读,熟悉概念,如果您想继续,请告诉我。

【讨论】:

  • @Orbling:太棒了!很好解释。很遗憾,我必须有 15 名声望才能对您的回复进行投票。是的,我的 PHP 水平或多或少是“初学者”——我已经玩了一段时间的 PHP sn-ps,并从各种教程(具有安全性)和联系人列表中成功完成了 PHP/MySQL 登录系统。我使用 PHP 作为我的网站模板,我对 HTML/CSS 很好。我在这里也使用 XAMPP 作为开发服务器。我已经有几个问题了,但我会等下一课,看看里面有什么。感谢您分享你的知识。干杯!
  • @Nick 如果你接受答案,点击勾选,总比投票好,因为这是你的问题。
  • @Nick 你明白了吗?如果你让它工作,请告诉我,我会添加关于如何使用相同的功能来做你想要的关键字/名词的答案。
  • 是的。就像一个令人讨厌的海绵一样,我已经准备好吸收更多信息了,哈哈!如果我点击勾号,它会关闭主题吗?
  • 不,问题仍然未解决 - 但已回答时显示为绿色。因此,如果您想要更多,请务必推迟。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-15
  • 1970-01-01
  • 2016-10-11
  • 1970-01-01
  • 1970-01-01
  • 2021-01-03
  • 1970-01-01
相关资源
最近更新 更多