我从命令行读取用户输入,检查它是否是有效的文件路径,并且 - 如果它没有要求用户重试。
如果用户输入为nil
,则应首次将其视为任何其他错误输入,让用户输入新值,但第二次输入nil
时,程序应该强制退出。
(我假设nil
值是用户不会故意进入的,所以如果它发生了两次以上,我会假设出错了并退出程序以避免永无止境的循环要求新的输入。这可能是也可能不是一个好方法,但这不会影响问题。)
问题是readLine()
如果收到了行结束输入(产生nil
值),则第二次调用后不会要求用户输入。 (可以用^ D输入行尾。)
这意味着readLine()
所在的函数会自动返回nil
,因为这是接收readLine()
的变量的最新值。
问题
无论接收变量已有多少值,都不应该readLine()
被调用?
如果是这样,为什么用户在输入nil
一次后才要求输入?
这是代码:
import Foundation
/**
Ask the user to provide a word list file, check if the file exists. If it doesn't exist, ask the user again.
*/
func askUserForWordList() -> String? {
print("")
print("Please drag a word list file here (or enter its path manually), to use as basis for the statistics:")
var path = readLine(stripNewline: true) // THIS IS SKIPPED IF "PATH" IS ALREADY "NIL".
return path
}
/**
Check the user input // PROBABLY NOT RELEVANT FOR THIS QUESTION
*/
func fileExists(filePath: String) -> Bool {
let fileManager = NSFileManager.defaultManager()
if fileManager.fileExistsAtPath(filePath) {
return true
} else {
return false
}
}
/**
Get the file from the user and make sure it’s valid.
*/
func getFilePathFromUser() throws -> String {
enum inputError: ErrorType {
case TwoConsecutiveEndOfFiles
}
var correctFile = false
var path: String? = ""
var numberOfConsecutiveNilFiles = 0
repeat {
// Check that the user did not enter a nil-value (end-of-file) – if they did so two times in a row, terminate the program as this might be some kind of error (so that we don't get an infinite loop).
if numberOfConsecutiveNilFiles > 1 { // FIXME: entering ^D once is enough to end the program (it should require two ^D). Actually the problem seems to be in function "askUserForWordList()".
throw inputError.TwoConsecutiveEndOfFiles
}
path = askUserForWordList()
if path == nil {
numberOfConsecutiveNilFiles += 1
} else {
numberOfConsecutiveNilFiles = 0
correctFile = fileExists(path!)
if !correctFile {
print("")
print("Oops, I couldn't recognize that file path. Please try again.")
}
}
} while !correctFile
return path!
}
// This is where the actual execution starts
print("")
print("=== Welcome to \"Word Statistics\", command line version ===")
print("")
print("This program will give you some statistics for the list of words you provide.")
do {
let path = try getFilePathFromUser()
} catch {
print("Error: \(error)")
exit(-46) // Using closest error type from http://www.swiftview.com/tech/exitcodes.htm (which may not be standard at all. I could, however, not find any "standard" list of exit values).
}
备注
path
函数中的原始askUserForWordList()
被声明为常量(let path = readLine(stripNewline: true)
),但我将其更改为var
,因为它应该在每次函数更新时更新调用。但是,这并不影响该计划的运作方式。path
之前尝试单独声明readLine()
,这没有任何区别。path
变量,让askUserForWordList()
函数直接返回readLine()
结果(return readLine(stripNewline: true)
)。这没什么区别。我一起跳过了askUserForWordList()
函数,并将要求用户输入的代码移动到函数" getFilePathFromUser()"的“主要”代码中,但是没有'改变任何事情。
修改后的代码:
func getFilePathFromUser() throws -> String {
enum inputError: ErrorType {
case TwoConsecutiveEndOfFiles
}
var correctFile = false
var path: String? = ""
var numberOfConsecutiveNilFiles = 0
repeat {
// Check that the user did not enter a nil-value (end-of-file) – if they did so two times in a row, terminate the program as this might be some kind of error (so that we don't get an infinite loop).
if numberOfConsecutiveNilFiles > 1 { // FIXME: entering ^D once is enough to end the program (it should require two ^D). Actually the problem seems to be in function "askUserForWordList()".
throw inputError.TwoConsecutiveEndOfFiles
}
// MODIFIED – This code was previously located in "askUserForWordList()"
print("")
print("Please drag a word list file here (or enter its path manually), to use as basis for the statistics:")
path = readLine(stripNewline: true)
// END OF MODIFICATION
if path == nil {
numberOfConsecutiveNilFiles += 1
} else {
numberOfConsecutiveNilFiles = 0
correctFile = fileExists(path!)
if !correctFile {
print("")
print("Oops, I couldn't recognize that file path. Please try again.")
}
}
} while !correctFile
return path!
}
答案 0 :(得分:1)
readLine()
将返回nil
。在读取输入时会发生这种情况(例如)
从tty开始,Ctrl-D
("end-of-transmission character")作为第一个字符输入。
所有后续readLine()
次调用都会返回nil
,但没有
方式检测" Ctrl-D输入两次"。
换句话说,一旦标准输入处于文件结束条件
你不能再读取它的任何数据了。如果您的程序需要
如果您有更多数据,则只能报告错误,例如
guard let path = readLine(stripNewline: true) else {
throw InputError.UnexpectedEndOfFile
}