Je lis l'entrée de l'utilisateur à partir de la ligne de commande, vérifie s'il s'agit d'un chemin de fichier valide et, si ce n'est pas le cas, demande à l'utilisateur de réessayer. Dans le cas où l'entrée de l'utilisateur est nil
, il doit être traité comme toute autre entrée incorrecte la première fois, en laissant l'utilisateur entrer une nouvelle valeur, mais la deuxième fois que nil
est entré, le programme devrait forcer quitter.Appeler la ligne readline de Swift à la même variable ignore le deuxième appel
(Je suppose qu'une valeur nil
est quelque chose qu'un utilisateur n'entrera pas intentionnellement, donc si cela arrive plus de deux fois je suppose que quelque chose s'est mal passé et quitte le programme pour éviter une boucle sans fin demandant une nouvelle entrée. Cela peut ou peut ne pas être un bon moyen de le faire mais cela n'affecte pas la question.)
Le problème est que readLine()
ne demande pas l'entrée de l'utilisateur la deuxième fois il est appelé après s'il a reçu un entrée de fin de ligne (qui donne la valeur nil
). (Fin de ligne peut être entrée avec^D.)
Cela signifie que la fonction où readLine()
se trouve revient automatiquement nil
parce que c'est la dernière valeur de la variable qui reçoit le readLine()
.
Questions
ne devraient
readLine()
être appelés, peu importe quelle valeur la variable récepteur a déjà?Si oui, pourquoi l'utilisateur n'a-t-il pas été invité à entrer
nil
lorsqu'il a été entré une fois?
Voici le code:
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).
}
Remarques
- Lorsque vous entrez dans un autre chemin non valide (toute chaîne, même un vide (presser la touche Entrée), la boucle fonctionne comme prévu
- À l'origine
path
dans la fonctionaskUserForWordList()
a été déclaré comme consta nt (let path = readLine(stripNewline: true)
) mais je l'ai changé envar
car il est censé être mis à jour chaque fois que la fonction est appelée. Cependant, cela n'a pas affecté le fonctionnement du programme. - J'ai essayé de déclarer
path
séparément sur la ligne avant d'appelerreadLine()
, ce qui n'a fait aucune différence. - J'ai essayé d'ignorer complètement la variable
path
et de laisser la fonctionaskUserForWordList()
renvoyer le résultatreadLine()
directement (return readLine(stripNewline: true)
). Cela n'a fait aucune différence. J'ai ignoré la fonction
askUserForWordList()
tous ensemble et déplacé le code demandant l'entrée de l'utilisateur dans le code "principal" de la fonction "getFilePathFromUser()", mais cela n'a rien changé.Code mise à jour:
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! }
En ce qui concerne la 'sortie (-46)', les codes de sortie rapide sont les mêmes que dans C, de sorte que les seules valeurs "standard" sont 0 ('EXIT_SUCCESS') et 1 (' EXIT_FAILURE'). Si vous avez l'intention de quitter de toute façon, je suggère d'utiliser 'fatalError()' à la place, car il affiche le fichier et le numéro de ligne du plantage d'origine qui facilite le débogage. – xoudini