J'essaie d'obtenir la saisie du clavier pour une application en ligne de commande pour le nouveau langage de programmation Swift d'Apple.
J'ai scanné les documents en vain.
import Foundation
println("What is your name?")
???
Des idées ?
J'essaie d'obtenir la saisie du clavier pour une application en ligne de commande pour le nouveau langage de programmation Swift d'Apple.
J'ai scanné les documents en vain.
import Foundation
println("What is your name?")
???
Des idées ?
J'ai réussi à le comprendre sans descendre en C :
Ma solution est la suivante :
func input() -> String {
var keyboard = NSFileHandle.fileHandleWithStandardInput()
var inputData = keyboard.availableData
return NSString(data: inputData, encoding:NSUTF8StringEncoding)!
}
Les versions plus récentes de Xcode nécessitent un typecast explicite (fonctionne dans Xcode 6.4) :
func input() -> String {
var keyboard = NSFileHandle.fileHandleWithStandardInput()
var inputData = keyboard.availableData
return NSString(data: inputData, encoding:NSUTF8StringEncoding)! as String
}
J'aime bien ça, et on peut aussi le comprimer en une seule ligne si on ne veut pas définir une fonction, par exemple si on n'a besoin d'accepter une entrée qu'une seule fois dans un programme : var input = NSString(data: NSFileHandle.fileHandleWithStandardInput().availableData, encoding:NSUTF8StringEncoding)
Existe-t-il un moyen de l'utiliser dans le Playground pour accepter les entrées de l'utilisateur à la volée ?
Vous ne pouvez pas l'utiliser dans la cour de récréation. Vous devez y utiliser des variables.
En fait, ce n'est pas si simple, vous devez interagir avec l'API C. Il n'y a pas d'alternative à scanf
. J'ai construit un petit exemple :
main.swift
import Foundation
var output: CInt = 0
getInput(&output)
println(output)
UserInput.c
#include <stdio.h>
void getInput(int *output) {
scanf("%i", output);
}
cliinput-Bridging-Header.h
void getInput(int *output);
editar A partir de Swift 2.2, la bibliothèque standard comprend readLine
. Je note également que Swift est passé aux commentaires de documents markdown. Je laisse ma réponse originale pour le contexte historique.
Par souci d'exhaustivité, voici une implémentation Swift de readln
Je l'ai utilisé. Il a un paramètre optionnel pour indiquer le nombre maximum d'octets que vous voulez lire (qui peut ou non être la longueur de la chaîne).
Cela démontre également la bonne utilisation des commentaires swiftdoc - Swift générera un fichier <projet>.swiftdoc et Xcode l'utilisera.
///reads a line from standard input
///
///:param: max specifies the number of bytes to read
///
///:returns: the string, or nil if an error was encountered trying to read Stdin
public func readln(max:Int = 8192) -> String? {
assert(max > 0, "max must be between 1 and Int.max")
var buf:Array<CChar> = []
var c = getchar()
while c != EOF && c != 10 && buf.count < max {
buf.append(CChar(c))
c = getchar()
}
//always null terminate
buf.append(CChar(0))
return buf.withUnsafeBufferPointer { String.fromCString($0.baseAddress) }
}
J'aime les commentaires sur swiftdoc, et le modificateur d'accès "public", je n'avais pas vu ce genre de choses dans Swift auparavant, mais le CChar et le C-String semblent être un retour au C et aux jeux de caractères 8 bits, alors que Swift est un texte Unicode... ou les outils de ligne de commande sont-ils tous ASCII ?
Une autre alternative est de lier libedit pour une édition correcte des lignes (touches fléchées, etc.) et un support optionnel de l'historique. J'en avais besoin pour un projet que je suis en train de démarrer et j'ai créé une exemple de base pour savoir comment je l'ai mis en place .
Utilisation de swift
let prompt: Prompt = Prompt(argv0: C_ARGV[0])
while (true) {
if let line = prompt.gets() {
print("You typed \(line)")
}
}
wrapper ObjC pour exposer libedit
#import <histedit.h>
char* prompt(EditLine *e) {
return "> ";
}
@implementation Prompt
EditLine* _el;
History* _hist;
HistEvent _ev;
- (instancetype) initWithArgv0:(const char*)argv0 {
if (self = [super init]) {
// Setup the editor
_el = el_init(argv0, stdin, stdout, stderr);
el_set(_el, EL_PROMPT, &prompt);
el_set(_el, EL_EDITOR, "emacs");
// With support for history
_hist = history_init();
history(_hist, &_ev, H_SETSIZE, 800);
el_set(_el, EL_HIST, history, _hist);
}
return self;
}
- (void) dealloc {
if (_hist != NULL) {
history_end(_hist);
_hist = NULL;
}
if (_el != NULL) {
el_end(_el);
_el = NULL;
}
}
- (NSString*) gets {
// line includes the trailing newline
int count;
const char* line = el_gets(_el, &count);
if (count > 0) {
history(_hist, &_ev, H_ENTER, line);
return [NSString stringWithCString:line encoding:NSUTF8StringEncoding];
}
return nil;
}
@end
Je jure devant Dieu la solution à ce problème complètement basique Ce problème m'a échappé pendant des années. C'est Si simple mais il y a tellement d'informations vagues ou mauvaises. quelqu'un de un peu de de l'infini trous de lapin que je me suis retrouvé dans...
Alors, récupérons une "chaîne" de "l'utilisateur" via "la console", via stdin
, devons-nous ?
[NSString.alloc initWithData:
[NSFileHandle.fileHandleWithStandardInput availableData]
encoding:NSUTF8StringEncoding];
si vous le voulez SANS la nouvelle ligne de queue, ajoutez simplement...
[ ... stringByTrimmingCharactersInSet:
NSCharacterSet.newlineCharacterSet];
Ta Da!
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.