dongliang1654 2010-11-26 21:23
浏览 42
已采纳

PHP:我需要按用户检查输入字符串中的单词,并根据匹配输出响应

At the moment I have a very simple autoresponder/chatbot. To get it to play a more complex role (like a help bot) it needs to be heavily modified. I'm not a php programmer but I think I know what needs to be done after a little research, I just don't understand fully the articles on pregmatch and fopen etc at php.net. I know I can download a readymade helpbot but where is the learning curve for me in that? i'm not in a hurry either and I enjoy these little challenges. I have asked this question elsewhere and the knowitalls there either knew nothing or simply couldn't be bothered - they just kept telling me to download a prefab helpbot.

Any help would be greatly appreciated but please don't send me back to the php manuals because I have already tried to work with that. I need a fresh approach.

I have a form for users to input a (maxlength) 50 character text question. I think it would be an advantage to limit the number of characters a user can input so that the manipulation of the strings becomes easier. Once the user submits the question it needs to be passed to a variable.

  1. I want to compare the words in the string with a list of words in a file
  2. then if the words don't exist in the file already ad them to it.
  3. identify certain keywords (eg: who;what;where;when;how;why;which) to break down the question
  4. identify any nouns to further breakdown the question (the nouns obviously will be a rather large list that i will have to manually create).
  5. compare the results with a list of responses (another list I will manually create).
  6. output the best matching response.

The following code is basic and doesn't yet check the input string for combinations of keywords. I've commented the code as best as I can understand it.

The following is my responder002.php file:

/*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();
?>
  • 写回答

1条回答 默认 最新

  • duanfa2014 2010-11-27 22:48
    关注

    Well this reminds me a lot of stuff I did many moons ago when I first started programming. Except I started off asking maths questions. Writing an ELIZA type program is quite an undertaking for a beginner!

    Obviously you are not looking to write an award winning chat interface just yet, well I hope not, as that is a massive research level undertaking. But I will try and give a few PHP examples that show you how to accomplish a few of the steps you wish to take and a bit of clarity on the steps you have taken.

    A long tutorial, brace yourself...

    First lets clean up the existing code.

    I assume from the last line of that file you are using some sort of HTML generator, or trying to? $h->endpage();, this is never actually being used as you use exit; frequently which terminates the script at the point where it is present. You do not need to use that at the end of an if-block unless you wish the program to end at that point. The program will continue after the closing brace } to the next statement.

    I see you are using echo and print in your code a lot. echo is needed for writing variables to the HTML page, but there are better ways to do the primary HTML page that separate the code and the HTML, so you can make a cleaner job at both. The tags that start and finish your PHP page, <?php ?>, can be used anywhere in the page to "break-in" and "break-out" of code. Inside the brackets, PHP, outside, HTML.

    eg.

    <?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
    ?>
    

    Once we have this basic method of taking a question and answering, then we can move on to making it more substantial.

    You say you want to store a list of words that have been seen, and keep adding to it when new words come up. Presumably so you can manually look at what is being asked and write new answers; or do you have another motivation?

    However you store data, if you are inspecting it and adding to it, it is a database of sorts. You can use a text file to store data in, if you can decide on a method, or if the data is complex most programmers would like a proper database system where records comprising many fields can be stored easily.

    For the moment let us assume you want to use text files.

    The step stage is deciding how you will store the words, my advice to keep things simple is one word per line.

    There are many ways of reading files, given that we want one word per line, perhaps the most convenient and simple method if the file() command.

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

    This command reads in the whole of words.txt, skipping any empty lines and not storing any of the line endings (each line in a file ends with a newline character or characters, passing the ignore new line option to the function tells PHP not to keep these.

    $words is now an array of every line in the file, a list in the order they appear in the file.

    To check if a word is already in a file, we can use the in_array() function, we want to know if the word we are inspecting is not in the file. So we can say:

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

    The ! character means not. So how do we add the word to the file? Well there is another function called file_put_contents() (if you are using a PHP version older than v5 then this function does not exist, tell me and I will show you the older more complicated method). file_put_contents() requires us to put the newline character after each word to end the line, so we concatenate " " to each word.

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

    The flags FILE_APPEND and LOCK_EX tell the function to append to the file at the end, not recreate the file from the beginning and lock the file exclusively whilst doing so, so that no one else can write to the file while we are doing so.

    Now this is all very well for one word, $currentWord, but how do we go through each word in the question?

    First step is to split the question up in to words. There are a few ways of doing this, but the simplistic command for the purpose is explode().

    explode() takes a line or block of text and splits it up using a separator you specify in to a list (array) of individual pieces.

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

    Assuming each word is separated with a space, this will return an array of words. explode() is a simple function and splits at every space, so if you have two spaces together it will split that up and say you have an empty string between the spaces. explode("-", "hello--world") (using dashes for spaces) would give a list ('hello', '', 'world') for instance, because of the double dash. To get rid of empty "words", we can put a filter on the explode, so that empty entries are removed.

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

    Now we have our list of words from the question, how do we put it together with the reading of the word file and storing of the new words? With a loop.

    $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 . "
    ", FILE_APPEND | LOCK_EX);
        }
    }
    

    foreach loops through each word in $questionWords setting the variable $currentWord each time through the code between the braces.

    This would work, but is very inefficient as the file has to be opened, written to and closed for each new word. It would be better to make a list of new words and add them all at once. To do this we create an empty array (list) of new words, and add new words to it when we find them.

    $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("
    ", $newWords), FILE_APPEND | LOCK_EX);
    

    The new words are added all at once by taking the list in $newWords and doing the opposite of explode(), which broke a line down in to individual words, we implode() the list of words in to a single piece of text, each word separated with a newline " ".

    I think this is enough to take in for the moment, read through it carefully, familiarise yourself with the concepts and let me know if you want to proceed.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 mmocr的训练错误,结果全为0
  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