文字列を文字配列に変換する

投稿者: | 2017年2月19日

ちょっと方針を変えまして、配列を操作するの内容とmkpass用CheckOptionクラスを統合します。実行時コマンドラインオプションに従って乱数生成文字セットを用意するまでをConditionという一つのクラスにします。

以前datecountコマンドのところでコマンドライン引数の字句解析のために、.charactersを使って文字列を一文字づつ分解しました。

前回はforループを回して分解後の文字を都度変数に格納して扱いましたが、今回は分解したものを配列に格納してみます。

class Condition {
  private var length: Int           // Condition class returns length of password from options.
  private var returnCode: Int32     // Condition class returns return code. Success:0, Version:1, Help:2, Failure:9
  private var member: [Character]   // Condition class returns character set of password from options.
  init(length: Int = 0, returnCode: Int32 = 0, member: [Character] = []) {
    self.length = length
    self.returnCode = returnCode
    self.member = member
  }
  func get(arguments: [String]) -> ([Character], Int, Int32) {
    enum ArgsType {
      case unknown
      case option
      case length
      case error
    }
    var argType: ArgsType = ArgsType.unknown
    var option: String
    let upper: [String] = ["ABCDEFGHIJKLMNOPQRSTUVWXYZ","ABCDEFGHJKLMNPQRSTUVWXYZ"]
    let lower: [String] = ["abcdefghijklmnopqrstuvwxyz","abcdefghijkmnopqrstuvwxyz"]
    let number: [String] = ["0123456789","23456789"]
    let symbol: [String] = ["!\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~","!\"#$%&\'()*+,-./:;<=>?@[\\]^_`{}~"]
    var status: (upper: Int, lower: Int, number: Int, symbol: Int, exclude: Int) = (0, 0, 0, 0, 0)
    chk_opt: for n in 1..<arguments.count {
      option = arguments[n]
      for char in option.characters {
        if argType == ArgsType.unknown {
          switch char {
          case "-":
            argType = ArgsType.option
          case "1"..."9":
            argType = ArgsType.length
          default:
            argType = ArgsType.error
            returnCode = 9
            break
          }
        } else if argType == ArgsType.option {
          switch char {
          case "a":
            status.upper |= 0b00000001
            status.lower |= 0b00000001
            status.number |= 0b00000001
            status.symbol |= 0b00000001
          case "u":
            status.upper |= 0b00000001
          case "l":
            status.lower |= 0b00000001
          case "n":
            status.number |= 0b00000001
          case "s":
            status.symbol |= 0b00000001
          case "x":
            status.exclude |=  0b00000001
          case "v":
            argType = ArgsType.error
            returnCode = 1
            break
          case "h":
            argType = ArgsType.error
            returnCode = 2
            break
          default:
            argType = ArgsType.error
            returnCode = 9
            break
          }
        } else if argType == ArgsType.length {
          switch char {
          case "0"..."9":
            argType = ArgsType.length
          default:
            argType = ArgsType.error
            returnCode = 9
            break
          }
        }
        if returnCode != 0 {
          break chk_opt
        }
      }
      if argType == ArgsType.length {
        length = Int(option)!
      }
      argType = ArgsType.unknown
    }
    if status.upper != 0 {
      member += Array(upper[status.exclude].characters)
    }
    if status.lower != 0 {
      member += Array(lower[status.exclude].characters)
    }
    if status.number != 0 {
      member += Array(number[status.exclude].characters)
    }
    if status.symbol != 0 {
      member += Array(symbol[status.exclude].characters)
    }
    if (returnCode == 0 && member.count == 0) {
      member = Array(lower[status.exclude].characters) + Array(number[status.exclude].characters)
    }
    if (returnCode == 0 && length == 0) {
      length = 8
    }
    return (member, length, returnCode)
  }
}

88行目などにあるように、Array()初期化子を使って配列に要素を加えています。こうすることで文字列型のデータを文字型の配列に変換しました。

テストはこんな感じ。

