对同一个变量调用 Swift 的 readline 两次会忽略第二次调用

Calling Swift's readline to the same variable twice ignores the second call

我正在从命令行读取用户输入,检查它是否是有效的文件路径,如果不是,则要求用户重试。

如果用户输入的是 nil,则第一次应将其视为任何其他错误输入,让用户输入新值,但第二次输入 nil ,程序应该强制退出。

(我假设 nil 值是用户不会故意输入的值,所以如果它发生两次以上,我假设出现问题并退出程序以避免永无止境的循环要求新的输入。这可能是也可能不是一个好方法,但这不会影响问题。)

问题是 readLine() 在收到行尾输入(产生 nil 值)后第二次调用时不会要求用户输入. (行尾可以用^D输入。)

这意味着 readLine() 自动位于 returns nil 的函数,因为这是接收 readLine().[=34= 的变量的最新值]

问题

  1. 不管接收变量已经有什么值都不应该调用readLine()吗?

  2. 如果是,为什么输入一次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).
}

备注

readLine() returns nil 如果(且仅当)标准输入文件描述符已到达文件末尾。这发生在(例如)读取输入时 来自 tty,并且 Ctrl-D"end-of-transmission character")作为一行中的第一个字符输入。

所有随后的readLine()调用然后return nil也是如此,没有 方式检测 "Ctrl-D was entered twice"。 换句话说,一旦标准输入处于文件结束状态 您无法再从中读取任何数据。如果您的程序需要 更多数据则只能报错,例如

guard let path = readLine(stripNewline: true) else {
    throw InputError.UnexpectedEndOfFile
}