Antworten:
Der richtige Weg, dies zu tun, ist die Verwendung readLine
aus der Swift Standard Library.
Beispiel:
let response = readLine()
Gibt Ihnen einen optionalen Wert, der den eingegebenen Text enthält.
Ich habe es geschafft, es herauszufinden, ohne zu C zu kommen:
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 benötigen 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
}
var input = NSString(data: NSFileHandle.fileHandleWithStandardInput().availableData, encoding:NSUTF8StringEncoding)
string.stringByTrimmingCharactersInSet(NSCharacterSet.newlineCharacterSet())
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 gebaut:
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);
Bearbeiten Ab Swift 2.2 enthält die Standardbibliothek readLine
. Ich werde auch feststellen, dass Swift auf Markdown-Dokumentkommentare umgestellt hat. Ich lasse meine ursprüngliche Antwort für den historischen Kontext.
Der Vollständigkeit halber hier eine Swift-Implementierung, die readln
ich verwendet habe. Es verfügt über einen optionalen Parameter, der die maximale Anzahl von Bytes angibt, die Sie lesen möchten (dies kann die Länge des Strings sein oder nicht).
Dies zeigt auch die ordnungsgemäße 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) }
}
Eine andere Alternative besteht darin, libedit für eine ordnungsgemäße Zeilenbearbeitung (Pfeiltasten usw.) und optionale Verlaufsunterstützung zu verknüpfen . Ich wollte dies für ein Projekt, das ich gerade starte, und habe ein grundlegendes Beispiel für die Einrichtung zusammengestellt .
Verwendung von schnell
let prompt: Prompt = Prompt(argv0: C_ARGV[0])
while (true) {
if let line = prompt.gets() {
print("You typed \(line)")
}
}
ObjC-Wrapper zum Offenlegen von 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
Im Allgemeinen wird die Funktion readLine () zum Scannen von Eingaben von der Konsole verwendet. In normalen iOS-Projekten funktioniert dies jedoch erst, wenn Sie das Befehlszeilentool hinzufügen .
Der beste Weg zum Testen ist:
import Foundation
print("Please enter some input\n")
if let response = readLine() {
print("output :",response)
} else {
print("Nothing")
}
Please enter some input
Hello, World
output : Hello, World
Program ended with exit code: 0
Hier ist ein einfaches Beispiel für die Eingabe von Benutzern in einer konsolenbasierten Anwendung: Sie können readLine () verwenden. Nehmen Sie die Eingabe von der Konsole für die erste Nummer und drücken Sie die Eingabetaste. Geben Sie danach die zweite Zahl ein, wie im Bild 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)
Ich schwöre bei Gott. Die Lösung dieses äußerst grundlegenden Problems entging mir JAHRE lang. Es ist so einfach ... aber es gibt so viele vage / schlechte Informationen da draußen; hoffentlich kann ich jemanden vor einigen der bodenlosen Kaninchenlöcher retten , in denen ich gelandet bin ...
Lassen Sie uns also einen "String" von "dem Benutzer" über "die Konsole" erhalten, über stdin
, sollen wir ?
[NSString.alloc initWithData:
[NSFileHandle.fileHandleWithStandardInput availableData]
encoding:NSUTF8StringEncoding];
Wenn Sie es OHNE den nachfolgenden Zeilenumbruch möchten, fügen Sie einfach ...
[ ... stringByTrimmingCharactersInSet:
NSCharacterSet.newlineCharacterSet];
Ta Da!
♥ ⱥ ᏪℯⅩ
Viele veraltete Antworten auf diese Frage. Ab Swift 2+ enthält die Swift Standard Library die Funktion readline () . Es wird ein Optional zurückgegeben, aber es wird nur Null sein, wenn EOF erreicht wurde. Dies tritt nicht auf, wenn Eingaben von der Tastatur abgerufen werden, sodass es in diesen Szenarien sicher gewaltsam ausgepackt werden kann. Wenn der Benutzer nichts eingibt, ist sein (nicht verpackter) Wert eine leere Zeichenfolge. Hier ist eine kleine Dienstprogrammfunktion, die den Benutzer mithilfe der Rekursion auffordert, 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 input = readLine ()) zur Überprüfung, ob etwas wie in anderen Antworten vorgeschlagen eingegeben wurde, nicht den gewünschten Effekt hat, da es beim Akzeptieren von Tastatureingaben niemals Null und mindestens "" ist.
Dies funktioniert nicht auf einem Spielplatz oder in einer anderen Umgebung, in der Sie keinen Zugriff auf die Eingabeaufforderung haben. Es scheint auch Probleme in der Befehlszeile REPL zu geben.
Da es für dieses Problem keine ausgefallenen Lösungen gab, habe ich eine winzige Klasse erstellt, um die Standardeingabe in Swift zu lesen und zu analysieren. Sie finden es hier .
Beispiel
Zum Parsen:
+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"
}
Dies 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
}
Wenn Sie eine durch Leerzeichen getrennte Zeichenfolge lesen und die Zeichenfolge sofort in ein Array aufteilen möchten, haben Sie folgende Möglichkeiten:
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)")
Wenn die Funktion readLine () unter Xcode ausgeführt wird, wartet die Debug-Konsole auf die Eingabe. Der Rest des Codes wird nach erfolgter Eingabe fortgesetzt.
let inputStr = readLine()
if let inputStr = inputStr {
print(inputStr)
}
Die am besten bewertete Antwort auf diese Frage schlägt vor, die readLine () -Methode zu verwenden, um Benutzereingaben über die Befehlszeile zu erfassen. Ich möchte jedoch darauf hinweisen, dass Sie die! Operator beim Aufrufen dieser Methode, um eine Zeichenfolge anstelle einer optionalen zurückzugeben:
var response = readLine()!
readLine()
aus einem bestimmten Grund optional zurückgegeben wird, ist daher das Force-Unwrap unsicher und fügt dem Beispiel nichts hinzu.
Swift 5: Wenn Sie kontinuierlich Eingaben über die Tastatur wünschen, ohne das Programm wie einen Eingabestream zu beenden, führen Sie die folgenden Schritte aus:
Erstellen Sie ein neues Projekt vom Typ comnnad line tool
Fügen Sie den folgenden Code in die Datei main.swift ein:
var inputArray = [String]()
while let input = readLine() {
guard input != "quit" else {
break
}
inputArray.append(input)
print("You entered: \(input)")
print(inputArray)
print("Enter a word:")
}
var a;
scanf("%s\n", n);
Ich habe dies in ObjC getestet, und vielleicht ist dies nützlich.
Ich wollte nur die Implementierung von xenadu kommentieren (ich habe nicht genug Wiederholungen), weil dies CChar
in OS X der Fall ist Int8
und Swift es überhaupt nicht mag, wenn Sie dem Array wann hinzufügengetchar()
Teile von UTF-8 oder etwas anderes über 7 Bit zurückgegeben werden.
Ich verwende UInt8
stattdessen ein Array von , und es funktioniert großartig und String.fromCString
konvertiert das UInt8
in UTF-8 ganz gut.
Aber so habe ich es gemacht
func readln() -> (str: String?, hadError: Bool) {
var cstr: [UInt8] = []
var c: Int32 = 0
while c != EOF {
c = getchar()
if (c == 10 || c == 13) || c > 255 { break }
cstr.append(UInt8(c))
}
cstr.append(0)
return String.fromCStringRepairingIllFormedUTF8(UnsafePointer<CChar>(cstr))
}
while true {
if let mystring = readln().str {
println(" > \(mystring)")
}
}
Ich konnte jetzt Tastatureingaben in Swift mithilfe der folgenden Funktionen abrufen:
In meiner Datei main.swift habe ich eine Variable i deklariert und ihr die Funktion GetInt () zugewiesen, die ich in Ziel C definiert habe. Über einen sogenannten Bridging Header, in dem ich den Funktionsprototyp für GetInt deklariert habe, konnte ich eine Verknüpfung zu main.swift herstellen. Hier sind die Dateien:
main.swift:
var i: CInt = GetInt()
println("Your input is \(i) ");
Überbrückungskopfzeile:
#include "obj.m"
int GetInt();
obj.m:
#import <Foundation/Foundation.h>
#import <stdio.h>
#import <stdlib.h>
int GetInt()
{
int i;
scanf("%i", &i);
return i;
}
In obj.m ist es möglich, die c-Standardausgabe und -eingabe stdio.h sowie die c-Standardbibliothek stdlib.h einzuschließen, mit der Sie in C in Objective-C programmieren können, sodass keine Einbeziehung erforderlich ist eine wirklich schnelle Datei wie user.c oder so ähnlich.
Hoffe ich konnte helfen,
Bearbeiten: Es ist nicht möglich, String-Eingaben über C zu erhalten, da ich hier das CInt -> den Integer-Typ von C und nicht von Swift verwende. Es gibt keinen äquivalenten Swift-Typ für das C-Zeichen *. Daher kann String nicht in String konvertiert werden. Aber es gibt hier ziemlich genug Lösungen, um String-Eingaben zu erhalten.
Raul