Swift开发——循环执行方式

简介: Swift语言中的循环主要包括`for-in`和`while`结构。`for-in`适用于遍历数字区间、字符串和字典,支持使用`stride`函数定制步进。字典遍历时,可以用二元元组`(k, v)`访问键值对。`while`循环有标准形式和`repeat-while`形式,确保至少执行一次循环体。程序示例展示了`for-in`和不同`while`结构的用法,包括计算阶乘、奇数和、加密字符串以及最大公约数和最小公倍数。

image.png


本文将介绍 Swift 语言的循环执行方式



# 01、循环执行方式



在Swift语言中,主要有两种循环执行控制方式: for-in结构和while结构。while结构又细分为当型while结构和直到型while结构,后者称为repeat-while结构。下面首先介绍for-in结构。

循环控制方式for-in结构可用于区间中的整数值遍历、字符串中的字符遍历、字典中的元素遍历等,常用的形式如下。

(1) 典型for-in结构。

image.png


上述for-in结构中,遍历“范围”中的各个“元素”,对于每个“元素”执行“语句组”一次。这里无须为“元素”定义变量类型,自动根据“范围”中的数组类型设定“元素”的数据类型。

如果“元素”使用“_”替换,则表示不关注“范围”中的具体元素,只关注循环次数。表示“范围”的方法可借助运算符“...”和“..<”,或者使用函数stride(from:to:by:)或stride(from:through:by:)实现,两个stride的区别在于前者不包含“to”参数指定的边界,而后者包含“through”参数指定的边界。例如: stride(from:1, to:10, by:3)表示1~10、步长为3生成的序列,即1、4、7,不包含10; stride(from:1, through:10, by:3)表示1~10、步长为3生成的序列,即1、4、7、10,包含10。

for-in结构中的“范围”可以为字符串或字典。

(2) 用于字典遍历的for-in结构。

image.png

在上述for-in结构中,使用“二元元组”作为字典中每个元素的返回值,例如,将二元元组表示为“(k,v)”,则k将对应着字典元素的键值,v将对应着同一个字典元素的值。如果k用“”表示,则将只关心字典元素的值,而不关心它的键值。如果v用“”表示,则将只关心字典元素的键值,而不关心它的值。

程序段1介绍了for-in结构的用法。

程序段1for-in结构的用法实例

image.png


image.png


image.png


程序段1的执行结果如图1所示。

image.png


■ 图3-5程序段3-11的执行结果



下面结合图3-5介绍程序段3-11的执行过程。在程序段3-11中,第2行“var s=1”定义整型变量s,赋初值为1。第3~6行为一个for-in结构,第3行“for e in 1...10”表示e在1~10的10个整数上遍历,即e依次取值1、2、……、10,循环执行第5行“s = e”,这里为计算10的阶乘。第7行“print("10!=",s)”输出10的阶乘的值。

第9行“s=1”令变量s的值为1。第10~13行为一个for-in结构,第10行“for in 1...10”中使用“”作为循环变量,没有指定循环变量的名称,表示该循环只关注循环次数,这里循环10次,计算第12行“s
= 2”,即计算2的10次方。第14行“print("2^10=",s)”输出2的10次方的值。

第16行“s=0”将0赋给变量s。第17~20行为一个for-in结构,第17行“for e in stride(from:1, to:100, by:2)”这里e遍历的序列为1、3、5、……、99,对于每个遍历值执行第19行“s+=e”,即计算100以内的正奇数的和。第21行“print("1+3+...+99=",s)”输出字符串“1+3+...+99=”和s的值。这里循环变量e的作用范围为for-in结构,故在其他的for-in结构中仍然可以使用同名的局部变量e。

第23~32行实现了与第16~21行相同的功能,这里为演示continue语句的用法。第23行“s=0”将0赋给变量s。第24~31行为一个for-in结构,第24行“for e in stride(from:1, through:100, by:1)”表示循环变量e在范围1、2、……、100上遍历取值,对每个e,执行第26~30行,第26~29行为一个if结构,第26行“if e % 2 == 0”如果e为偶数,则执行第28行“continue”,表示跳过for-in结构中continue后面的语句回到第24行执行条件判断,这里跳过第30行回到第24行,即忽略循环变量e为偶数的情况。第32行“print("1+3+...+99=",s)”输出字符串“1+3+...+99=”和s的值。

