目录
for循环
语法结构
for (初始化表达式;循环控制表达式;增值表达式)
{
语句序列;
}
for语句属于当型循环结构
初始化表达式的作用是循环控制变量初始化,即赋初值,决定了循环的起始条件;循环控制表达式是循环控制条件,当这个表达式的值为真(非0)时继续重复执行循环,否则循环结束;增值表达式的作用是每执行一次循环后将循环控制变量增值
每一次(包括第一次)循环体被执行之前,都要对循环控制条件测试一次;每次循环体执行完以后都要执行一次增值表达式
for循环的变种
(1)判断部分省略就是恒为真,会进入死循环
for (;;)
{
printf("haha\n");
}
(2)省略初始化部分
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
printf("haha\n");
}
}
运行结果:
haha
haha
haha
haha
haha
haha
haha
haha
haha
但是省略之后,就没有了在进入循环时对变量进行初始化赋值的过程
int i = 0;
int j = 0;
for (; i < 3; i++)
{
for (; j < 3; j++)
{
printf("haha\n");
}
}
运行结果:
haha
haha
haha
由于第二层循环中没有了初始化部分,所以在进行第一层循环的第二次时,j的值无法初始化为0,所以还为3,导致无法进入第二层循环
(3)省略增值表达式,可能因此进入死循环,但是可以在循环体内写增值语句来避免这种情况
初始化表达式;
for(;循环控制表达式;)
{
语句序列;
增值表达式;
}
思考:下面这个代码的输出结果是什么?
int j = 0;
int k = 0;
for (j = 0,k = 0; k = 0; j++,k++)
{
k++;
}
printf("%d", k);
答案是0,其实程序并没有进入循环,原因是for循环中的循环控制表达式,也就是判断部分,写成了一个赋值语句,这一个不是判断语句,这个语句的结果就是0,0为假,不进入循环
int j = 0;
int k = 0;
for (j = 0,k = 0; k = 2; j++,k++)
{
k++;
}
printf("%d", k);
这样做又会发生什么?
答案是程序进入死循环,因为判断部分仍然是一个赋值语句,但这个语句的结果为2,为真,也就是可以进入循环,当进入下一次循环时,k的值又会变成2,原因是会执行判断部分,从而执行赋值语句,导致k的值一直在2和3中切换,所以进入死循环
(4)省略语句序列
当循环体内是空语句时,表示在循环体中什么也不做,常用于编写延时程序
①for (i = 1; i < 50000000; i++)
{
;
}
② for (i = 1; i < 50000000; i++)
{
}
③for (i = 1; i < 50000000; i++);
注意:除非特殊需要,一般不在for语句后加分号
for (i = 1; i < 50000000; i++);
{
sum+=i;
}
相当于
for (i = 1; i < 50000000; i++)
{
;
}
sum+=i;
示例:
int main()
{
int i, n;
long p = 1;//由于阶乘取值范围较大,故p定义为长整型,并赋初值1
printf("请输入数字n:");
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
p *= i;
}
printf("%d!=%ld\n", n, p);//以长整型格式输出n的阶乘值
return 0;
}
int main()
{
float term, result = 1;
int n;
for (n = 2; n <= 100; n += 2)
{
term = (n * n) / ((n - 1) * (n + 1));
result *= term;
}
printf("pi=%f\n", 2 * result);
return 0;
}
运行结果:
pi=2.000000
为什么会出现这种情况?
不难发现,pi的输出值为整数,所以可能是计算时出现了错误,代码第7行中由于n时整型,整型之间的除法还是整型,这就是错误的原因,应当修改为:
int main()
{
float term, result = 1;
int n;
for (n = 2; n <= 100; n += 2)
{
term = (float)(n * n) / (float)((n - 1) * (n + 1));
result *= term;
}
printf("pi=%f\n", 2 * result);
return 0;
}
运行结果:
pi=3.126079
注意事项
1.不可在for循环体内修改循环变量,防止for循环失去控制
2.建议for语句的循环控制变量的取值采用“前闭后开区间”写法
如:for (i = 1; i < 10; i++) 左开右闭,效果更好
break和continue
break语句
在循环体中写入break语句,会导致本次循环直接结束从而进入下一次循环,但是break语句只能跳出一层循环,嵌套循环的使用的话可能需要使用多个break或goto语句
int i = 0;
for (i = 1; i <= 10; i++)
{
if (i == 5)
{
break;
}
printf("%d ", i);
}
运行结果:
1 2 3 4
当i的值为5时,会执行break语句,从而跳出这个循环,所以会导致循环语句到i的值为5时就结束了
continue语句
在循环体中写入continue语句意味着开始执行下一次循环,即只结束本次循环的执行,并不终止整个循环的执行
int i = 0;
for (i = 1; i <= 10; i++)
{
if (i == 5)
{
continue;
}
printf("%d ", i);
}
运行结果:
1 2 3 4 6 7 8 9 10
当i的值为5时,会执行continue语句,直接开始下一次循环,但是仍然会执行本次循环的增值语句,所以会继续打印之后的数字
while循环
语法结构
while(表达式)
循环语句;
break语句的应用
int i = 1;
while (i <= 10)
{
if (i == 5)
{
break;
}
printf("%d", i);
i++;
}
运行结果:
1234
continue语句的应用
int i = 1;
while (i <= 10)
{
if (i == 5)
{
continue;
}
printf("%d", i);
i++;
}
运行结果:
1234(光标闪烁)
光标闪烁意味着程序没有执行完毕,所以可以理解为程序进入了死循环,原因是由于当i的值为5时,会遇到continue,跳过本次循环,执行下一次循环,但并不会执行增值语句,所以在下一次循环中i的值仍是5,导致不断进入循环和退出循环,从而进入了死循环
应用
int ch = 0;
while ((ch = getchar()) != EOF)
{
putchar(ch);
}
运行结果:
A
A
123
123
(光标闪烁)
(1)EOF=end of file ,文件结束标志,其值为-1
(2)如何让getchar读取EOF?输入 Ctrl+z就会读取结束
(3)例如:输入A后,先读取A,再读取\n,即换行,此时缓冲区内空,所以需要再次输入,输入123后,依次读取123\n
应用实例:
(1)清理缓冲区多个字符
char password[20] = { 0 };
printf("请输入密码:");
scanf("%s", &password);
printf("请确认密码(y/n):");
int ch = getchar();
getchar();//清理缓冲区,处理'\n'
if (ch == 'y')
{
printf("确认成功\n");
}
else {
printf("确认失败\n");
}
但是如果输入“123456 abc”仍然会失败,因为getchar只能处理一个,而后面的abc\n无法处理,让然会被下面的getchar读取,因此做出如下改进:
char password[20] = { 0 };
printf("请输入密码:");
scanf("%s", &password);
printf("请确认密码(y/n):");
int tmp = 0;
while ((tmp = getchar() != '\n'))//清理缓冲区的多个字符
{
;
}
int ch = getchar();
if (ch == 'y')
{
printf("确认成功\n");
}
else {
printf("确认失败\n");
}
(2)打印特定区间内的字符
int ch = 0;
while ((ch = getchar()) != EOF)
if (ch < '0' || ch>'9')
{
continue;
putchar(ch);
}
可以实现从输入数据中找到特定字符进行输出的效果
注意:在while语句后面加分号,可能导致死循环
i = 1;
while (i <= n);
{
sum+=i;
i++;
}
相当于
i = 1;
while (i <= n)
{
;
}
sum+=i;
i++;
do while循环
语法结构
do
循环语句;
while(表达式);
先执行,再判断,while语句是先判断再执行
break语句的应用
int i = 1;
do
{
if (i == 5)
{
break;
}
printf("%d ", i);
i++;
} while (i <= 10);
运行结果:
1 2 3 4
continue语句的应用
int i = 1;
do
{
if (i == 5)
{
continue;
}
printf("%d ", i);
i++;
} while (i <= 10);
运行结果:
1 2 3 4 (光标闪烁)
do while和while的区别
当第一次测试循环结果就为假时,二者就是有区别的
int main()
{
int n = 101;
while (n < 100)
{
printf("n=%d\n", n);
n++;
}
printf("n=%d\n", n);
return 0;
}
运行结果:
n=101
n的初值不小于100,循环一次也不执行
int main()
{
int n = 101;
do
{
printf("n=%d\n", n);
n++;
} while (n < 100);
printf("n=%d\n", n);
return 0;
}
运行结果;
n=101
n=102
n的初值不小于100,但循环至少执行一次
goto语句
语法结构
goto 语句标号;
goto语句为无条件转向语句,它既可以向下跳转,也可以往回跳转
它的作用是在不需要任何条件的情况下直接使程序跳转到该语句标号所标识的语句去执行
int main()
{
flag:
printf("haha\n");
goto flag;
return 0;
}
运行结果:
死循环地打印haha
生成随机数测试
写一个猜字游戏
1.自动生成1-100随机数
2.猜数字
3.可以中途退出
void menu()
{
printf("*****************************************\n");
printf("***************1.play********************\n");
printf("***************2.exit********************\n");
printf("*****************************************\n");
}
void game()
{
//生成随机数
int guess = 0;
int num = rand()%100+1;//取得1-100之间的随机数
//rand函数返回一个0-32767之间的随机数,使用种子,改变范围
//在使用rand函数之前需要调用srand,否则rand生成的数字不完全随机,即每个第1/2/...生成的数字相同
//srand()需要传一个整型值进入,但传一个整型值会导致每次生成的随机数一致,所以选择传入时间
// 时间-时间戳,即以秒为单位,现在时间相对于计算机起始时间的差值
//猜数字
while(1)
{
printf("请输入你所猜的数字:");
scanf("%d", &guess);
if (guess > num)
{
printf("猜大了\n");
}
else if (guess < num)
{
printf("猜小了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;
}
}
}
//由于srand是生成种子的函数,rand是生成随机数的函数,且给rand一个相同的参数
//通过循环可以生成不同的值,但两个相邻的参数会导致rand函数在相同的第某次的输出结果相近
//所用用time函数随时改变,这样就能生成看似没有关联的随机数了
//但如果将srand函数放在循环中,则每回都会生成一个种子,这样rand函数相当于只循环第一次,则生成的随机数会相同或相近
//所以将srand函数放在main函数里面,这样用一个相同的种子,根据算法,生成关联度极低的随机数
int main()
{
srand(unsigned int(time(NULL)));
int choice = 0;
//先执行,之后再进行判断是否继续进行,使用do while循环
do
{
menu();//打印菜单
printf("请选择:");
scanf("%d", &choice);
switch (choice)
{
case 1:
game();
break;
case 2:
printf("已退出\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (choice != 2);
return 0;
}
(1)利用求余运算rand()%b将函数rand()生成的随机数变化在[0,b-1]上
(2)利用rand()%b+a将随机数的取值范围平移到[a,a+b-1]上
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
int ret;
int guess = 0;
int counter = 1;
char choise=' ';//保存用户回答
//生成随机数
int number = 0;
unsigned int seed;
seed = time(NULL);
srand(seed);//生成种子
do
{
counter = 1;//猜下一个数之前,计数清零
choise = 'n';
number = rand() % 100 + 1;
printf("%d\n", number);
do
{
//猜数字
flag:
printf("请输入您猜的数字:");
ret=scanf("%d", &guess);
if (ret == 1)
{
if (guess > number)
{
printf("猜大了\n");
counter++;
}
else if (guess < number)
{
printf("猜小了\n");
counter++;
}
else if (guess == number)
{
printf("恭喜您,猜对了!\n");
break;
}
}
else
{
while ((getchar() != '\n'))//清理缓冲区的非法字符
{
;
}
goto flag;
}
} while (guess != number && counter <= 10);
//判断是否继续
printf("是否开始下一局游戏?(y/n):");
scanf(" %c", &choise);
} while (choise == 'y');
return 0;
}