【原创】C#初级教程学习笔记004-流程控制

 其他路径:

CSDN: https://blog.csdn.net/wodehao0808

微信公众号:程序喵星人

更多资源和视频教程,QQ:1902686547

4. 流程控制

4.1 关系运算符

 

4.2 逻辑运算符

 

4.3 位运算符

 

 

 

4.4 goto语句

  goto 语句将执行转移到语句块中的另一个标签。

4.5 Example:关系运算符

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

// 关系运算符

namespace Lesson_3_1

{

    class Program

    {

        static void Main(string[] args)

        {

            // example_1

            int iScore = 90;

            bool bResult = iScore > 30;  // 比较运算返回一个bool值,真为true,假为false

            Console.WriteLine("bResult = " + bResult);

            // example_2

            int iNum1 = 56;

            int iNum2 = 36;

            bool bRet1 = iNum1 == iNum2;  // false

            bool bRet2 = iNum1 != iNum2;  // true

            bool bRet3 = iNum1 > iNum2;   // true

            bool bRet4 = iNum1 < iNum2;   // false

            bool bRet5 = iNum1 >= iNum2;  // true

            bool bRet6 = iNum1 <= iNum2;  // false

            Console.WriteLine("bRet1 = " + bRet1);

            Console.WriteLine("bRet2 = " + bRet2);

            Console.WriteLine("bRet3 = " + bRet3);

            Console.WriteLine("bRet4 = " + bRet4);

            Console.WriteLine("bRet5 = " + bRet5);

            Console.WriteLine("bRet6 = " + bRet6);

            // example_3

            bool b = true;

            bool b2 = false;

            bool bRes1 = b & b2;  // false

            bool bRes2 = b | b2;  // true

            bool bRes3 = b ^ b2;  // true

            bool bRes4 = !b;      // false

            bool bRes5 = (b && b2);  // false

            bool bRes6 = (b || b2);  // true

            Console.WriteLine("bRes1 = " + bRes1);

            Console.WriteLine("bRes2 = " + bRes2);

            Console.WriteLine("bRes3 = " + bRes3);

            Console.WriteLine("bRes4 = " + bRes4);

            Console.WriteLine("bRes5 = " + bRes5);

            Console.WriteLine("bRes6 = " + bRes6);

            // example_4: goto

            int iCount = 90;

            goto myGotoLabel;  // 跳转到 myGotoLabel标签处继续执行代码,这样 ++iCount 将不会执行

            ++iCount;

            myGotoLabel:

                Console.WriteLine("iCount = " + iCount);  // ++iCount 不会执行,所以输出结果是90

            // 对数字1到5进行迭代,模拟for循环:

            int i = 1;

            startLoop:

                if (i <= 5)

                {

                    Console.Write(i + " ");

                    i++;

                    goto startLoop;

                }

            Console.ReadKey();

        }

    }

}

4.6 判断语句

4.6.1 if语句

       if (<A>)

  {

    // 语句块A

  }

  else

  {

    // 语句块else

  }

  如果<A>为真,则执行语句块A;否则执行语句块else。

  if(<A>)

  {

    // 语句块A

  }

  else if (<B>)

  {

    // 语句块B

  }

  ...

  else

  {

    // 语句else

  }

  如果<A>为真,则执行语句块A;否则判断<B>,如果<B>为真,则执行语句块B;否则...,如果所有if里面的条件都不满足,则执行语句块else。

4.6.2 :?语句

       语法:

    <test> ? <resultfTrue> : <resultIfFalse>;

  如果<test>为真,则返回将结果<resultIfTrue>;否则返回结果<resultIfFalse>。

  例如:

    int i = 10;

    int count = i > 9? i : -1; // 结果是10

    int m = 8;

    int num = m > 9 ? m : -1; // 结果是-1

4.6.3 Example: if 语句,和 ?:语句

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

// if 语句,和 ?:语句

namespace Lesson_3_2

{

    class Program

    {

        static void Main(string[] args)

