web-dev-qa-db-fra.com

Entrée à partir du clavier dans l'application en ligne de commande

Je tente d'obtenir l'entrée au clavier pour une application de ligne de commande pour le nouveau langage de programmation Apple Swift.

J'ai scanné les documents en vain.

import Foundation

println("What is your name?")
???

Des idées?

88
Chalkers

J'ai réussi à comprendre sans tomber dans 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 une conversion de type 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
}
59
Chalkers

Pour ce faire, utilisez readLine , à partir de la bibliothèque Swift Standard.

Exemple:

let response = readLine()

Vous donnera une valeur optionnelle contenant le texte saisi.

120
Ezekiel Elin

Ce n'est pas si facile, 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);
13
Leandros

edit A partir de Swift 2.2, la bibliothèque standard inclut readLine. Je noterai également que Swift est passé aux commentaires de Markdown. Laissant ma réponse originale pour le contexte historique. 

Juste pour être complet, voici une implémentation rapide de readln que j'utilise. Il a un paramètre facultatif pour indiquer le nombre maximum d'octets que vous voulez lire (qui peut être ou non la longueur de la chaîne).

Cela démontre également la bonne utilisation des commentaires de 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) }
}
6
russbishop

En général readLine () Cette fonction est utilisée pour balayer les entrées depuis la console. Mais cela ne fonctionnera pas dans un projet iOS normal tant que vous n'ajouterez pas "outil en ligne de commande".

La meilleure façon de tester, vous pouvez faire: 

1. Créez un fichier macOS

 enter image description here

2. Utilisez la fonction readLine () pour analyser une chaîne facultative depuis la console.

 import Foundation

 print("Please enter some input\n")

 if let response = readLine() {
    print("output :",response)
 } else {
    print("Nothing")
 }

Sortie:

Please enter some input

Hello, World
output : Hello, World
Program ended with exit code: 0

 enter image description here

5
Ashis Laha

Une autre alternative consiste à lier libedit pour une édition de ligne appropriée (touches de direction, etc.) et un support d’historique optionnel. Je voulais cela pour un projet que je commençais et ai construit un exemple de base pour la façon dont 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)")
    }
}

ObjC wrapper 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
5
Neil

Voici un exemple simple de saisie de l'utilisateur sur une application basée sur la console: Vous pouvez utiliser readLine (). Prenez l’entrée de la console pour le premier numéro puis appuyez sur Entrée. Après cela, saisissez le deuxième numéro comme indiqué dans l'image ci-dessous:

func solveMefirst(firstNo: Int , secondNo: Int) -> Int {
    return firstNo + secondNo
}

let num1 = readLine()
let num2 = readLine()

var IntNum1 = Int(num1!)
var IntNum2 = Int(num2!)

let sum = solveMefirst(IntNum1!, secondNo: IntNum2!)
print(sum)

 Output

2
Shehzad Ali

La réponse la mieux classée à cette question suggère d'utiliser la méthode readLine () pour prendre en compte les entrées utilisateur à partir de la ligne de commande. Cependant, je tiens à noter que vous devez utiliser le! opérateur lors de l'appel de cette méthode pour retourner une chaîne au lieu d'un optionnel:

var response = readLine()!
1
topherPedersen

Lorsque la fonction readLine () est exécutée sur Xcode, la console de débogage attend l’entrée. Le reste du code sera repris après la saisie. 

    let inputStr = readLine()
    if let inputStr = inputStr {
        print(inputStr)
    }
0
Sourabh Shekhar

Avant

 enter image description here

********************.

Correction

 enter image description here

0
Murphy

Beaucoup de réponses obsolètes à cette question. À partir de Swift 2+, la bibliothèque standard de Swift contient la fonction readline () . Il renverra un facultatif, mais il sera nul si EOF a été atteint, ce qui ne se produira pas lors de la saisie à partir du clavier, de sorte qu'il peut être déplacé en toute sécurité par la force dans ces scénarios. Si l'utilisateur n'entre rien, sa valeur (non enveloppée) sera une chaîne vide. Voici une petite fonction utilitaire qui utilise la récursivité pour inviter l'utilisateur jusqu'à ce qu'au moins un caractère ait été saisi:

func Prompt(message: String) -> String {
    print(message)
    let input: String = readLine()!
    if input == "" {
        return Prompt(message: message)
    } else {
        return input
    }
}

let input = Prompt(message: "Enter something!")
print("You entered \(input)")

Notez que l'utilisation de la liaison facultative (si let input = readLine ()) pour vérifier si quelque chose a été entré tel que proposé dans d'autres réponses n'aura pas l'effet souhaité, car elle ne sera jamais nulle et au moins "" lors de l'acceptation de l'entrée au clavier.

Cela ne fonctionnera pas dans un terrain de jeu ou dans tout autre environnement où vous n'avez pas accès à la commande Invite. Il semble également y avoir des problèmes dans la ligne de commande REPL.

0
Andreas Bergström

Comme il n'y avait pas de solution sophistiquée à ce problème, j'ai créé une petite classe pour lire et analyser l'entrée standard dans Swift. Vous pouvez le trouver ici .

Exemple

Pour analyser:

+42 st_ring!
-0.987654321 12345678900
.42

Tu fais:

let stdin = StreamScanner.standardInput

if
    let i: Int = stdin.read(),
    let s: String = stdin.read(),
    let d: Double = stdin.read(),
    let i64: Int64 = stdin.read(),
    let f: Float = stdin.read()
{
    print("\(i) \(s) \(d) \(i64) \(f)")  //prints "42 st_ring! -0.987654321 12345678900 0.42"
}
0
shoumikhin

Cela fonctionne dans xCode v6.2, je pense que c'est Swift v1.2

func input() -> String {
    var keyboard = NSFileHandle.fileHandleWithStandardInput()
    var inputData = keyboard.availableData
    return NSString(data: inputData, encoding:NSUTF8StringEncoding)! as String
}
0
Giant Elk

Je jure devant Dieu… la solution à ce problème {absolument fondamental} m'a échappé pendant des années. C'est SO simple .. mais il y a tellement d'informations vagues/mauvaises; j'espère pouvoir sauver quelqu'un de certains du sans-fond des trous de lapin dans lesquels j'ai fini.

Donc, obtenons une "chaîne" de "l'utilisateur" via "la console", via stdin, doit-on}?

[NSString.alloc initWithData:
[NSFileHandle.fileHandleWithStandardInput availableData]
                          encoding:NSUTF8StringEncoding];

si vous le voulez SANS la fin de ligne, il suffit d'ajouter ...

[ ... stringByTrimmingCharactersInSet:
                       NSCharacterSet.newlineCharacterSet];

Ta Da! ♥ ᏪℯⅩ

0
Alex Gray