第34~47行实现了与第16~21行相同的功能,即计算100以内正奇数的和,这里为了演示break语句的用法。第41~44行为一个if结构,如果第41行“if e>=100”的条件为真,则执行第43行break语句,跳出它所在的for-in结构,这里跳转到第47行执行。

现在总结一下continue和break的特点: ①continue和break均可以用于if、switch、for-in和while结构中; ②在循环体中遇到continue,将跳过循环体内continue之后的语句,转到循环开头执行条件判断,开始下一次循环; ③在循环体内遇到break语句,将跳出该循环体,转到循环体外的下一条语句执行; ④对于嵌套的循环体而言,continue和break语句仅对它所在的循环体有效,当有多个嵌套的循环体时,为了明确continue和break作用的循环体,可以为它们所在的循环体开头添加标号,指示continue和break的跳转,这个仅是为了方便程序阅读,第49~62行中演示了这种用法。

第49~62行实现了与第16~21行相同的功能。第50~61行为一个for-in结构,第50行“mylabel:for e in 1...100”在for循环体头部添加了标号mylabel,第54行continue mylabel表示continue执行时要跳转的标号为mylabel; 第58行break mylabel表示break要执行时跳出的循环体为mylabel指示的循环体。

第64行“let p="helloworld"”定义常量p,赋值为“helloworld”。第65行“var c:String=""”定义字符串变量c,赋值为空串。第66行“print("plain=",p)”输出字符串“plain=”和字符串p的值。第67~70行为一个for-in结构,这里实现了凯撒密码,即一个字符用其后的第4个字符替换,第67行“for e in p.unicodeScalars”表示循环变量e在p的Unicode码形式的字符串中遍历各个字符,对于每个e,执行第69行“c+=String(UnicodeScalar((e.value-97+4)%26+97)!)”,这里“e.value”返回e的ASCII值,97为字符a的ASCII值,UnicodeScalar函数返回以整数值参数作为ASCII值对应的字符,这里将每个e变换后的字符转换为字符串添加到c的尾部。第71行“print("cipher=",c)”,输出加密后的密文文本c。第69行中的97可以使用“UnicodeScalar("a").value”替换,可避免去查字符a的ASCII值,这里,“UnicodeScalar("a").value”返回字符a的ASCII值。

第73行“let dic=["Apple":3.5,"Pear":2.7,"Banana":5.2]”定义字典dic。第74~77行为一个for-in结构,第74行“for (k,v) in dic”中,元组(k,v)遍历dic字典的每个元素,其中,k存储遍历到的字典元素的键值,v存储遍历到的字典元素的值,对于每个元组(k,v),执行第76行“print(k,v,terminator:",")”,输出遍历到的键值对。第78行“print()”输出一个空行。

第80行“var t=0.0”定义双精度浮点型变量t,赋值为0.0。第81~84行为一个for-in结构,第81行“for(_,v) in dic”中,只关注从字典dic中遍历到的元素的值,将这个值赋给v,对于每次遍历,执行第83行“t+=v”,这里表示计算字典中所有水果的单价和。第85行“print("Total price:",t)”输出字符串“Total price:”和t的值。

上述介绍的for-in结构的特点在于循环变量的取值范围是确定的,可以准确地推断出循环的次数。而当循环次数不可知时,一般不使用for-in结构,而使用while循环控制结构。while结构分为标准while结构和repeat-while结构两种,其语法如下。

(1) 标准while结构,即当型while结构。

image.png


在上述结构中,当“条件表达式”为真时,循环执行“条件表达式为真时执行的语句组”,直到“条件表达式”为假时跳出while循环体。在“条件表达式为真时执行的语句组”中,一般包含有调整“条件表达式”结果的语句。在标准while结构中,如果“条件表达式”为假,则“条件表达式为真时执行的语句组”可能一次也得不到执行。