        {

            // example_1: if

            Console.WriteLine("请输入分数:");

            int iScore = Convert.ToInt32(Console.ReadLine());

            if (iScore >= 60)

            {

                Console.WriteLine("及格");

            }

            else

            {

                Console.WriteLine("未及格");

            }

            // example_2: ?:

            Console.WriteLine("请输入语文分数:");

            int iYWScore = Convert.ToInt32(Console.ReadLine());

            string strOut = iYWScore >= 90 ? "语文及格" : "语文未及格";

            Console.WriteLine("语文分数结果是(90分及格):" + strOut);

            // example_3: if...if else ... if else ... else

            Console.WriteLine("请输入英语分数(0~150):");

            int iYYScore = Convert.ToInt32(Console.ReadLine());

            string str = "";

            if (iYYScore >= 130)

            {

                str = "英语优秀";

            }

            else if (iYYScore >= 100)

            {

                str = "英语良好";

            }

            else if (iYYScore > 90)

            {

                str = "英语一般";

            }

            else

            {

                str = "英语偏科";

            }

            Console.WriteLine("英语评价是(总分150):" + str);      

            Console.ReadKey();

        }

    }

}

4.6.4 switch语句

       语法:

    switch(<test>)

    {

    case A:

      ...

      break;

    case B:

      ...

      break;

    ...

    default:

      ...

      break;

    }

  当<test>中的内容,与case中的条件相匹配时,就会执行case中的语句块。break会终止switch继续向下进行并退出switch语句。

  default,当所有case中的条件都不满足时,就会执行default中的语句块。

  case允许多个条件判断通过后,执行同一个语句块。例如:

    int i = 2;

    swtich(i)

    {

    case 0:

    case 1:

    case 2:

    case 3:

      // 以上4个条件满足任意一个,都执行该语句块

      Console.WriteLine("小于4的数");

      break;

    case 4:

      Console.WriteLine("等于4的数");

      break;

    case 5:

    case 6:

      // 以上2个条件满足任意一个,都执行该语句块

      Console.WriteLine("大于4,小于7的数");

      break;

    default:

      Console.WriteLine("大于6的数");

      break;

    }

4.6.5 Example: switch

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

// switch

namespace Lesson_3_3

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("请输入月份(1-12):");

            int iMonth = Convert.ToInt32(Console.ReadLine());

            switch (iMonth)

            {

                case 1:

                case 2:

                case 3:

                    Console.WriteLine("春");

                    break;

                case 4:

                case 5:

                case 6:

                    Console.WriteLine("夏");

                    break;

                case 7:

                case 8:

                case 9:

                    Console.WriteLine("秋");

                    break;

                case 10:

                case 11:

                case 12:

                    Console.WriteLine("冬");

                    break;

                default:

                    Console.WriteLine("输入的月份有误,输入的月份是:" + iMonth);

                    break;

            }

            Console.WriteLine("请输入方向键(a:左,s:下,d:右,w:上):");

            char ch = Convert.ToChar(Console.ReadLine().ToLower());

            switch (ch)

            {

                case 'a':

                    Console.WriteLine("向左");

                    break;

                case 's':

                    Console.WriteLine("向下");

                    break;

                case 'd':

                    Console.WriteLine("向右");

                    break;

                case 'w':

                    Console.WriteLine("向上");

                    break;

                default:

                    Console.WriteLine("输入的方向有误,输入的方向是:" + ch);

                    break;

            }

            Console.ReadKey();

        }

    }

}

4.7 循环语句

4.7.0 死循环

       死循环:

    循环会一直执行,永不停止。

  例如:

    while( true ) // 条件永远为真,循环一直执行不会停止,即死循环。

    { }

4.7.1 do...while循环

        语法:

    do

    {

      // 循环体

    } while(<条件>);

  注意:

    1.循环体一定会执行一次;

    2.while后面有分号 ";" ,容易遗忘;

  do...while循环,是先执行一次循环体,再进行条件判断;如果条件为真,则继续执行循环体,直到条件为假(false)退出循环。

4.7.2 while循环

       语法:

    while(<条件>)

    {

      // 循环体

    }

  while循环,先进行条件判断,如果为真,就执行循环体,直到条件为假(false)退出循环。

