【发布时间】:2016-07-17 20:25:18
【问题描述】:
我正在从命令行读取用户输入,检查它是否是有效的文件路径,如果不是,请用户再试一次。
如果用户输入的是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).
}
备注
- 当输入任何其他无效路径(任何字符串,甚至是空的(只需按 Enter))时,循环将按预期工作。
- 最初
askUserForWordList()函数中的path被声明为常量(let path = readLine(stripNewline: true)),但我将其更改为var,因为它应该在每次调用函数时更新。不过,这并不影响程序的运行方式。 - 我尝试在调用
readLine()之前在行上单独声明path,没有任何区别。 - 我尝试完全跳过
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! }
【问题讨论】:
-
关于
exit(-46),Swift 退出代码与 C 中的相同,因此唯一的“标准”值是 0 (EXIT_SUCCESS) 和 1 (EXIT_FAILURE)。如果您仍然打算退出,我建议改用fatalError(),因为它会输出原始崩溃的文件和行号,这有助于调试。
标签: swift null variable-assignment readline