如何在sml中从文本文件中获取随机行?如何在sml中制作多选题程序



我想在SML.中制作一个多选题程序

我有一个文本文件,其内容结构如下:

category1:Basic sml/sql
1-How many subsets does the power set of an empty set have?
A) One
B) Two
C) Three
D) Zero
Ans:A
2-What is the cardinality of the set of odd positive integers less than 10? 
A) 20 
B) 3 
C) 5 
D) 10 
Ans:C

每个类别有5个以上的问题

每个问题都属于一个类别

对于每个问题,有4个建议的答案,然后是另一行上的答案

我希望能够检索并向用户显示问题(随机问题(和相应的建议答案。我已经编写了这个函数,它允许我逐行检索文件的所有内容。但我仍然纠结于如何卸载问答块。

fun getFromFile(file_name) =
let 
val file = TextIO.openIn file_name
val text = TextIO.inputAll file
val _ = TextIO.closeIn file
in
String.tokens (fn c => c = #"n") text
end

val table = getFromFile("question_file.txt");

我该如何继续?是否可以在不首先通过表的情况下检索文件的行(直接检索文本(?

我仍然纠结于如何卸载问答块。

我该如何继续?

找到一种方法来对包含多个问题的多个类别进行编码,每个问题包含多个答案。一旦你找到了将其存储到文件(文件格式(中的方法,就编写一个解码器。您当前的解码器是线路解码器。您可以使用行对事物中的事物进行编码,但也可以通过其他方式进行编码。

例如,使用JSON:

[
{
"category": "Basic sml/sql",
"questions": [
{
"question": "How many subsets does the power set of an empty set have?",
"answers": [
{ "answer": "Zero", "correct": false },
{ "answer": "One", "correct": true },
{ "answer": "Two", "correct": false },
{ "answer": "Three", "correct": false }
]
},
...
]
},
...
]

如果依赖第三方库似乎太难了,你可以自己想出一种文件格式,例如基于行的格式:

CATEGORY Basic sml/sql
QUESTION How many subsets does the power set of an empty set have?
ANSWER Zero
ANSWER_CORRECT One
ANSWER Two
ANSWER Three
QUESTION ...

因此,给你的基于行的阅读器,在每一行上循环,看看第一个词:

  1. 如果是CATEGORY,则启动一个新类别
  2. 如果是QUESTION,则在当前类别中开始一个新问题
  3. 如果是ANSWERANSWER_CORRECT,请在当前类别中的当前问题中提供一个选项

这建议使用一个递归函数(因为它需要遍历每一行(,该函数包含许多参数:当前类别、当前问题以及迄今为止的类别、问题和答案的集合。

在这一点上,你可能需要思考:我如何在记忆中存储具有多个答案的问题类别?我应该使用什么数据类型?例如,使用类型别名,您可以这样表达您的数据模型:

type answer_option = string * bool
val example_answer_option = ("Zero", false) : answer_option
type question_answers = string * answer_option list
val example_question_answers =
("How many subsets does the power set of an empty set have?",
[
("Zero", false),
("One", true),
("Two", false),
("Three", false)
]
) : question_answers
type category = string * question_answers list
val example_category =
("Basic sml/sql",
[ example_question_answers ]
) : category
val example_categories = [ example_category ] : category list

SML类型别名的工作方式是,您将所有这些别名扩展到它们所组成的基元类型中,因此它们可能会显示在REPL中,如下所示:

> type answer_option = string * bool
type question_answers = string * (string * bool) list
type category = string * (string * (string * bool) list) list

其可读性相当低并且是使用诸如datatypeabstype或不透明模块之类的替代方案的原因之一。

然而,接下来,您可以定义一个存根,如:

fun parse (line::lines, currentQuestion, currentAnswers, currentCategory, acc) =
case splitFirstWord line of
("CATEGORY", cat)          => ...
| ("QUESTION", q)            => ...
| ("ANSWER", aWrong)         => ...
| ("ANSWER_CORRECT", aRight) => ...
| _                          => raise Fail ("Unknown: " ^ line)

现在有两个子问题:

  1. splitFirstWord实际上并不存在。

  2. 有很多关于当前状态的书籍。

祝你好运!

是否可以在不首先通过表的情况下检索文件的行(直接检索文本(?

我真的不明白这个问题。毫无疑问,是吗?

如果通过";表";你指的是某种可索引的数据结构,比如列表:

只是不要在输入上调用String.tokens (fn c => ...)

这为您提供了一个基本的string

请注意,table只是一个值绑定的名称。

如果你愿意,你可以通过chair来代替:

fun getFromFile(file_name) =
let 
val file = TextIO.openIn file_name
val text = TextIO.inputAll file
val _ = TextIO.closeIn file
in
text
end
val chair = getFromFile "question_file.txt"

还要注意,函数参数周围的括号在SML中是不必要的。事实上,如果你认为它们是必要的,你可能很快就会犯语法错误。为了更清晰,尽量避免使用多余的语法。

相关内容

  • 没有找到相关文章

最新更新