4.7.3 for循环

       for循环语法:

    for (init; condition; increment)

    {

      // 循环体

    }

  for 循环的控制流:

    1.init会首先被执行,且只会执行一次。这一步允许声明并初始化任何循环控制变量。也可以不在这里写任何语句,只要有一个分号出现即可。

    2.接下来,会判断 condition。如果为真,就执行循环体。如果为假,则不执行循环体,退出循环语句;

    3.在执行完 for 循环主体后,控制流会跳回上面的 increment 语句。该语句允许你更新循环控制变量。该语句可以留空,只要在条件后有一个分号出现即可。

    4.条件再次被判断。如果为真,则执行循环,这个过程会不断重复(循环主体,然后增加步值,再然后重新判断条件)。在条件变为假时,for 循环终止。

  例如:

    // 1

    for (int i = 1; i < 9; ++i)

    {

      Console.WriteLine(i);

    }

    // 2

    int i = 1; // 初始化写在外面。

    for (; i < 9; ++i)

    {

      Console.WriteLine(i);

    }

    // 3

    int i = 1;  

    // 初始化写在外面。

    for (; i < 9; )

    {

      Console.WriteLine(i);

      ++i; // 控制变量的数值的修改,写在循环体里面,没有写在for后面。

    } 

4.7.4 foreach循环

       使用foreach可以迭代数组或者一个集合对象。

  不要在foreach中试图增删,这样会报异常!需使用for!

  以下实例有三个部分:

    1.通过 foreach 循环输出整型数组中的元素。

    2.通过 for 循环输出整型数组中的元素。

    3.foreach 循环设置数组元素的计算器。

  int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 };

  foreach (int element in fibarray)

  {

    System.Console.WriteLine(element);

  }

  System.Console.WriteLine();

  // 类似 foreach 循环

  for (int i = 0; i < fibarray.Length; i++)

  {

    System.Console.WriteLine(fibarray[i]);

  }

  System.Console.WriteLine();

  // 设置集合中元素的计算器

  int count = 0;

  foreach (int element in fibarray)

  {

    count += 1;

    System.Console.WriteLine("Element #{0}: {1}", count, element);

  }

  System.Console.WriteLine("Number of elements in the array: {0}", count);

4.7.5 循环控制语句

       1.break语句

    break:

    终止当前循环语句;

  2.continue语句

    continue:

    跳过本次循环体执行,进入下一次的循环逻辑处理;

  3.return语句

    return:

    终止函数所有逻辑,退出该函数。

4.7.6 Example:循环语句

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

// 循环语句

namespace Lesson_3_4

{

    class Program

    {

        static void Main(string[] args)

        {

            // do...while

            do

            {

                Console.WriteLine("do...while 循环体一定会执行一次");

            } while (false);

            int i = 1;

            do

            {

                Console.WriteLine("do...while i = " + i);

                ++i;

            } while (i < 10);

            // while

            i = 1;

            while (i < 10)

            {

                Console.WriteLine("while  i = " + i);

                ++i;

            }

            // for

            i = 1;

            for (; i < 10; ++i)

            {

                Console.WriteLine("for 1  i = " + i);

            }

            i = 1;

            for (; i < 10; )

            {

                Console.WriteLine("for 2  i = " + i);

                ++i;

            }

            for (int j = 1; j < 10; ++j)

            {

                Console.WriteLine("for 3  j = " + j);

            }

            // break

            for (int j = 1; j < 10; ++j)

            {

                if (5 == j)

                {

                    break;  // 结束循环  // 这里是5及5以上的数字不会输出

                }

                Console.WriteLine("break  j = " + j);

            }

            Console.WriteLine("break,这里会执行");

            // break

            for (int j = 1; j < 10; ++j)

            {

                if (5 == j)

                {

                    continue;  // 结束本次循环体,继续下一个条件判断  // 这里是 数字5 不会输出

                }

                Console.WriteLine("continue  j = " + j);

            }

            Console.WriteLine("continue,这里会执行");

            // return

            for (int j = 1; j < 10; ++j)

            {

                if (5 == j)

                {

                    return;  // 结束循环,并退出函数  // 这里是5及5以上的数字不会输出

                }

                Console.WriteLine("continue  j = " + j);

            }

            Console.WriteLine("return了,这里和该函数后面的代码都不会执行了");

            Console.ReadKey();

        }

    }

}