(2) repeat-while结构,即直到型while结构。

image.png


在上述结构中,先执行一次“语句组”,再判断“条件表达式”的值,若其为真,则循环执行“语句组”,直到“条件表达式”为假,跳出repeat-while循环体。在repeat-while结构中,表示循环体的“语句组”至少可以被执行一次。

程序段2介绍了while结构的用法,实现了欧几里得求两个整数的最大公约数和最小公倍数的算法。欧几里得算法的基本原理: 设a和b为两个整数,不妨设a>b,则gcd(a,b)=gcd(b, a mod b),即a与b的最大公约数等于b与a模b的最大公约数,通过反复求模运算,最后可以表示为gcd(r,0),则r为a与b的最大公约数,最小公倍数为a*b/r。现在发现这个2000多年前的算法是求两数的最大公约数最快的方法。

程序段 2 while 结构用法实例

image.png


image.png


程序段2的执行结果如图2所示。

image.png


■ 图2 程序段2的执行结果

下面结合图2介绍程序段2的执行过程。在程序段3-12中,第3行“var a0=6525”定义整型变量a0,赋初值为6525。第4行“var b0=81450”定义整型变量b0,赋初值为81450。第5行“var a,b:Int”定义整型变量a和b。

第6~9行为一个if结构,第6行“if a0”若a0小于b0,则执行第8行“(a0,b0)=(b0,a0)”将a0和b0的值对换。第10行“(a,b)=(a0,b0)”将a0赋给a,将b0赋给b。

第11行“var r=1”定义整型变量r,赋初值为1。第12~17行为一个while结构,实现欧几里得算法,第12行“while r>0”当r大于0时,循环执行第14~16行,这里的r保存a除以b的余数,如第14行“r=a % b”所示,然后,第15行“a=b”将b赋给a,第16行“b=r”将r赋给b,进行下一次循环,直到余数r为0。第18行“print("gcd(\(a0),\(b0))=\(a)")”输出a0和b0的最大公约数,第19行“print("lcm(\(a0),\(b0))=\(a0*b0/a)")”输出a0和b0的最小公倍数。

第21~29行实现了与第10~19行相同的功能,这里使用了repeat-while结构。第21行“(a,b)=(a0,b0)”将a0赋给a,将b0赋给b。第22~27行为一个repeat-while结构,循环执行第24~26行直到r小于或等于0。第28、29行依次输出a0和b0的最大公约数和最小公倍数。

第31~43行实现了与第10~19行相同的功能。这里使用了while结构,第31行“(a,b)=(a0,b0)”将a0赋给a,将b0赋给b; 第32行“while true”表示这是一个无限循环,循环执行第34~40行,在无限循环体中,添加了第37~40行的一个if结构,判断r的值是否为0(第37行“if r==0”),如果r为0,则执行第39行break,跳出while循环体,跳至第42行执行,第42行“print("gcd(\(a0),\(b0))=\(a)")”输出a0和b0的最大公约数; 第43行“print("lcm(\(a0),\(b0))=\(a0*b0/a)")”输出a0和b0的最小公倍数。

