import UIKit

class HomeViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        /*
         [打印输出]
         Swift使用print函数打印输出,函数是一个全局函数,完整的函数签名为:
         public func print(items: Any..., separator: String = default, terminator: String = default)
         */
        print("输出");
        for i in 10...20 {
            // 默认输出会换行
            print(i);
            // 不换行输出,各字符间以逗号分隔开
            print(i, terminator: ",")
        }

        /*
         [分号]
         Swift不要求在每行语句的结尾使用分号,但当你在同一行书写多条语句时,必须用分号。
         */
        let firstString = "Hello World!"; print(firstString);
        
        /*
         [标识符]
         标识符就是给变量、常量、方法、函数、枚举、结构体、类、协议等指定的名字。构成标识符的字母均有一定的规范,Swift语言中标识符的命名规则如下:
            区分大小写;
            标识符首字符可以以下划线或者字母开始,但不能是数字;
            标识符中其他字符可以是下划线、字母或数字。
         如果一定要使用关键字作为标识符,可以在关键字前后添加重音符号(`);
         */
        let `let` = "let";
        print(`let`);
        
        /*
         [关键字]
         与声明有关的关键字:
         class          deinit          enum            extension
         func           import          init            internal
         let            operator        private         protocol
         public         static          struct          subscript
         typealias      var
         与语句有关的关键字:
         break          case            continue        default
         do             else            fallthrough     for
         if             in              return          switch
         where          while
         表达式和类型关键字:
         as             dynamicType     false           is
         nil            self            Self            super
         true           _COLUMN_        _FILE_          _FUNCTION_
         _LINE_
         在特定上下文中使用的关键字:
         associativity  convenience     dynamic         didSet
         final          get             infix           inout
         lazy           left            mutating        none
         nonmutating    optional        override        postfix
         precedence     prefix          Protocol        required
         right          set             Type            unowned
         weak           willSet
         */
        
        /*
         [空格]
         编码规范推荐使用这种写法:
            let x = 1 + 1;
         这样书写也不会报错
            let x = 1+1;
         在Swift中,运算符不能直接跟在变量或常量的后面,例如下面的代码会报错:
         let x= 1 + 1;
         let x =1 + 1;
         let x = 1+ 1;
         let x = 1 +1;
         */

        /*
         [Int]
            整数类型Int,长度与当前平台的原生字长相同:
            在32位平台上,Int和Int32长度相同。
            在64位平台上,Int和Int64长度相同。
         
         [UInt]
            无符号类型UInt,长度与当前平台的原生字长相同:
         
         [Float/Double]
            浮点数是有小数部分的数字,比如 3.1415926,0.9,-9.15。
            浮点类型比整数类型表示的范围更大,可以存储比 Int 类型更大或者更小的数字。
            Double精确度很高,至少有15位数字,而Float最少只有6位数字。
            Float 表示32位浮点数。
            Double 表示64位浮点数。
         
         [Bool]
            布尔值指逻辑上的值,只能是true和false。
         
         [Character]
            字符指的是单个字母:"Hello, World!"
         [String]
            字符串是字符的序列集合:"C"
         
         [Optional]
             使用可选类型来处理值可能缺失的情况。可选类型表示有值或没有值。
         */
        // 字符串
        var cTotal = "合计:";
        let cPrice = 10.5;
        // 字符串中可以使用括号与反斜线来插入常量
        print(cTotal+"\(cPrice)元");
        // 追加数组
        cTotal.append(String(cPrice));
        // 追加字符串
        cTotal.append("元");
        print(cTotal);
        /*
         [数值范围]
         变量类型的最大最小值
         类型     大小(字节)     区间值
         Int8     1 字节      -128 到 127
         UInt8    1 字节      0 到 255
         Int32    4 字节      -2147483648 到 2147483647
         UInt32   4 字节      0 到 4294967295
         Int64    8 字节      -9223372036854775808 到 9223372036854775807
         UInt64   8 字节      0 到 18446744073709551615
         Float    4 字节      1.2E-38 到 3.4E+38 (~6 digits)
         Double   8 字节      2.3E-308 到 1.7E+308 (~15 digits)
         */
        
        /*
         [类型别名]
         类型别名是为当前类型定义的另一个名字,通过使用typealias关键字来定义。
         */
        typealias newInt = Int;
        var curInt:newInt = 35;
        curInt = 36;
        print(curInt);
        
        /*
         [类型安全]
         Swift是一个类型安全(type safe)的语言,它会在编译代码时进行类型检查(type checks)并把不匹配的类型标记为错误。
         var stringA = "strA";
         stringA = 10; // 报错 Cannot assign value of type 'Int' to type 'String'
         print(stringA);
         */
        
        /*
         [类型推断]
         标准格式声明常量和变量时需要指定参数的类型,如果没有指定类型Swift会使用类型推断(type inference)来选择合适的类型。
         */
        let dInt:Int = 56;
        let eInt = 100;
        let fValue = 0.618 + 1;
        print(String(dInt)+String(eInt)+String(fValue));
        
        /*
         [常量]
         常量使用关键字let来声明,常量定义时必须初始值。
         常量的值一旦设定就不能改变,而变量的值可以随意更改。
         常量可以是任何的数据类型:
            整型常量、浮点型常量、字符常量、字符串常量、枚举类型的常量。
         */
        let gInt = 25;
        let gFloat:Float = 0.618;
        // 两参数同一行并且用一个空格隔开。输出:25 0.618
        print(gInt,gFloat);
        // 字符串中可以使用括号与反斜线来插入常量
        print("\(gInt)和\(gFloat)");
        
        /*
         [变量]
         变量使用关键字var来声明,意思是告诉编译器在内存中的哪个位置上为变量创建多大的存储空间。
         每个变量都指定了特定的类型,该类型决定了变量占用内存的大小,不同的数据类型也决定可存储值的范围。
         */
        var hInt = 0;
        hInt = 23;
        print(hInt+1);
        var hFloat:Float;
        hFloat = 0.618;
        print(hFloat+1);
        
        /*
         [字面量]
         指特定的数字、字符串或者布尔值,能够直接指出自己的类型并为变量进行赋值的值。
         */
        let iInt = 1;
        let iFloat = 2.2;
        let iString = "3";
        let iBool = true;
        
        // 整型字面量
        // 可以是一个十进制,二进制,八进制或十六进制常量。 二进制前缀为 0b,八进制前缀为 0o,十六进制前缀为 0x,十进制没有前缀。
        let decInt = 100;
        let binInt = 0b1100100;
        let octInt = 0o144;
        let hexInt = 0x64;
        
        // 浮点型字面量
        // 浮点型字面量有整数部分,小数点,小数部分及指数部分。浮点型字面量默认用十进制表示(无前缀),也可以用十六进制表示(加前缀 0x)。
        let decDouble1 = 0.618;
        let decDouble2 = 0.618e2;   // 0.618x10^2
        let decDouble3 = -0.618e-2; // -0.618x10^-2
        let hexDouble1 = 0x3p0;
        print(hexDouble1);  // 3x2^0 输出:3.0
        let hexDouble2 = 0x3p1;
        print(hexDouble2);  // 3x2^1 输出:6.0
        let hexDouble3 = 0x3p-1;
        print(hexDouble3);  // 3x2^-1 输出:1.5
        let hexDouble4 = 0x3.0p0;
        print(hexDouble4);  // 3.0x2^0 输出:3.0
        // 一脸懵逼!搞不懂下面怎么计算的
        let hexDouble5 = 0x3.2p0;
        print(hexDouble5);  // (3+0.125)x2^0 输出:3.125
        let hexDouble6 = 0x3.2p1;
        print(hexDouble6);  // (3+0.125)x2^1 输出:6.25
        let hexDouble7 = 0x3.3p0;
        print(hexDouble7);  // (3+0.1875)x2^0 输出:3.1875
        let hexDouble8 = 0x3.3p2;
        print(hexDouble8);  // (3+0.1875)x2^2 输出:12.75
        
        // 字符串型字面量
        // 由被包在双引号中的一串字符组成,不能包含未转义的双引号(")、未转义的反斜线(\)、回车符或换行符。
        let jString = "\"关于\'XX\'的会议记录\"\n\t内容\\和\\n";
        print(jString);

        // 布尔型字面量
        // 布尔值字面量有三个值,true 表示真,false 表示假。
        var kBool:Bool = false;
        print(kBool);
        kBool = true;
        print(kBool);

        /*
         [可选(Optionals)类型]
         用于处理值缺失的情况,判断声明的可选类型是否有值。
         任何类型都可以明确声明为(或者隐式转换)可选类型。
         Optional是一个含有两种情况的枚举,None和Some(T),用来表示可能有或可能没有值。
         后缀?作为命名类型Optional的简写,类型和?之间没有空格。
         var oInt: Int?;
         var oInt1: Optional<Int>;
         */
        // 强制解析
        let pFloat: Float? = 0.5;
        var saveFloat: Float;
        if (pFloat != nil) {
            // 如果一个可选类型的实例包含一个值,你可以用后缀操作符 !来访问这个值
            print(pFloat,"\(pFloat!)"); // 输出:Optional(0.5) 0.5
            saveFloat = pFloat!;
            print(saveFloat);   // 输出:0.5
        } else {
            print("pFloat = nil");
        }
        // 自动解析
        let pString: String! = "值";
        if (pString != nil) {
            // 在声明可选变量时使用感叹号(!)替换问号(?)。这样可选变量在使用时就不需要再加一个感叹号(!)来获取值,它会自动解析。
            print(pString); // 输出:some("值")
            print(pString!);// 输出:值
        } else {
            print("pString = nil");
        }
    }
  
}