#! /usr/bin/swift
import Foundation
let testCase: [(condition: String, arguments: [String], result: String)] =
  [("No option -> ", ["./test-Condition"], "abcdefghijklmnopqrstuvwxyz0123456789-8-0"),
  ("Specified correct length(10) -> ", ["./test-Condition", "10"], "abcdefghijklmnopqrstuvwxyz0123456789-10-0"),
  ("Specified invalild length(-10) -> ", ["./test-Condition", "-10"], "-0-9"),
  ("Specified invalild length(0.5) -> ", ["./test-Condition", "0.5"], "-0-9"),
  ("Specified duplicated length(10 5) -> ", ["./test-Condition", "10", "5"], "abcdefghijklmnopqrstuvwxyz0123456789-5-0"),
  ("Specified correct switch(-a) -> ", ["./test-Condition", "-a"], "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~-8-0"),
  ("Specified correct switch(-ax) -> ", ["./test-Condition", "-ax"], "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{}~-8-0"),
  ("Specified correct switch(-a -x) -> ", ["./test-Condition", "-a", "-x"], "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{}~-8-0"),
  ("Specified correct switch(-u) -> ", ["./test-Condition", "-u"], "ABCDEFGHIJKLMNOPQRSTUVWXYZ-8-0"),
  ("Specified correct switch(-ux) -> ", ["./test-Condition", "-ux"], "ABCDEFGHJKLMNPQRSTUVWXYZ-8-0"),
  ("Specified correct switch(-u -x) -> ", ["./test-Condition", "-u", "-x"], "ABCDEFGHJKLMNPQRSTUVWXYZ-8-0"),
  ("Specified correct switch(-l) -> ", ["./test-Condition", "-l"], "abcdefghijklmnopqrstuvwxyz-8-0"),
  ("Specified correct switch(-lx) -> ", ["./test-Condition", "-lx"], "abcdefghijkmnopqrstuvwxyz-8-0"),
  ("Specified correct switch(-l -x) -> ", ["./test-Condition", "-l", "-x"], "abcdefghijkmnopqrstuvwxyz-8-0"),
  ("Specified correct switch(-n) -> ", ["./test-Condition", "-n"], "0123456789-8-0"),
  ("Specified correct switch(-nx) -> ", ["./test-Condition", "-nx"], "23456789-8-0"),
  ("Specified correct switch(-n -x) -> ", ["./test-Condition", "-n", "-x"], "23456789-8-0"),
  ("Specified correct switch(-s) -> ", ["./test-Condition", "-s"], "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~-8-0"),
  ("Specified correct switch(-sx) -> ", ["./test-Condition", "-sx"], "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{}~-8-0"),
  ("Specified correct switch(-s -x) -> ", ["./test-Condition", "-s", "-x"], "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{}~-8-0"),
  ("Specified correct switch(-x) -> ", ["./test-Condition", "-x"], "abcdefghijkmnopqrstuvwxyz23456789-8-0"),
  ("Specified invalild switch(-A) -> ", ["./test-Condition", "-A"], "-0-9"),
  ("Specified correct switch(-v) -> ", ["./test-Condition", "-v"], "-0-1"),
  ("Specified correct switch(-h) -> ", ["./test-Condition", "-h"], "-0-2"),
  ("Specified correct switch(-a) and length(10) -> ", ["./test-Condition", "-a", "10"], "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~-10-0")]
var condition: (member:[Character], length:Int, status:Int32)
var result: String
var strings: String
for var i in 0..<testCase.count {
  strings = ""
  print(testCase[i].condition, terminator:"")
  condition = Condition().get(arguments:testCase[i].arguments)
  for n in condition.member {
    strings += "\(n)"
  }
  result = "\(strings)-\(condition.length)-\(condition.status)"
  if result == testCase[i].result {
    print("\u{001B}[0;32mOK\u{001B}[0;30m")
  } else {
    print("\u{001B}[0;31mNG\nCorrect\t\(testCase[i].result)\nResult\t\(result)\u{001B}[0;30m")
  }
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です