it-swarm.com.de

Eingabe über die Tastatur in der Befehlszeilenanwendung

Ich versuche, die Tastatureingaben für eine Befehlszeilen-App für die neue Apple-Programmiersprache Swift zu erhalten.

Ich habe die Dokumente ohne Erfolg gescannt.

import Foundation

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

Irgendwelche Ideen?

88
Chalkers

Ich habe es herausgefunden, ohne in C zu fallen:

Meine Lösung lautet wie folgt:

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

Neuere Versionen von Xcode erfordern eine explizite Typumwandlung (funktioniert in Xcode 6.4):

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

Der korrekte Weg ist die Verwendung von readLine aus der Swift Standard Library.

Beispiel:

let response = readLine()

Gibt einen optionalen Wert an, der den eingegebenen Text enthält.

120
Ezekiel Elin

Es ist eigentlich nicht so einfach, Sie müssen mit der C-API interagieren. Es gibt keine Alternative zu scanf. Ich habe ein kleines Beispiel aufgebaut:

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 Ab Swift 2.2 enthält die Standardbibliothek readLine. Ich werde auch beachten, dass Swift zu markdown Doc-Kommentaren übergegangen ist. Meine ursprüngliche Antwort für den historischen Kontext lassen. 

Der Vollständigkeit halber ist hier eine Swift-Implementierung von readln, die ich verwendet habe. Es verfügt über einen optionalen Parameter, der die maximale Anzahl der zu lesenden Bytes angibt (die Länge des Strings kann oder nicht).

Dies zeigt auch die korrekte Verwendung von Swiftdoc-Kommentaren. Swift generiert eine <project> .swiftdoc-Datei, und Xcode verwendet sie.

///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

Im Algemeinen zeile lesen() Diese Funktion wird zum Scannen von Eingaben von der Konsole aus verwendet. Es funktioniert jedoch nicht in normalen iOS-Projekten, bis Sie es hinzufügen "Befehlszeilenprogramm".

Der beste Weg zum Testen können Sie tun: 

1. Erstellen Sie eine MacOS-Datei

 enter image description here

2. Verwenden Sie die Funktion readLine (), um die optionale Zeichenfolge von der Konsole aus zu scannen

 import Foundation

 print("Please enter some input\n")

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

Ausgabe :

Please enter some input

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

 enter image description here

5
Ashis Laha

Eine andere Alternative besteht darin, libedit für die korrekte Bearbeitung der Zeilen (Pfeiltasten usw.) und die optionale Protokollunterstützung zu verknüpfen. Ich wollte das für ein Projekt, das ich beginne, und füge ein grundlegendes Beispiel dafür zusammen, wie ich es aufbaue .

Nutzung von Swift

let Prompt: Prompt = Prompt(argv0: C_ARGV[0])

while (true) {
    if let line = Prompt.gets() {
        print("You typed \(line)")
    }
}

ObjC-Wrapper, um libedit verfügbar zu machen

#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

Hier ein einfaches Beispiel für die Eingabe von Eingaben von Benutzern in einer konsolenbasierten Anwendung: Sie können readLine () verwenden. Nehmen Sie die Eingabe der ersten Nummer von der Konsole und drücken Sie die Eingabetaste. Danach nehmen Sie die zweite Zahl ein, wie in der Abbildung unten gezeigt:

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

Die am besten bewertete Antwort auf diese Frage schlägt die Verwendung der readLine () - Methode vor, um Benutzereingaben über die Befehlszeile zu übernehmen. Ich möchte jedoch darauf hinweisen, dass Sie das verwenden müssen! Operator, wenn diese Methode aufgerufen wird, um eine Zeichenfolge anstelle einer optionalen Option zurückzugeben:

var response = readLine()!
1
topherPedersen

Wenn Sie eine durch Leerzeichen getrennte Zeichenfolge lesen und die Zeichenfolge sofort in ein Array aufteilen möchten, können Sie dies tun:

var arr = readLine()!.characters.split(" ").map(String.init)

z.B.

print("What is your full name?")

var arr = readLine()!.characters.split(" ").map(String.init)

var firstName = ""
var middleName = ""
var lastName = ""

if arr.count > 0 {
    firstName = arr[0]
}
if arr.count > 2 {
    middleName = arr[1]
    lastName = arr[2]
} else if arr.count > 1 {
    lastName = arr[1]
}

print("First Name: \(firstName)")
print("Middle Name: \(middleName)")
print("Last Name: \(lastName)")
0
Brian Ho

Wenn die Funktion readLine () unter Xcode ausgeführt wird, wartet die Debug-Konsole auf Eingaben. Der Rest des Codes wird nach der Eingabe fortgesetzt. 

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

Vor

 enter image description here

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

Korrektur

 enter image description here

0
Murphy

Viele veraltete Antworten auf diese Frage. Ab Swift 2+ enthält die Swift Standard Library die Funktion readline () . Es wird ein optionales Rückgabewert zurückgegeben, aber es wird nur null sein, wenn EOF erreicht wurde. Dies ist nicht der Fall, wenn Eingaben über die Tastatur abgerufen werden, sodass es in diesen Szenarien gewaltsam entpackt werden kann. Wenn der Benutzer nichts eingibt, ist sein (unverpackter) Wert eine leere Zeichenfolge. Hier ist eine kleine Hilfsfunktion, die Rekursion verwendet, um den Benutzer aufzufordern, bis mindestens ein Zeichen eingegeben wurde:

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)")

Beachten Sie, dass die Verwendung der optionalen Bindung (wenn let = readLine ()) verwendet wird, um zu prüfen, ob etwas eingegeben wurde, wie es in anderen Antworten vorgeschlagen wurde, nicht den gewünschten Effekt hat, da es bei Eingabe von Tastatureingaben niemals "Null" und zumindest "" ist.

Dies funktioniert nicht in einem Spielplatz oder einer anderen Umgebung, in der Sie nicht auf den Befehl Aufforderung zugreifen können. Es scheint auch Probleme in der Befehlszeile REPL zu geben.

0

Da es keine ausgefallenen Lösungen für dieses Problem gab, habe ich eine winzige Klasse gemacht, um die Standardeingabe in Swift zu lesen und zu analysieren. Sie finden es hier .

Beispiel

Zu analysieren:

+42 st_ring!
-0.987654321 12345678900
.42

Sie machen:

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

Das funktioniert in xCode v6.2, ich denke, das ist 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

Ich schwöre bei Gott .. die Lösung dieses absolut grundlegenden Problems entging mir jahrelang. Es ist SO einfach .., aber es gibt so viele vage/schlechte Informationen da draußen; hoffentlich kann ich jemanden von einige der bodenlosen Kaninchenlöcher retten, in denen ich gelandet bin ...

Also, lasst uns einen "String" vom "Benutzer" über "die Konsole" erhalten, über stdin, sollen wir?

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

wenn Sie möchten, dass OHNE die nachgestellte Zeile ist, fügen Sie einfach ...

[ ... stringByTrimmingCharactersInSet:
                       NSCharacterSet.newlineCharacterSet];

Ta Da! ♥ ⱥ ᏪℯⅩ

0
Alex Gray