目录
相关文章
|
3月前
|
Unix 调度 Swift
苹果iOS新手开发之Swift 中获取时间戳有哪些方式?
在Swift中获取时间戳有四种常见方式:1) 使用`Date`对象获取秒级或毫秒级时间戳;2) 通过`CFAbsoluteTimeGetCurrent`获取Core Foundation的秒数,需转换为Unix时间戳;3) 使用`DispatchTime.now()`获取纳秒级精度的调度时间点;4) `ProcessInfo`提供设备启动后的秒数,不表示绝对时间。不同方法适用于不同的精度和场景需求。
68 3
|
11天前
|
安全 Swift iOS开发
探索iOS开发之旅:Swift语言的魅力与挑战
【9月更文挑战第21天】在这篇文章中,我们将一起潜入iOS开发的海洋,探索Swift这门现代编程语言的独特之处。从简洁的语法到强大的功能,Swift旨在让开发者能够以更高效、更安全的方式构建应用程序。通过实际代码示例,我们会深入了解Swift如何简化复杂任务,并讨论它面临的挑战和未来的发展方向。无论你是初学者还是有经验的开发者,这篇文章都将为你提供新的视角和知识。
28 4
|
27天前
|
安全 编译器 Swift
探索iOS开发之旅:Swift编程语言的魅力与挑战
【9月更文挑战第5天】在iOS应用开发的广阔天地中,Swift作为苹果官方推荐的编程语言,以其简洁、高效和安全的特点,成为了开发者的新宠。本文将带领你领略Swift语言的独特魅力,同时探讨在实际开发过程中可能遇到的挑战,以及如何克服这些挑战,成为一名优秀的iOS开发者。
|
27天前
|
设计模式 前端开发 Swift
探索iOS开发:Swift与Objective-C的较量
在这篇文章中,我们将深入探讨iOS开发的两大编程语言——Swift与Objective-C。我们将分析这两种语言的特性、优势和局限性,并讨论它们在现代iOS开发中的应用。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和建议。
39 3
|
2月前
|
移动开发 安全 Swift
探索iOS开发:从零开始的Swift之旅
【8月更文挑战第31天】本文将带你开启一段Swift编程语言的奇幻旅程,通过简单易懂的方式介绍Swift的基本概念和编程实践。我们将一起构建一个简单的iOS应用,体验从代码到界面的转变。无论你是编程新手还是希望扩展技能的开发者,这篇文章都会为你提供宝贵的知识和启发。
|
2月前
|
API Swift C语言
探索iOS开发:Swift中的异步编程与GCD应用
【8月更文挑战第4天】在iOS开发的海洋中,掌握Swift语言的航向是至关重要的。本文将引领你深入理解Swift中的异步编程概念,并借助Grand Central Dispatch(GCD)这一强大的工具,来简化并发编程的复杂性。我们将通过实际代码示例,展现如何在iOS应用中高效地管理后台任务和提升用户界面的响应性。
55 3
|
3月前
|
Swift iOS开发 Kotlin
苹果iOS新手开发之Swift中实现类似Kotlin的作用域函数
Swift可通过扩展实现类似Kotlin作用域函数效果。如自定义`let`, `run`, `with`, `apply`, `also`,增强代码可读性和简洁性。虽无直接内置支持,但利用Swift特性可达成相似功能。
50 7
|
3月前
|
调度 Swift Android开发
苹果iOS新手开发之Swift中的并发任务和消息机制
Swift的消息机制类似Android的Handler,实现任务调度有三种方式: 1. **Grand Central Dispatch (GCD)**:使用`DispatchQueue`在主线程或后台线程执行任务。 2. **OperationQueue**:提供高级接口管理`Operation`对象。 3. **RunLoop**:处理事件如输入源、计时器,类似Android的`Looper`和`Handler`。 **示例**: - GCD:在不同线程执行代码块。 - OperationQueue:创建操作并执行。 - RunLoop:用Timer添加到RunLoop中。
82 2
|
3月前
|
安全 编译器 Swift
苹果重磅发布Swift 6:在 Swift 6 中如何实现并发开发?相比Swift 5.5 有哪些重磅升级?
Swift 6 强化了并发编程,引入结构化并发、任务、执行器、隔离、同步原语、类型化错误处理和取消超时功能。对比Swift 5.5,它默认启用全面并发检查,改进错误处理,增加了隔离区域、类型化抛出、包迭代等新特性,优化了性能并更新了库。
57 2
|
3月前
|
安全 编译器 Swift
探索iOS开发:Swift语言的现代魔法
【7月更文挑战第11天】本文深入探讨了Swift编程语言,它如何革新iOS开发领域,以及它为开发者带来的独特优势。我们将从Swift的基础语法出发,通过实际案例分析其性能优化技巧,最后讨论Swift在跨平台开发中的潜力。文章旨在为读者提供一个全面而深入的视角,了解Swift不仅仅是一门语言,更是一种推动创新的力量。