Saya mencoba mendapatkan input keyboard untuk aplikasi baris perintah untuk bahasa pemrograman Apple yang baru, Swift.
Saya telah memindai dokumen tetapi tidak berhasil.
import Foundation
println("What is your name?")
???
Ada ide?
swift
macos
cocoa
command-line
Kapur
sumber
sumber
Saya berhasil mengetahuinya tanpa jatuh ke C:
Solusi saya adalah sebagai berikut:
func input() -> String { var keyboard = NSFileHandle.fileHandleWithStandardInput() var inputData = keyboard.availableData return NSString(data: inputData, encoding:NSUTF8StringEncoding)! }
Versi Xcode yang lebih baru memerlukan typecast eksplisit (berfungsi di Xcode 6.4):
func input() -> String { var keyboard = NSFileHandle.fileHandleWithStandardInput() var inputData = keyboard.availableData return NSString(data: inputData, encoding:NSUTF8StringEncoding)! as String }
sumber
var input = NSString(data: NSFileHandle.fileHandleWithStandardInput().availableData, encoding:NSUTF8StringEncoding)
string.stringByTrimmingCharactersInSet(NSCharacterSet.newlineCharacterSet())
Sebenarnya tidak semudah itu, Anda harus berinteraksi dengan C API. Tidak ada alternatif untuk
scanf
. Saya telah membuat sedikit contoh: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);
sumber
sunting Pada Swift 2.2 termasuk pustaka standar
readLine
. Saya juga akan mencatat Swift beralih ke komentar dokumen penurunan harga. Meninggalkan jawaban asli saya untuk konteks sejarah.Sekadar kelengkapan, berikut adalah implementasi Swift yang
readln
telah saya gunakan. Ini memiliki parameter opsional untuk menunjukkan jumlah maksimum byte yang ingin Anda baca (yang mungkin atau mungkin bukan panjang String).Ini juga mendemonstrasikan penggunaan yang tepat dari komentar swiftdoc - Swift akan menghasilkan file <project> .swiftdoc dan Xcode akan menggunakannya.
///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) } }
sumber
Secara umum, fungsi readLine () digunakan untuk memindai input dari konsol. Tapi itu tidak akan bekerja dalam proyek iOS normal sampai atau kecuali Anda menambahkan "alat baris perintah" .
Cara terbaik untuk pengujian, Anda dapat melakukan:
1. Buat file macOS
2. Gunakan fungsi readLine () untuk memindai String opsional dari konsol
import Foundation print("Please enter some input\n") if let response = readLine() { print("output :",response) } else { print("Nothing") }
Keluaran:
Please enter some input Hello, World output : Hello, World Program ended with exit code: 0
sumber
Alternatif lain adalah menautkan libedit untuk pengeditan baris yang tepat (tombol panah, dll.) Dan dukungan riwayat opsional. Saya menginginkan ini untuk proyek yang saya mulai dan mengumpulkan contoh dasar bagaimana saya mengaturnya .
Penggunaan dari swift
let prompt: Prompt = Prompt(argv0: C_ARGV[0]) while (true) { if let line = prompt.gets() { print("You typed \(line)") } }
Pembungkus ObjC untuk mengekspos 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
sumber
Berikut adalah contoh sederhana untuk mengambil input dari pengguna pada aplikasi berbasis konsol: Anda dapat menggunakan readLine (). Ambil input dari konsol untuk nomor pertama lalu tekan enter. Setelah itu ambil input angka kedua seperti yang terlihat pada gambar di bawah ini:
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)
sumber
Banyak jawaban usang untuk pertanyaan ini. Mulai Swift 2+, Perpustakaan Standar Swift berisi fungsi readline () . Ini akan mengembalikan Opsional tetapi hanya akan menjadi nihil jika EOF telah tercapai, yang tidak akan terjadi saat mendapatkan input dari keyboard sehingga dapat dibuka secara paksa dengan paksa dalam skenario tersebut. Jika pengguna tidak memasukkan apa pun, nilainya (tidak terbungkus) akan menjadi string kosong. Berikut adalah fungsi utilitas kecil yang menggunakan rekursi untuk meminta pengguna hingga setidaknya satu karakter telah dimasukkan:
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)")
Perhatikan bahwa menggunakan penjilidan opsional (jika let input = readLine ()) untuk memeriksa apakah ada sesuatu yang dimasukkan seperti yang diusulkan dalam jawaban lain tidak akan memiliki efek yang diinginkan, karena tidak akan pernah nol dan setidaknya "" saat menerima input keyboard.
Ini tidak akan berfungsi di Playground atau lingkungan lain di mana Anda tidak memiliki akses ke prompt perintah. Tampaknya ada masalah pada baris perintah REPL juga.
sumber
Aku bersumpah demi Tuhan .. solusi untuk masalah yang benar-benar mendasar ini membuatku kabur selama bertahun-tahun. Sangat sederhana .. tetapi ada begitu banyak informasi yang tidak jelas / buruk di luar sana; semoga saya dapat menyelamatkan seseorang dari beberapa lubang kelinci tak berdasar yang akhirnya saya masuki ...
Jadi, mari kita dapatkan "string" dari "pengguna" melalui "konsol", melalui
stdin
, oke ?[NSString.alloc initWithData: [NSFileHandle.fileHandleWithStandardInput availableData] encoding:NSUTF8StringEncoding];
jika Anda menginginkannya TANPA trailing newline, tambahkan saja ...
[ ... stringByTrimmingCharactersInSet: NSCharacterSet.newlineCharacterSet];
Ta Da!
♥ ⱥ ᏪℯⅩsumber
Swift 5: Jika Anda terus-menerus menginginkan input dari keyboard, tanpa mengakhiri program, seperti aliran input, Gunakan langkah-langkah di bawah ini:
Buat proyek baru jenis alat baris comnnad
Tambahkan kode di bawah ini di file main.swift:
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:") }
sumber
Karena tidak ada solusi yang bagus untuk masalah ini, saya membuat kelas kecil untuk membaca dan mengurai input standar di Swift. Anda bisa menemukannya di sini .
Contoh
Mengurai:
+42 st_ring! -0.987654321 12345678900 .42
Anda melakukan:
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" }
sumber
Sebelum
*******************.
Koreksi
sumber
Ini berfungsi di xCode v6.2, saya pikir itu Swift v1.2
func input() -> String { var keyboard = NSFileHandle.fileHandleWithStandardInput() var inputData = keyboard.availableData return NSString(data: inputData, encoding:NSUTF8StringEncoding)! as String }
sumber
Jika Anda ingin membaca string yang dipisahkan spasi, dan segera memisahkan string menjadi array, Anda dapat melakukan ini:
var arr = readLine()!.characters.split(" ").map(String.init)
misalnya.
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)")
sumber
Saat fungsi readLine () dijalankan di Xcode, konsol debug menunggu masukan. Sisa kode akan dilanjutkan setelah input selesai.
let inputStr = readLine() if let inputStr = inputStr { print(inputStr) }
sumber
Jawaban peringkat teratas untuk pertanyaan ini menyarankan penggunaan metode readLine () untuk mengambil input pengguna dari baris perintah. Namun, saya ingin mencatat bahwa Anda perlu menggunakan! operator saat memanggil metode ini untuk mengembalikan string alih-alih opsional:
var response = readLine()!
sumber
readLine()
mengembalikan opsional karena suatu alasan, oleh karena itu tidak aman untuk membuka paksa dan tidak benar-benar menambahkan apa pun ke contoh.var a; scanf("%s\n", n);
Saya menguji ini di ObjC, dan mungkin ini akan berguna.
sumber
Saya hanya ingin berkomentar (saya tidak memiliki cukup repetisi) tentang implementasi xenadu, karena
CChar
di OS XInt8
, dan Swift sama sekali tidak suka ketika Anda menambahkan ke array ketikagetchar()
mengembalikan bagian UTF-8, atau apa pun di atas 7 bit.Saya menggunakan array
UInt8
sebagai gantinya, dan itu berfungsi dengan baik danString.fromCString
mengubahnyaUInt8
menjadi UTF-8 dengan baik.Namun begitulah cara saya melakukannya
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)") } }
sumber
Sekarang saya bisa mendapatkan input Keyboard di Swift dengan menggunakan berikut ini:
Dalam file main.swift saya, saya mendeklarasikan variabel i dan menugaskannya ke fungsi GetInt () yang saya definisikan di Objective C. Melalui apa yang disebut Bridging Header di mana saya mendeklarasikan prototipe fungsi untuk GetInt, saya bisa menautkan ke main.swift. Ini file-nya:
main.swift:
var i: CInt = GetInt() println("Your input is \(i) ");
Bridging Header:
#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; }
Dalam obj.m dimungkinkan untuk menyertakan keluaran dan masukan standar c, stdio.h, serta pustaka standar c stdlib.h yang memungkinkan Anda memprogram dalam C dalam Objective-C, yang berarti tidak perlu menyertakan file cepat yang nyata seperti user.c atau sesuatu seperti itu.
Semoga saya bisa membantu,
Sunting: Tidak mungkin mendapatkan input String melalui C karena di sini saya menggunakan CInt -> tipe integer C dan bukan Swift. Tidak ada tipe Swift yang setara untuk C char *. Oleh karena itu, String tidak dapat diubah menjadi string. Tetapi ada solusi yang cukup di sekitar sini untuk mendapatkan input String.
Raul
sumber