4.8 练习

练习1

编写一个程序,对输入的4个整数,求出其中的最大值和最小值,并显示出来。

练习2

让用户输入两个整数,然后再输入0-3之间的一个数,0代表加法,1代表减法,2代表乘法,3代表除法,计算这两个数字的结果。

练习3

  求出1~1000之间的所有能被7整除的数,并计算和输出每5个的和。

练习4

编写一个控制台程序,分别输出1~100之间的平方、平方根。

练习6

  编程输出1~100中能被3整除但不能被5整除的数,并统计有多少个这样的数。

练习7

编程输出1000以内的所有素数

练习8

  编程输出九九乘法表。

练习9

编写一个掷筛子100次的程序,并打印出各种点数的出现次数。

练习10

  一个控制台应用程序,输出1~5的平方值,要求:用for语句实现。用while语句实现。用do-while语句实现。

练习11

一个控制台应用程序,要求用户输入5个大写字母,如果用户输入的信息不满足要求,提示帮助信息并要求重新输入。

练习12

  一个控制台应用程序,要求完成写列功能。

    1)接收一个整数n。

    2)如果接收的值n为正数,输出1~n间的全部整数。

    3)如果接收的值n为负值,用break或者return退出程序。

    4)如何n为0的话 转到1继续接收下一个整数。

练习13

一个控制台应用程序,求1000之内的所有“完数”。所谓“完数”是指一个数恰好等于它的所有因子之和。例如6是完数,因为6=1+2+3。

4.8.1 Example:练习1、2

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

// 练习1、练习2

namespace Lesson_3_5

{

    class Program

    {

        static void Main(string[] args)

        {

            // example_1: 编写一个程序,对输入的4个整数,求出其中的最大值和最小值,并显示出来。

            Console.WriteLine("输入4个整数,请输入第一个整数:");

            int iNum1 = Convert.ToInt32(Console.ReadLine());

            Console.WriteLine("输入4个整数,请输入第二个整数:");

            int iNum2 = Convert.ToInt32(Console.ReadLine());

            Console.WriteLine("输入4个整数,请输入第三个整数:");

            int iNum3 = Convert.ToInt32(Console.ReadLine());

            Console.WriteLine("输入4个整数,请输入第四个整数:");

            int iNum4 = Convert.ToInt32(Console.ReadLine());

            int iMax = iNum1, iMin = iNum2;  // 最大数 和 最小数

            if (iMax < iNum2)

            {

                iMax = iNum2;

            }

            if (iMax < iNum3)

            {

                iMax = iNum3;

            }

            if (iMax < iNum4)

            {

                iMax = iNum4;

            }

            if (iMin > iNum2)

            {

                iMin = iNum2;

            }

            if (iMin > iNum3)

            {

                iMin = iNum3;

            }

            if (iMin > iNum4)

            {

                iMin = iNum4;

            }

            Console.WriteLine("最大数:{0},最小数:{1}", iMax, iMin);

            // example_2: 让用户输入两个整数,然后再输入0-3之间的一个数,0代表加法,1代表减法,2代表乘法,3代表除法,计算这两个数字的结果

            Console.WriteLine("输入两个整数,请输入第一个整数:");

            int iInt1 = Convert.ToInt32(Console.ReadLine());

            Console.WriteLine("输入两个整数,请输入第二个整数:");

            int iInt2 = Convert.ToInt32(Console.ReadLine());

            Console.WriteLine("请输入0-3之间的一个数:");

            int iOperator = Convert.ToInt32(Console.ReadLine());

            int iTemp = 0;

            switch (iOperator)

            {

                case 0:

                    iTemp = iInt1 + iInt2;

                    break;

                case 1:

                    iTemp = iInt1 - iInt2;

                    break;

                case 2:

                    iTemp = iInt1 * iInt2;

                    break;

                case 3:

                    iTemp = iInt1 / iInt2;

                    break;

                default:

                    Console.WriteLine("输入的操作数有误,不是0-3。");

                    break;

            }

            Console.WriteLine("执行操作后的结果为:" + iTemp);

            Console.ReadKey();

        }

    }

}

