Я пытаюсь получить ввод с клавиатуры для приложения командной строки для нового языка программирования Apple Swift.
Я просмотрел документы безрезультатно.
import Foundation
println("What is your name?")
???
Любые идеи?
swift
macos
cocoa
command-line
Мелки
источник
источник
Мне удалось понять это, не переходя на C:
Мое решение таково:
func input() -> String { var keyboard = NSFileHandle.fileHandleWithStandardInput() var inputData = keyboard.availableData return NSString(data: inputData, encoding:NSUTF8StringEncoding)! }
Более поздние версии Xcode нуждаются в явном приведении типов (работает в 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())
На самом деле это не так просто, вам нужно взаимодействовать с C API. Альтернативы нет
scanf
. Я построил небольшой пример: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);
источник
edit Начиная с Swift 2.2 стандартная библиотека включает
readLine
. Также отмечу, что Swift переключился на комментарии к документам по уценке. Оставлю свой первоначальный ответ для исторического контекста.Просто для полноты, вот реализация Swift,
readln
которую я использовал. У него есть необязательный параметр, указывающий максимальное количество байтов, которое вы хотите прочитать (которое может быть или не быть длиной строки).Это также демонстрирует правильное использование комментариев swiftdoc - Swift сгенерирует файл <project> .swiftdoc, и Xcode будет его использовать.
///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) } }
источник
Обычно функция readLine () используется для сканирования ввода с консоли. Но он не будет работать в обычном проекте iOS до тех пор, пока вы не добавите «инструмент командной строки» .
Лучше всего для тестирования вы можете:
1. Создайте файл macOS.
2. Используйте функцию readLine () для сканирования необязательной строки с консоли.
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
источник
Другой альтернативой является привязка libedit для правильного редактирования строк (клавиши со стрелками и т. Д.) И дополнительной поддержки истории. Я хотел это для проекта, который я начинаю, и собрал базовый пример того, как я его настроил .
Использование из swift
let prompt: Prompt = Prompt(argv0: C_ARGV[0]) while (true) { if let line = prompt.gets() { print("You typed \(line)") } }
Оболочка ObjC для доступа к 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
источник
Вот простой пример ввода данных пользователем в консольном приложении: Вы можете использовать readLine (). Введите первый номер с консоли и нажмите Enter. После этого введите второй номер, как показано на изображении ниже:
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)
источник
Множество устаревших ответов на этот вопрос. Начиная с Swift 2+, стандартная библиотека Swift содержит функцию readline () . Он вернет Optional, но будет равен нулю только в том случае, если был достигнут EOF, чего не произойдет при получении ввода с клавиатуры, поэтому его можно безопасно развернуть принудительно в этих сценариях. Если пользователь ничего не вводит, его (развернутое) значение будет пустой строкой. Вот небольшая служебная функция, которая использует рекурсию, чтобы запрашивать пользователя, пока не будет введен хотя бы один символ:
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)")
Обратите внимание, что использование необязательной привязки (если let input = readLine ()) для проверки того, было ли что-то введено, как было предложено в других ответах, не будет иметь желаемого эффекта, так как оно никогда не будет равно нулю и, по крайней мере, при приеме ввода с клавиатуры.
Это не будет работать на игровой площадке или в любой другой среде, где у вас нет доступа к командной строке. Кажется, есть проблемы и с REPL командной строки.
источник
Клянусь Богом ... решение этой фундаментальной проблемы ускользало от меня ГОДЫ. Это НАСТОЛЬКО просто ... но существует так много расплывчатой / плохой информации; надеюсь , я могу спасти кого - то от некоторых из бездонных дыр кролика , что я оказался в ...
Итак, давайте получим «строку» от «пользователя» через «консоль»
stdin
, не так ли ?[NSString.alloc initWithData: [NSFileHandle.fileHandleWithStandardInput availableData] encoding:NSUTF8StringEncoding];
если вы хотите его БЕЗ завершающего символа новой строки, просто добавьте ...
[ ... stringByTrimmingCharactersInSet: NSCharacterSet.newlineCharacterSet];
Ta Da!
♥ ⱥ ᏪℯⅩисточник
Swift 5: если вы постоянно хотите вводить данные с клавиатуры, не завершая программу, например поток ввода, выполните следующие действия:
Создать новый проект типа comnnad line tool
Добавьте ниже код в файл 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:") }
источник
Поскольку у этой проблемы не было необычных решений, я создал крошечный класс для чтения и анализа стандартного ввода в Swift. Вы можете найти это здесь .
пример
Чтобы разобрать:
+42 st_ring! -0.987654321 12345678900 .42
Ты сделаешь:
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" }
источник
Перед
*******************.
Исправление
источник
Это работает в xCode v6.2, я думаю, что это Swift v1.2
func input() -> String { var keyboard = NSFileHandle.fileHandleWithStandardInput() var inputData = keyboard.availableData return NSString(data: inputData, encoding:NSUTF8StringEncoding)! as String }
источник
Если вы хотите прочитать строку, разделенную пробелами, и сразу же разбить строку на массив, вы можете сделать это:
var arr = readLine()!.characters.split(" ").map(String.init)
например.
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)")
источник
Когда функция readLine () запускается в Xcode, консоль отладки ожидает ввода. Остальная часть кода будет возобновлена после завершения ввода.
let inputStr = readLine() if let inputStr = inputStr { print(inputStr) }
источник
Самый популярный ответ на этот вопрос предполагает использование метода readLine () для ввода пользовательского ввода из командной строки. Однако хочу отметить, что нужно использовать! при вызове этого метода для возврата строки вместо необязательного:
var response = readLine()!
источник
readLine()
по какой-то причине возвращает необязательно, поэтому принудительное развертывание небезопасно и на самом деле ничего не добавляет к примеру.var a; scanf("%s\n", n);
Я тестировал это в ObjC, и, возможно, это будет полезно.
источник
Я просто хотел прокомментировать (у меня недостаточно представителей) реализацию xenadu, потому что
CChar
в OS X естьInt8
, а Swift совсем не любит, когда вы добавляете в массив, когдаgetchar()
возвращает части UTF-8 или что-либо еще выше 7 бит.UInt8
Вместо этого я использую массив , и он отлично работает и отличноString.fromCString
конвертируетUInt8
в UTF-8.Однако вот как я это сделал
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)") } }
источник
Теперь я смог получить ввод с клавиатуры в Swift, используя следующее:
В моем файле main.swift я объявил переменную i и назначил ей функцию GetInt (), которую я определил в Objective C. Через так называемый Bridging Header, где я объявил прототип функции для GetInt, я мог ссылаться на main.swift. Вот файлы:
main.swift:
var i: CInt = GetInt() println("Your input is \(i) ");
Заголовок моста:
#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; }
В obj.m можно включить стандартный вывод и ввод c, stdio.h, а также стандартную библиотеку c stdlib.h, которая позволяет вам программировать на C в Objective-C, что означает, что нет необходимости включать настоящий быстрый файл типа user.c или что-то в этом роде.
Надеюсь, я смогу помочь,
Изменить: невозможно получить ввод String через C, потому что здесь я использую CInt -> целочисленный тип C, а не Swift. Для C char * не существует эквивалентного типа Swift. Следовательно, String не может быть преобразован в строку. Но здесь достаточно решений для ввода String.
Рауль
источник