-
2021-05-17 14:14:52
1 shell for循环语法
for 变量 in 列表
do
command1
command2
...
commandN
done
1.1 读取列表中的值
#!/bin/bash
for test in apple boy cat dog
do
echo The next state is $test
done
结果:
The next state is apple
The next state is boy
The next state is cat
The next state is dog
1.2 读取列表中的复杂值
有两种解决办法:
#使用转义字符(反斜线)来将单引号转移;
#使用双引号来定义用到单引号的值。
#!/bin/bash
for test in I don\'t think if "this'll" work
do
echo The next state is $test
done
结果是:
The next state is I
The next state is don't
The next state is think
The next state is if
The next state is this'll
The next state is work
*记住,for命令用空格来划分列表中的每个值。如果在单独的数据值中有空格,就必须用双引号将这些值圈起来。
1.3 从变量读取列表
将一系列的值都集中存储在一个变量中,然后需要遍历变量中的整个列表。
#!/bin/bash
list="helllo world"
#向已有列表中添加或拼接一个值
list=$list" ok"
for state in $list
do
echo "this word is $state"
done
结果是:
this word is helllo
this word is world
this word is ok
1.4 从命令读取值
有两种方式可以将命令输出赋值给变量:
(1)反引号字符(``)
(2)$()格式
如:
for i in $(who)
do
echo "visit beautiful $i"
done
输出结果:
visit beautiful etldev
visit beautiful pts/0
visit beautiful 2019-05-15
visit beautiful 09:31
visit beautiful (112.64.161.227)
visit beautiful root
visit beautiful pts/1
visit beautiful 2019-05-09
visit beautiful 07:41
visit beautiful (10.1.1.62)
visit beautiful etldev
visit beautiful pts/3
visit beautiful 2019-05-15
visit beautiful 09:34
visit beautiful (112.64.161.227)
visit beautiful etldev
visit beautiful pts/4
visit beautiful 2019-05-15
visit beautiful 10:49
visit beautiful (112.64.161.227)
*who默认输出当前登录的所有用户的信息如下所示
etldev pts/0 2019-05-15 09:31 (112.64.161.227)
root pts/1 2019-05-09 07:41 (10.1.1.62)
etldev pts/3 2019-05-15 09:34 (112.64.161.227)
etldev pts/4 2019-05-15 10:49 (112.64.161.227)
1.5 更改字段分隔符
造成这个问题的原因是特殊的环境变量IFS,叫作内部字段分隔符。默认情况下,bash shell会将下列字符当作字段分隔符:
*空格
*制表符
*换行符
如果bash shell在数据中看到这些字符中的任意一个,它就会假定这表明了列表中一个新数据字段的开始。
想修改IFS的值,使其只能识别换行符,那就必须:
IFS=$'\n'
将这个语句加入到脚本中,告诉bash shell在数据值中忽略空格和制表符。
一个可参考的安全实践是在改变IFS之前保存原来的IFS值,之后再恢复它。
实现:
IFS.OLD=$IFS
IFS=$'\n'
IFS=$IFS.OLD
这就保证了在脚本的后续操作中使用的是IFS的默认值。
遍历一个文件中用冒号分隔的值:
IFS=:
如果要指定多个IFS字符,只要将它们在赋值行串起来就行。
IFS=$'\n':;"
这个赋值会将换行符、冒号、分号和双引号作为字段分隔符。如何使用IFS字符解析数据没有任何限制。
1.6 用通配符读取目录
for file in /proc/*;
do
echo $file is file path \! ;
done
2 类C风格for循环的语法格式
for((expr1; expr2; expr3))
do
command
command
...
done
有些部分并没有遵循bash shell标准的for命令:
*变量赋值可以有空格
*条件中的变量不以美元符开头
*迭代过程的算式为用expr命令格式
#!/bin/bash
#使用类C风格for循环输出1~5
for ((integer = 1; integer <= 5; integer++))
do
echo "$integer"
done
结果:
1
2
3
4
5
使用类C风格for循环要注意以下事项:
a.如果循环条件最初的退出状态为非0,则不会执行循环体
b.当执行更新语句时,如果循环条件的退出状态永远为0,则for循环将永远执行下去,从而产生死循环
c.Linux shell中不运行使用非整数类型的数作为循环变量
d.如果循环体中的循环条件被忽略,则默认的退出状态为0
e.在类C风格的for循环中,可以将三个语句全部忽略掉,下面是合法的for循环
for((; ; ))
do
echo "hello world"
done
更多相关内容 -
python-for循环-嵌套循环-函数
2022-01-20 21:43:02for循环和可迭代对象遍历 for循环通常用于可迭代对象的遍历。for 循环的语法格式如下: for变量in 可迭代对象 : 循环体语句 [操作]遍历一个元组或列表 for x in (20,30,40): print(x*3) 可迭代对象 Python...for循环和可迭代对象遍历
for循环通常用于可迭代对象的遍历。for 循环的语法格式如下:
for变量in 可迭代对象 :
循环体语句
[操作]遍历一个元组或列表
for x in (20,30,40): print(x*3)
可迭代对象
Python包含以下几种可迭代对象:
1.序列。包含:字符串、列表、元组
2.字典
3.迭代器对象( iterator )
4.生成器函数( generator )
5.文件对象
range对象
range对象是一个迭代器对象,用来产生指定范围的数字序列。格式为:
range(start, end [step])
生成的数值序列从start开始到end结束(不包含end )。若没有填写start ,则默认从0开始。step 是可选的步长,默认为1。如下是几种典型示例:
for i in range(10) 产生序列:0123456789
for i in range(3,10) 产生序列:3456789
for i in range(3,10,2) 产生序列:3579
嵌套循环
一个循环体可以嵌入另一个循环体,一般称为嵌套循环,或者多重循环
操作利用嵌套循环打印九九乘法表
for m in range(1,10): s = " " for n in range(1,m+ 1): s += str.format("{0}*{1}= {2}\t",m,n,m*n) print(s)
break语句
break语句可用于while和for循环,用来结束整个循环。当有嵌套循环时, break语句只能跳出最近一层的循环。
continue语句
continue语句用于结束本次循环,继续下一次。多个循环嵌套时, continue也是应用于最近的一层循环。
else语句
while. for 循环可以附带一个 else语句(可选)。如果for. while 语句没有被break语句结束,则会执行else子句,否则不执行。语法格式如下:
while条件表达式 : for变量in 可迭代对象 :
循环体 循环体
else: else:
语句块 语句块
循环代码优化
虽然计算机越来越快,空间也越来越大,我们仍然要在性能问题上“斤斤计较”。编写循环时,遵守下面三个原则可以大大提高运行效率,避免不必要的低效计算:
1.尽量减少循环内部不必要的计算
2.嵌套循环中,尽量减少内层循环的计算,尽可能向外提。
3.局部变量查询较快,尽量使用局部变量
使用zip()并行迭代
我们可以通过zip0函数对多个序列进行并行迭代, zip0函数在最短序列"用完”时就会停止
[操作]测试zip0并行迭代
names = ("老大",' 老二","老三","老四") ages = (18,16,20,25) jobs = ("老师","程序员","公务员") for name,age.job in zip(names,ages,jobs): print("{0}-{1}-{2}".format(name,age,job))
推导式创建序列
推导式是从一个或者多个迭代器快速创建序列的一种方法。它可以将循环和条件判断结合,从而避免冗长的代码。推导式是典型的Python风格。
列表推导式
列表推导式生成列表对象,语法如下:
[表达式 for item in 可迭代对象]
或者: {表达式 for item in 可迭代对象 if 条件判断}
>>> [x for x in range(1,5)]
[1, 2,3, 4]
字典推导式
字典的推导式生成字典对象,格式如下:
{key_ expression : value_ expression for表达式in 可迭代对象}
类似于列表推导式,字典推导也可以增加if条件判断、多个for循环。
集合推导式
集合推导式生成集合,和列表推导式的语法格式类似:
{表达式 for item in 可迭代对象}
或者: {表达式 for item in 可迭代对象if 条件判断}
生成器推导式(生成元组)
提示是一个生成器对象,显然元组是没有推导式的
>>> (x forx in range(1,100) if x%9==0) < generator object < genexpr> at 0x0000000002BD3048>
一个生成器只能运行一次。 第一次迭代可以得到数据,第二次迭代发现数据已经没有了.
>>> gnt = (x for x in range(1,100) if x%9==0) >>> for X in gnt: print(x,end='') 9 18 27 36 45 54 63 72 81 90 99 >>> for X in gnt: print(x,end=' ') >>>
函数
函数基本概念
1.一个程序由一个个任务组成;函数就是代表一个任务或者一个功能。
2.函数是代码复用的通用机制。
python函数分类
1.内置函数
我们前面使用的str(). list()、 len(等这些都是内置函数,我们可以拿来直接使用。
2.标准库函数
我们可以通过import语句导入军,然后使用其中定义的函数
3.第三方库函数
Python社区也提供了很多高质量的库。下载安装这些库后,也是通过import语句导入,然后可以使用这些第三方库的函数
4.用户自定义函数
用户自己定义的函数,显然也是开发中适应用户自身需求定义的函数。
函数定义和调用
核心要点
Python中,定义函数的语法如下:
def函数名([参 数列表]) :
"文档字符串"
函数体/若干语句
要点:
1.我们使用def来定义函数,然后就是一个空格和函数名称:
(1) Python 执行def时,会创建一个函数对象 ,并绑定到函数名变量上。
2.参数列表
(1)圆括号内是形式参数列表,有多个参数则使用逗号隔开
(2)形式参数不需要声明类型,也不需要指定函数返回值类型
(3)无参数,也必须保留空的圆括号
(4)实参列表必须与形参列表一对应
3. return 返回值
4.调用函数之前,必须要先定义函数,即先调用def创建函数对象
(1)内置函数对象会自动创建
(2)标准库和第三方库函数,通过import导入模块时,会执行模块中的def语句
形参和实参
[操作]定义一个函数.实现两个数的比较,并返回较大的值。
def printMax(a,b): '''实现两个数的比较,并返回较大的值''' if a>b: print(a,"较大值") else: print(b,"较大值") printMax(10,20) printMax(30,5)
上面的printMax函数中,在定义时写的printMax(a,b)。a和b称为“形式参数”,简称“形参" .也就是说,形式参数是在定义函数时使用的。形式参数的命名只要符合“标识符”命名规则即可。
在调用函数时,传递的参数称为“实际参数”,简称“实参”。上面代码中 .printMax(10,20) , 10和20就是实际参数。
返回值
return返回值要点:
1.如果函数体中包含return语句,则结束函数执行并返回值;
2.如果函数体中不包含return语句,则返回None值。
3.要返回多个返回值,使用列表、元组、字典、集合将多个值“存起来”即可。
[操作]定义一个返回两个数平均值的函数
def my_avg(a,b): return (a+b)/2 #如下是函数的调用 c = my_avg(20,30) print(c)
-
for的用法详解,for循环完全攻略
2021-06-11 14:56:23for 循环语句的一般形式为: for (表达式1; 表达式2; 表达式3) { 语句; } 首先要强调两点: 1) 表达式1、表达式2和表达式3之间是用分号;隔开的,千万不要写成逗号。 2)for(表达式1;表达式2;表达式3)的后面千万...for 循环语句的一般形式为:
for (表达式1; 表达式2; 表达式3) { 语句; }
首先要强调两点:
1) 表达式1、表达式2和表达式3之间是用分号;
隔开的,千万不要写成逗号。
2)for(表达式1;表达式2;表达式3)
的后面千万不要加分号,很多新手都会犯这种错误——会情不自禁地在后面加分号。
因为 for 循环只能控制到其后的一条语句,而在C语言中分号也是一个语句——空语句。所以如果在后面加个分号,那么 for 循环就只能控制到这个分号,下面大括号里面的语句就不属于 for 循环了。
下面来看看它的执行过程:求解表达式1。 求解表达式2。若其值为真,则执行 for 语句中指定的内嵌语句,然后执行第3步;若表达式2值为假,则结束循环,转到第5步。 求解表达式3。 转回上面第2步继续执行。 循环结束,执行 for 语句下面的语句。
从这个执行过程中可以看出,“表达式1”只执行一次,循环是在“表达式2”“表达式3”和“内嵌语句”之间进行的。
for语句最简单的形式是:for (循环变量赋初值; 循环条件; 循环变量增值) { 语句; }
下面给大家写一个程序,求 1+2+3+4+…+100 的总和。# include <stdio.h> int main(void) { int i; int sum = 0; //sum的英文意思是“总和” for (i=1; i<=100; ++i) //++是自加的意思, ++i相当于i = i + 1 { sum = sum + i; /*等价于sum += i;但是不建议这么写, 因为sum = sum + i看起来更清楚、更舒服*/ } printf("sum = %d\n", sum); return 0; }
输出结果是:
sum = 5050
这个程序的功能是实现求 1+2+3+4+…+100 的和,如果不用循环,加一次就要一条语句,加 100 次就要 100 条语句。这里是从 1 加到 100,要是从 1 加到 10000 那就要 10000 条语句。但有了循环就很方便了,你想加到多少就加到多少,只要改一个参数就可以了。所以循环很重要。
下面按照执行过程看看上面这个程序是怎样执行的。
1) 首先定义一个循环变量 i。定义的时候可以不给它赋初值,在 for 循环里面再给它赋初值也行。但前面说过,最好在定义变量的时候就对它进行初始化,如果值不确定就初始化为 0。所以程序中也可以在定义 i 的时候就给它赋初值,那么 for 循环里的“表达式1”就可以省略了,但分号不可以省略。
这样的话,执行的时候就跳过第1步,直接进入第2步,其他的不变。所以程序也可以像下面这样写:# include <stdio.h> int main(void) { int i = 1; int sum = 0; for (; i<=100; ++i) { sum = sum + i; } printf("sum = %d\n", sum); return 0; }
当然表达式1加上也行,大不了再重新赋一次值。
2) 然后定义一个用来存放“和”的变量 sum,并给它赋初值 0,然后进入 for 循环:首先求解表达式1,即给变量i赋初值,i=1;表达式1只执行这一次,下面都不会再执行了。 然后求解表达式2,若 1<=100 成立,则执行 for 循环中的内嵌语句,即 sum=0+1。 然后执行第3步,变量 i 自加 1,即变量 i 由 1 变为 2。 然后再求解表达式2,2<=100 成立,则执行 for 循环中的内嵌语句,sum=0+1+2。 然后再执行第3步,变量 i 自加 1,即变量 i 由 2 变为 3。 然后再求解表达式2,即 3<=100 成立,则执行 for 循环中的内嵌语句,sum=0+1+2+3。 ……
就这样一直循环下去,直到 ++i 等于 100 的时候,求解表达式2,即 100<=100 成立,则执行 for 循环中的内嵌语句,sum=0+1+2+3+…+100。
然后再执行第3步,变量 i 自加 1,即变量 i 由 100 变为 101。然后再求解表达式2,即 101<=100 不成立,则结束循环,执行 for 循环下面的语句即 printf。
以上就是这个程序的执行过程。关于 for 语句的代码规范化问题,有两点要再跟大家强调一下:
1)if、else、for、while、do 都只能控制到其后的一条语句,如果要控制多条语句必须加大括号{}
。但基于代码规范化,if、else、for、while、do 后面的执行语句不论有多少行,就算只有一行也要加{}
。
2) 像 if、for、while 等关键字之后应留一个空格再跟左括号(
,以突出关键字。
此外上面的程序还有一个知识点要跟大家说一下:从功能上讲,for(i=1; i<=100;++i)
完全可以写成for(i=1; i<101; ++i)
,而且建议大家尽量使用这种写法。也就是说,循环语句的循环条件尽量写成半开半闭的,不管是 for 循环还是 while 循环。for(i=1; i<101; ++i)
实际上是 1≤i<101,是半开半闭的;而for(i=1; i<=100; ++i)
实际上是 1≤i≤100,是全闭的。那么为什么建议使用半开半闭的呢?因为如果写成 i<=100 的话,那么每次判断的时候都要判断两次,即 i<100 和 i==100,而写成 i<101 的话每次只需要判断一次。
也许有人说:程序在执行 i<=100 的时候不是将它转换成 i<100||i==100 吗?这样由“短路或”的知识可知,如果前面的为真那么后面的不就不会执行了吗?这样不也是判断一次吗?不是这样的,系统是不会将 i<=100 转换成 i<100||i==100 的,每次判断的时候 i<100 和 i==100 都要判断。
但是写成半开半闭也有一个问题,就是会影响对代码的理解。有时候写成全闭的区间理解起来才顺畅,而写成半开半闭反而不易理解,比如<=
右边是变量或表达式的时候。这时候要以可读性为第一要素,即哪种好理解就使用哪种。现在 CPU 速度那么快,也不在乎那点效率。所以前面说“尽量”,没有要求一定要那样写。
下面再给大家写一个程序,求 1 到 100 之间所有奇数的和。# include <stdio.h> int main(void) { int i; int sum = 0 ; for (i=1; i<100; i+=2) //i+=2;等价于i = i + 2; { sum = sum + i; } printf("sum = %d\n", sum); return 0; }
输出结果是:
sum = 2500关于自增和自减
一直以来,++ 和 –– 语法浪费了太多人的时间。说句实在话,++ 和 –– 在C语言中根本就不重要,除了表达简练外,真的没有什么其他好处了。
简单地说:++i 和 i++ 在单独使用时,都表示 i=i+1;––i 和 i–– 在单独使用时,都表示 i=i–1。
而 a=++i 就相当于 i=i+1,a=i;a=i++ 就相当于 a=i,i=i+1。
同理,a=––i 就相当于 i=i–1,a=i;a=i–– 就相当于 a=i,i=i–1。
如果实在搞不明白 ++ 和 –– 是怎么回事,那也不是什么天塌下来的事情。因为a=++i;
完全可以写成i++; a=i;
。而a=i++;
也完全可以写成a=i; i++;
。而且,这也是一种很好的程序风格。
作为一个优秀的程序员,在你的程序中就不应该体现出 ++i 和 i++ 的区别,要么都用 ++i,要么都用 i++,不要一会儿用 ++i 一会儿用 i++。
对于自增和自减还有一点需要强调的是:只有“变量”才能进行自增和自减!你认为 3++ 等于多少?C语言中没有这种写法,常量是不能进行自增和自减的。for循环练习
1) 求 1! + 2! + 3! + ... + n!
# include <stdio.h> int main(void) { int n = 0; int i = 0; int m = 1; int sum=0; printf("请输入n的值:"); scanf("%d", &n); for (i=1; i<=n; ++i) { m = m * i; sum = sum +m; } printf ("sum = %d\n", sum); return 0; }
这个程序虽然短,但逻辑性很强,算法很好,所以建议读者记住。因为逻辑性强,所以只看是很难明白的,自己在纸上试一下,将自己当成计算机一步步地计算就明白了。
假如 n=4: 当 i=1 时,m=1,sum=1。 当 i=2 时,m=1×2,sum=1+1×2。 当 i=3 时,m=1×2×3,sum=1+1×2+1×2×3。 当 i=4 时,m=1×2×3×4,sum=1+1×2+1×2×3+1×2×3×4。
看出规律来了吗?m 的值是一直往下乘,乘以 i 之前 m 的值是(i–1)的阶乘,乘以 i 之后 m 的值就是 i 的阶乘了。这样 i 循环到多少,m*i 就立刻将这个数的阶乘计算出来,然后加到 sum 中。
2) for 和 if 的嵌套使用。求 1 到 100 之间所有能被 3 整除的数之和。# include <stdio.h> int main(void) { int i; int sum = 0; for (i=3; i<100; ++i) { if (0 == i%3) { sum = sum +i; } } printf("sum = %d\n", sum); return 0; }
输出结果是:
sum = 1683
大家想想如果不用 if,这个程序能不能写出来?当然能,能被 3 整除的数肯定是 3 的倍数,只要 i 每次自加 3 就行了。我们将这个程序写一下:# include <stdio.h> int main(void) { int i; int sum = 0; for (i=3; i<100; i+=3) { sum = sum +i; } printf("sum = %d\n", sum); return 0; }
因为 ++i 每次只加 1,而 i+=3 每次加 3,所以这种写法与第一种写法比较起来计算机少执行很多步,所以执行起来更快。由此可知,完成相同的功能,算法不一样则效果就不一样。对计算机而言当然是执行得越快越好。
3) 编写程序,输出 1~1000 之间所有的完全平方数。# include <stdio.h> # include <math.h> //要用sqrt() int main(void) { int i; //循环变量 int x; //存储每个数的二次方根 for (i=1; i<1000; ++i) { x = sqrt(i); /*如果i不是完全平方数, 那么sqrt(i)肯定是小数, 而i是int型, 所以x是sqrt(i)取整后的值, 这样x*x肯定不等于i*/ if (x*x == i) { printf("%d\t", i); // \t是跳到下一个Tab位置 } } printf("\n"); return 0; }
输出结果是:
1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400 441 484 529 576 625 676 729 784 841 900 961
其实这个程序还有更简单的算法,不需要使用 sqrt()。下面将这个程序也写下来:# include <stdio.h> int main(void) { int i; //循环变量 for (i=1; i*i<1000; ++i) { printf("%d\t", i * i); // \t是跳到下一个Tab位置 } printf("\n"); return 0; }
输出结果是:
1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400 441 484 529 576 625 676 729 784 841 900 961
-
循环语句(while,for,do...while)
2021-10-29 17:01:15写这篇文章,我深有感触,在写代码的过程中,我们...在这篇文章中,我们将会对循环语句有一个更加深入的了解 并且我们还能了解到getchar与putchar的相关知识 让我们开始吧! 一.while循环 1.while循环语法 ...写这篇文章,我深有感触,在写代码的过程中,我们经常会出现最后的结果达不到我们预期的效果的情况,我们一定一定要耐下心来,一步一步地去思考,是哪里出了问题,怎么能解决问题,这样的一个过程是十分重要的,是能让我们越来越接近真相的过程。学习编程的路肯定不是一帆风顺的,但我们要有能够克服任何苦难的决心,这是最重要的。
在这篇文章中,我们将会对循环语句有一个更加深入的了解
并且我们还能了解到getchar与putchar的相关知识
让我们开始吧!
目录
2.break和continue在do...while循环中
一.while循环
1.while循环语法
while语句又称当型循环语句,其语法为:
while (表达式)
循环语句;
其具体执行过程如下:
(1)计算表达式的值。若为真,则转步骤(2),否则退出循环,执行while的下一条语句
(2)执行循环语句(即循环体),并返回步骤(1)
这里试着使用while循环打印1~10的数
#include <stdio.h> int main() { int i = 1; while(i<=10) { printf("%d ", i); i++; } return 0; }
2.break和continue 在while循环中
(1).break
#i#include <stdio.h> int main() { int i = 1; while(i<=10) { if(5 == i) break; printf("%d ", i); i ++; } return 0; }
运行的结果如图
总结:
break在while循环中的作用:
其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。
所以:while中的break是用于永久终止循环的。
(2).continue
如果将刚刚的break换成continue
那么运行的结果又会发生什么变化呢?
#include <stdio.h> int main() { int i = 1; while(i<=10) { if(5 == i) continue; printf("%d ", i); i ++; } return 0; }
4后面的光标在闪动,说明此时程序进入了死循环
原因是,与break语句不同,
continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,而是直接 跳转到while语句的判断部分。进行下一次循环的入口判断
如图中红色框框内的代码在continue的作用下会被跳过,i++不会被执行,所以i就一直为5,进去死循环
3.两个代码的练习
让我们再看两个跟while循环有关的代码,再看之前,我们需要先了解一下getchar和putchar
getchar
在msdn中,我们查找到getchar的解释
int ch = getchar() ; //获取字符
printf("%c\n",ch) ; //打印获取的字符
这里我们会有这样的疑问:我们的 ch 获取的是一个字符,为什么放到int整型里去?
原因有两个:
- 虽然getchar返回的是个字符,但是字符的存储值是它的 ASCII码值,如 ’a‘对应的ASCII码值就是97
- getchar读取失败的时候返回EOF,而EOF是-1,是个整数
getchar - 获取(输入一个字符)
putchar - 输出一个字符
putchar
在msdn中的定义
int ch = getchar() ; //获取字符
putchar (ch);//输出一个字符
getchar 和 putchar 可以用scanf 和printf代替,且scanf和printf的功能更全,getchar和putchar只能操作字符
第一个代码
这个代码会将你输入的字符打印出来,如果想停止:ctrl+z 可以让getchar返回一个EOF
我们写这样的代码有什么意义呢?实际上是有意义的,我们这里再举一个例子
#include <stdio.h> int main() { char input[20] = { 0 };//创建一个数组 printf("请输入密码:>"); scanf("%s", input); printf("请确认密码(Y/N):>"); int ch = getchar(); if (ch == 'Y') { printf("确认成功\n"); } else { printf("确认失败\n"); } return 0; }
看这个代码时,可能会有疑问,为什么scanf函数里的input没有取地址,
是因为数组名本身就是一个地址,所以不需要再取地址
这样一个程序,我们的本意是输入密码后需要用户确认密码是否正确,可当程序走起来后我们发现,在我们还没有输入时,已经打印出了“确认失败”
下面我们就来分析一下程序出问题的原因 ,全部在这张图上了
解决方法 :把输入缓冲区里scanf没有拿走的\n拿走 ,改进如下
#include <stdio.h> int main() { char input[20] = { 0 };//创建一个数组 printf("请输入密码:>"); scanf("%s", input); getchar(); //拿走\n printf("请确认密码(Y/N):>"); int ch = getchar(); if (ch == 'Y') { printf("确认成功\n"); } else { printf("确认失败\n"); } return 0; }
我们成功了!!!
下面是还可能出现的错误的情况:如果密码当中有“ ”(空格)
当用户输入的密码中含有空格时,又出现了刚刚的错误的情况,我们再来分析
我们可以发现这时需要拿走更多的字符,所以我们使用while循环
while ((tmp = getchar()) != '\n') //只要不是/n,就说明没拿完,就进入循环
{
; //空语句(什么也不干)
}#include <stdio.h> int main() { char input[20] = { 0 };//创建一个数组 printf("请输入密码:>"); scanf("%s", input); int tmp = 0; while ((tmp = getchar()) != '\n')//只要不是/n,就说明没拿完,就进入循环 { ;//空语句(什么也不干) } printf("请确认密码(Y/N):>"); int ch = getchar(); if (ch == 'Y') { printf("确认成功\n"); } else { printf("确认失败\n"); } return 0;
我们惊喜地发现,我们又通过改变代码使这个程序执行成功了!
第二个代码
#include <stdio.h> int main() { int ch=0; while ((ch = getchar()) != EOF) { if (ch < ‘0’ || ch > ‘9’) continue; putchar(ch); } return 0; }
这个代码就比较简单了 就是只打印0~9的数字
但有一点需要说明
这个括号不能少((ch=getchar())!=EOF) 如果少了 ,就不是把获取的字符放进ch和EOF比较了,而是字符直接与EOF比较,不相等就为假,就为0,这时就把0赋给了ch
二.for循环
1.for循环语法
for循环的语法:
for (表达式1;表达式2;表达式3)
循环语句;
表达式1
表达式1为初始化部分,用于初始化循环变量的。
表达式2
表达式2为条件判断部分,用于判断循环时候终止。
表达式3
表达式3为调整部分,用于循环条件的调整。
这里我们同样也使用for循环来打印一下1~10的数来熟悉一下for循环
#include <stdio.h> int main() { int i = 0; for(i=1; i<=10; i++) { printf("%d ", i); } return 0; }
并且,我们用这个代码为例,来帮助我们理解for循环的流程图
现在我们对比一下for循环和while循环
int i = 0; //实现相同的功能,使用while i=1;//初始化部分 while(i<=10)//判断部分 { printf("hehe\n"); i = i++;//调整部分 } //实现相同的功能,使用while for(i=1; i<=10; i++) { printf("hehe\n"); }
可以发现在while循环中依然存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离 较远,这样查找修改就不够集中和方便。所以,for循环的风格更胜一筹。 for循环使用的频率也最高。
2. break和continue在for循环中
我们发现在for循环中也可以出现break和continue,他们的意义和在while循环中是一样的。
但是还是有些差异:
(1).break
可见,break在for循环中与在while循环中类似,都是直接终止循环
(2).continue
#include <stdio.h> int main() { int i = 0; for(i=1; i<=10; i++) { if(i == 5) continue; printf("%d ",i); } return 0; }
continue在for循环和在while循环中有所不同
这里执行起来并不是死循环了,而是跳过5打印了1 2 3 4 6 7 8 9 10
当i==5时,执行continue语句,跳过printf语句 ,执行 i++,之后 i为6,i==5为假,continue语句不再执行
for语句的循环控制变量 (作为补充)
一些建议:
- 不可在for 循环体内修改循环变量,防止 for 循环失去控制。
- 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。
int i = 0; //前闭后开的写法 for(i=0; i<10; i++) {} //两边都是闭区间 for(i=0; i<=9; i++) {}
第一种也就是前闭后开的写法很直观,这个循环要循环10次(但不是总是如此)
一些for循环的变种
#include <stdio.h> int main() { //变种1 for(;;) { printf("hehe\n"); } //变种2 int x, y; for (x = 0, y = 0; x<2 && y<5; ++x, y++) { printf("hehe\n"); } return 0; }
变种1
for的初始化,判断,调整三个部分都可以省略
中间的判断部分如果省略,意味着判断恒为真,就构成死循环
如果条件允许,不建议省略for循环的3个表达式
这里看一个嵌套的for循环 ,来比较一下
#include <stdio.h> int main() { int i = 0; int j = 0; for (i = 0;i < 3;i++) { for (j = 0;j < 3;j++) { printf("hehe\n"); } } return 0; }
在正常情况下,这个程序会3次外循环,3次内循环,共9次 打印9次hehe
我们现在试一下省略for的第一个初始化语句
#include <stdio.h> int main() { int i = 0; int j = 0; for (;i < 3;i++) { for (;j < 3;j++) { printf("hehe\n"); } } return 0; }
结果只打印了三次, 原因是 虽然外循环还是3次,但内循环由于 j 没有初始化,在内循环第3次后,j就变成了4,内循环不再执行
变种2
使用多于一个变量控制循环,这是允许的
for (x=0,y=0;x<2&&y<5,++x,y++)
这里,我们再拓展一道笔试题:
请问循环要循环多少次?
//请问循环要循环多少次? #include <stdio.h> int main() { int i = 0; int k = 0; for(i =0,k=0; k=0; i++,k++) k++; return 0; }
答案是0次
原因是这里的红色框中的 k=0是赋值,k被赋值为0,0为假,循环不执行
三.do...while()循环
1.do...while()循环的语法
do
循环语句;
while (表达式);
我们再用do...while循环来试着打印1~10的数
#include <stdio.h> int main() { int i = 1; do { printf("%d ", i); i++; } while (i <= 10); }
do..while的特点是:循环至少执行一次,使用的场景有限,所以不是经常使用。
流程图
2.break和continue在do...while循环中
(1).break
#include <stdio.h> int main() { int i = 1; do { if (5 == i) break; printf("%d ", i); i++; } while (i <=10); return 0; }
可见,break在三个循环中较为类似,都是直接终止循环,但是值得注意的是: break只能终止一层循环,如果有刚刚那种嵌套式的循环,只能终止一层
(2).continue
#include <stdio.h> int main() { int i = 1; do { if (5 == i) continue; printf("%d ", i); i++; } while (i <=10); return 0; }
运行的结果是1 2 3 4死循环
-
for和双重for循环的用法和案例举例
2020-08-16 15:02:237.1 for循环 for ( 初始化变量;条件表达式;操作表达式){ //循环体 } 1.初始化变量:就是用var 声明的一个普通变量,在循环(代码块)开始之前执行。通常用于计数器的使用。可以不写。 2.条件表达式 就是用来... -
for循环中抛出异常_不要抛出循环!
2020-06-28 05:13:58原因很简单:除了val使得对程序的线程安全性的推理更容易外,这是Scala的基本主题,开发人员几乎不需要像我们认为的那样需要可变状态。 从不可变的字段和局部变量( val )开始,就是一种证明这一点的方法,甚至向... -
for的用法详解,C语言for循环完全攻略
2021-02-06 16:50:51for 循环语句的一般形式为:for (表达式1; 表达式2; 表达式3){语句;}首先要强调两点:1) 表达式1、表达式2和表达式3之间是用分号;隔开的,千万不要写成逗号。2)for(表达式1;表达式2;表达式3)的后面千万不要加分号... -
61-C++while循环
2018-09-10 19:48:04While循环是没有初始化和更新部分的for循环,它只有测试条件和循环体: while (test-condition) body; 首先,程序计算圆括号内的测试条件表达式,如果该表达式为true,则执行循环体中的语句。与for循环... -
GAN生成对抗网络合集(七):cycleGAN—循环损失的提出 / starGAN
2020-06-03 12:11:31我们使用循环一致性损失以鼓励这种行为: 在初步实验中,我们也尝试用F(G(x))和x之间、G(F(y))和y之间的对抗性损失来代替L1范数,但没有观察到性能的改善。 循环一致性损失引起的行为如图4所示: 重构图像F(G(x))最终... -
温控风扇
2018-12-26 21:24:46while(1) //进入while循环 { if(js>=50) //当js在定时器里加到50次时(js加一次是20ms,加到50次就是1000ms,也就是1秒读取一次温度) { ReadTemperature(); //读取温度值 js=0; //定时读取温度... -
普中科技51单片机直流电机控制风扇调速
2020-06-15 18:21:17if(k1==0 || k3==0 || k4==0 || k5==0 || k6==0)//其他按键按下跳出循环 break; } } while(!k2);//检测按键是否松开 } if(k1==0)//按键按下就关 { delay(1000); if(k1==0) { P0=~smgduan[0]; moto=0; } while(!k1);... -
能模仿韩寒小四写作的神奇循环神经网络
2016-04-26 19:32:19记忆破蛹而出,翻滚着随风摆动的兰花草,气味扑鼻,海潮依旧。 你们虔诚的看着远方,我抬起头,不经意间,目光划过你们的面庞,上面淡淡的倔强印,那么坚强 尘世凡间 沉睡亿万光年的年轻战士 萦绕不散的寂寞烟云中... -
Java的循环语句
2014-04-21 21:01:21Java 的循环语句有for,while 和 do-while 。这些语句创造了我们通常所称的循环(loops)。你可能知道,一个循环重复执行同一套指令直到一个结束条件出现。你将看到,Java 有适合任何编程所需要的循环结构。 ... -
Nature综述:微生物构成的氮循环网络(收藏)
2019-11-02 00:00:00微生物构成的氮循环网络The microbial nitrogen-cycling network 翻译:翟志文 中科院遗传发育所责编:刘永鑫 中科院遗传发育所Nature Review... -
LSTM和循环网络RNN学习简记
2017-07-29 11:24:39前馈网络回顾要理解循环网络,首先需要了解前馈网络的基础知识。这两种网络的名字都来自于它们通过一系列网络节点数学运算来传递信息的方式。前馈网络将信息径直向前递送(从不返回已经过的节点),而循环网络则将... -
Nature综述:微生物构成的氮循环网络(必读)
2019-04-21 16:07:05文章目录微生物构成的氮循环网络大纲摘要亮点名词解析背景和内容概述Box 1 | 氮全球生化循环圈:全球的氮库存、氮转化过程、氮通量图1 | 微生物转化氮化合物图2 | 催化氮循环中关键的四种反应的酶氮转化反应固氮作用... -
ICCV2017 Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks循环一致对抗...
2022-03-05 16:39:16我们提出了一种学习在没有成对例子的情况下将图像从源域X转换为目标域Y的方法。我们的目标是学习一种映射G: X→Y,使G(X)的图像分布与使用对抗性损失的分布Y难以区分。我们将它与一个逆映射F: Y→X耦合,并引入一个... -
17届智能车:浅析总转风摄像头的图像处理
2022-02-05 19:24:56简单来说,总转风摄像头可以极大地消除动态模糊问题,在高速下采集的图像也不会造成太大的失真。 一、图像的采集 摄像头的工作原理大致为:景物通过镜头生成的光学图像投射到图像传感器表面上,然后转为电信号,... -
Win32消息循环机制等【转载】
2015-10-31 00:29:49Dos的过程驱动与Windows的事件驱动在讲本程序的消息循环之前,我想先谈一下Dos与Windows驱动机制的区别:DOS程序主要使用顺序的,过程驱动的程序设计方法。顺序的,过程驱动的程序有一个明显的开始,明显的过程及一个... -
基于Arduino的自动调速风扇
2020-06-15 21:22:58好久没有更新了,家里实在太乱,最近趁着618活动,买了一堆收纳抽屉和置物架,把家里彻底收拾了一下,然后客厅就成了这个奇葩样子,注孤生的节奏了。 话不多说,夏天到了,天气逐渐热起来,风扇成了必不可少的消暑... -
华为C语言编程规范(精华总结)
2020-03-24 09:48:55除了不稳定的模块依赖于稳定的模块外,更好的方式是两个模块共同依赖于接口,这样任何一个模块的内部实现更改都不需要重新编译另外一个模块。在这里,我们假设接口本身是最稳定的。 4、每一个 .c 文件应有一个同名 .... -
邹欣对话图灵奖得主Jeffrey Ullman:数据库不会进入周期性的坏循环 |《新程序员》
2021-08-19 15:23:51数据库领域有足够的钱去生存,也不会进入像AI寒冬这样的周期性循环。 邹欣:你写过很多广为流传的著作,其中Compilers:Principles, Techniques, and Tools(《编译原理》)。这本书曾被很多高校作为教材,但目前很多... -
《C++ Primer》学习笔记(五):循环、分支、跳转和异常处理语句
2019-11-13 13:16:57《C++ Primer》习题参考答案:第5章 - 循环、分支、跳转和异常处理语句 文章目录 专栏C++学习笔记 [Cpp-Prime5 + Cpp-Primer-Plus6 源代码和课后题](https://github.com/TeFuirnever/Cpp-Primer-Plus-Plus-Plus) ... -
语义分割-CyCADA: Cycle-Consistent Adversarial Domain Adaptation.循环一致对抗领域自适应
2022-03-02 20:52:38提出了循环一致对抗域适应算法(CyCADA),该算法在像素级和特征级对表示进行适应,同时通过像素循环一致性和语义损失实现局部和全局结构一致性。CyCADA整合了之前的特征级别和图像级别对抗域自适应方法和循环一致的... -
气候变化中的极端气候事件对生态系统碳循环的影响
2015-04-01 09:46:13除了上述在生态系统水平的机制外,在社会和经济系统中同样存在滞后效应。例如,如果低产量提高了食品的价格,就会鼓励更多人将森林转变为农田或草原。 极端气候可诱导一系列相互关联的影响,所有这些影响有... -
风格迁移相关论文阅读笔记
2018-06-20 15:26:273.能否用水墨风的颜色损失 4.文中提到现有风格技术只涉及到了风格选择,而对其他艺术设计,如夸张、构图、艺术布局等的处理。抽象表达语义是关键 《基于深度学习的图像与视频风格化研究与实现》 ... -
Google C++ 风格指南内容整理
2015-05-17 16:43:35之前一直没有全面的看过Google C++风格指南,现在很多公司进行C++开发都要求按照Google C++风格。在这个网站 http://zh-google-styleguide.readthedocs.org/en/latest/contents/ 有人已经把其翻译成中文。为了... -
循环神经网络系列(六)基于LSTM的唐诗生成
2018-11-13 14:28:10对于循环神经网络来说,我们首先需要做的仍旧是找到一种将数据序列化的方法。当然,对于古诗词来说,每个字的出现顺序就是天然的一个序列,因此我们就可以直接按照这个序列来处理。并且一首古诗词可以看成是一个样本... -
【飞桨PaddlePaddle】四天搞懂生成对抗网络(四)——CycleGAN的绝妙设计:双向循环生成的结构
2020-11-22 20:03:24我们知道Pix2Pix优化时除了使用GAN Loss(对抗损失)外,还加入了生成器输入图片和输出图片的L1 Loss来对齐生成图片与输入图片的宏观轮廓(所谓低频信息)。同样的逻辑,我们也能在CycleGAN中用L1 Loss来对齐“循环...