4.8.2 Example:练习3、4

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

// 练习3、4

namespace Lesson_3_6

{

    class Program

    {

        static void Main(string[] args)

        {

            // example_3: 求出1~1000之间的所有能被7整除的数,并计算和输出每5个的和。

            int iCount = 0, iSum = 0;

            for (int i = 1; i < 1001; ++i)

            {

                if(i % 7 == 0)

                {

                    Console.WriteLine("能被7整除的数:" + i);

                    iSum += i;

                    ++iCount;

                    if (5 == iCount)

                    {

                        Console.WriteLine("每5个的和:" + iSum);

                        iSum = 0;

                        iCount = 0;

                    }

                }

            }

            Console.WriteLine("example_3 finish------------------------------------------------");

            // example_4: ,编写一个控制台程序,分别输出1~100之间的平方、平方根。

            for (int i = 1; i < 101; ++i)

            {

                Console.WriteLine(i + "的平方是:" + i * i);

                // double d = Math.Sqrt(i);

                Console.WriteLine(i + "的平方根是:" + Math.Sqrt(i));  // Math.Sqrt方法为:求平方根的方法。

            }

            Console.WriteLine("example_4 finish------------------------------------------------");

            Console.ReadKey();

        }

    }

}

4.8.3 Example:练习6、7

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

// 练习6、7

namespace Lesson_3_7

{

    class Program

    {

        static void Main(string[] args)

        {

            // example_6: 编程输出1~100中能被3整除但不能被5整除的数,并统计有多少个这样的数。

            int iCount = 0;

            for (int i = 1; i < 101; ++i)

            {

                if (i % 3 == 0 && i % 5 != 0)

                {

                    Console.WriteLine("能被3整除但不能被5整除的数:" + i);

                    ++iCount;

                }

            }

            Console.WriteLine("总计有:" + iCount);

            Console.WriteLine("example_6 finish -----------------------------------------");

            // example_7: 编程输出1000以内的所有素数

            for (int i = 2; i < 1001; ++i)

            {

                bool b = true;

                for (int j = 2; j < i; ++j)

                {

                    if (i % j == 0)  // 素数只能被1和自身整除,不能被其他数整除。所以,如果能被其他数整除,就不是素数。

                    {

                        b = false;

                        break;

                    }

                }

                if (b)

                {

                    Console.WriteLine("素数是:" + i);

                }

            }

            Console.WriteLine("example_7 finish -----------------------------------------");

            Console.ReadKey();

        }

    }

}

4.8.4 Example:练习8、9

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

// 练习8、9

namespace Lesson_3_8

{

    class Program

    {

        static void Main(string[] args)

        {

            // example_8: 编程输出九九乘法表。

            for (int i = 1; i < 10; ++i)

            {

                for (int j = i; j < 10; ++j)

                {

                    Console.Write("{0}*{1}={2} ", i, j, i * j);

                }

                Console.WriteLine();

            }

            Console.WriteLine("example_8 finish ----------------------------------------");

            // example_9: 编写一个掷筛子100次的程序,并打印出各种点数的出现次数。

            int iNum1 = 0, iNum2 = 0, iNum3 = 0, iNum4 = 0, iNum5 = 0, iNum6 = 0;

            int iPointNum = 0;

            Random rand = new Random();

            for (int i = 0; i < 100; ++i)

            {

                iPointNum = rand.Next(1, 7);  // 随机数,前包后不包[1,7),获得的是随机1~6的数

                switch (iPointNum)

                {

                    case 1:

                        ++iNum1;

                        break;

                    case 2:

                        ++iNum2;

                        break;

                    case 3:

                        ++iNum3;

                        break;

                    case 4:

                        ++iNum4;

                        break;

                    case 5:

                        ++iNum5;

                        break;

                    case 6:

                        ++iNum6;

                        break;

                }        

            }

            Console.WriteLine("1出现的次数是:" + iNum1);

            Console.WriteLine("2出现的次数是:" + iNum2);

            Console.WriteLine("3出现的次数是:" + iNum3);

            Console.WriteLine("4出现的次数是:" + iNum4);

            Console.WriteLine("5出现的次数是:" + iNum5);

            Console.WriteLine("6出现的次数是:" + iNum6);

            Console.WriteLine("example_9 finish ----------------------------------------");

            Console.ReadKey();

        }

    }

}

4.8.5 Example:练习10、11

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

// 练习10、11

namespace Lesson_3_9

{

    class Program

    {

        static void Main(string[] args)

        {

            // example_10: 一个控制台应用程序,输出1~5的平方值,要求:用for语句实现。用while语句实现。用do-while语句实现。

            for (int i = 1; i < 6; ++i)

            {

                Console.WriteLine("for {0}的平方值是:{1}", i, i * i);

            }

            int j = 1;

            while (j < 6)

            {

                Console.WriteLine("while {0}的平方值是:{1}", j, j * j);

                ++j;

            }

            int m = 1;

            do

            {

                Console.WriteLine("do...while {0}的平方值是:{1}", m, m * m);

                ++m;

            } while (m < 6);

            Console.WriteLine("example_10 finish-----------------------------------------");

            // example_11: 一个控制台应用程序,要求用户输入5个大写字母,如果用户输入的信息不满足要求,提示帮助信息并要求重新输入。

            bool bNeedInput = true;

            Console.WriteLine("请输入字符串:");

            while (bNeedInput)

            {

                bNeedInput = false;

                string str = Console.ReadLine();

                if (str.Length == 5)

                {

                    for (int i = 0; i < 5; ++i)

                    {

                        if (str[i] >= 'A' && str[i] <= 'Z')

                        {

                            //

                        }

                        else

                        {

                            bNeedInput = true;

                            break;

                        }

                    }

                }

                else

                {

                    bNeedInput = true;

                }

               

                if (bNeedInput)

                {

                    Console.WriteLine("请重新输入字符串:");

                }

                else

                {

                    Console.WriteLine("符合5个大写字母");

                }

            }

            Console.ReadKey();

        }

    }

}

4.8.6 Example:练习12、13

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

// 练习12、13

namespace Lesson_3_10

{

    class Program

    {

        static void Main(string[] args)

        {

            // example_12:

            /*

             * 一个控制台应用程序,要求完成写列功能。

                   1)接收一个整数n。

                   2)如果接收的值n为正数,输出1~n间的全部整数。

                   3)如果接收的值n为负值,用break或者return退出程序。

                   4)如何n为0的话 转到1继续接收下一个整数。

             */

            bool b = true;

            while (b)

            {

                b = false;

                Console.WriteLine("请输入一个整数:");

                int iNum = Convert.ToInt32(Console.ReadLine());

                if (iNum > 0)

                {

                    for(int i = 1; i <= iNum; ++i)

                    {

                        Console.WriteLine("1~n的全部整数:" + i);

                    }

                }

                else if (iNum <0)

                {

                    break;

                }

                else

                {

                    b = true;

                }

            }

            Console.WriteLine("example_12 finish-------------------------------");

            // example_13: 一个控制台应用程序,求1000之内的所有“完数”。所谓“完数”是指一个数恰好等于它的所有因子之和。例如6是完数,因为6=1+2+3。

            int iSum = 0;

            string str = "";

            for (int i = 1; i < 1001; ++i)

            {

                iSum = 0;

                str = "";

                for (int j = 1; j < i - 1; ++j)

                {

                    if (i % j == 0)

                    {

                        if (string.IsNullOrEmpty(str))

                        {

                            str = j + "";

                        }

                        else

                        {

                            str += "+" + j;

                        }

                        iSum += j;

                       

                    }

                }

                if (iSum == i)

                {

                    Console.WriteLine("完数:{0} = {1}", i, str);

                }               

            }

            Console.WriteLine("example_13 finish-------------------------------");

            Console.ReadKey();

        }

    }

}

原文地址:https://www.cnblogs.com/wodehao0808/p/14635640.html