1. 分支语句误区

1.1 连续判断符号

#include<stdio.h>
int main()
{
int age = 10;
if (18<=age<28)
printf("青年\n");
return 0;
}

执行上面语句时,编译器给出如下warning:

main.c:6:16: warning: result of comparison of constant 28 with boolean expression is always true [-Wtautological-constant-out-of-range-compare]
if (18<=age<28)
~~~~~~~^~~
1 warning generated.

这是因为在if语句中,会先执行18<=age,把得到的结果0(或1)与28进行比较

正确的代码段应该是:

if (18<=age && age<28)
printf("青年\n");

1.2 悬空else:else和离他最近的未匹配的if进行匹配

int a = 0;
int b = 2;
if (a == 0)
if (b==1)
printf("hehe\n");
else
printf("haha\n"); // 会被执行

执行上面语句时,程序输出 ​​haha​​ , 编译器给出如下warning:

main.c:15:5: warning: add explicit braces to avoid dangling else [-Wdangling-else]
else
^
1 warning generated.

这是悬空else产生的warning,上面代码段的实际运行效果和下面的是一样的:

if (a == 0)
{
if (b==1)
printf("hehe\n");
else
printf("haha\n");
}

2. switch语句

switch (整形表达式)
{
语句项;
}

示例:

int day = 0;
scanf("%d", &day);

switch (day)
{
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n");
break;
case 3:
printf("星期三\n");
break;
case 4:
printf("星期四\n");
break;
default:
printf("所输入的数字不是1,2,3,4其中之一\n");
break;
}

注:如果没有 ​​break​​ 语句,则在结束前不会跳出switch语句,这个特性也可以被我们利用,比如如果输入的数字是1~5的话,要求打印工作日,是6或7的话,要求打印休息日,否则打印其他信息:

int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("工作日\n");
break;
case 6:
case 7:
printf("休息日\n");
break;
default:
printf("所输入的数字不是1~7之一\n");
break;
}
return 0;

注意,default是可有可无的,一般用来处理意料之外的case,在顺序,上推荐放在switch语句的最后

3. 循环语句

3.1 while 循环

  1. while循环的基本使用:
#include <stdio.h>

int main() {
int i = 1;

while (i <= 10) {
printf("%d\n", i);
i++;
}

return 0;
}
  1. while循环中要注意:
int num;
int b = 1;
while ((num = 1 + 2) == 3)
{
printf("this is a test code\n");
b ++;
if (b == 5)
break;
}

​ 上述循环体中的内容会执行,这也是下面的例子中 ​​while ((ch = getchar()) != '\n')​​ 起作用的原因;

C语言学习之-分支与循环_循环

  1. while循环使用的具体例子:
#include <stdio.h>
#include <string.h>

int main()
{
char ret = 0;
int ch;

char password[20] = {0};
printf("请输入密码:>");
scanf("%s", password);
printf("您输入的密码是:>%s\n", password);
while ((ch = getchar()) != '\n')
{
;
// printf("请忽略本行: ch is %c\n", ch); // 可以放一个空语句 `;`
}
printf("请确认 Y/N :>");
ret = getchar();
printf("ret是:>%c\n", ret);
// if (strcmp(&ret, "Y") == 0)
if ( ret == 'Y')
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
return 0;
}

3.2 for 循环

  1. for循环是使用最多的循环结构,for循环的基本使用如下:
#include <stdio.h>

int main() {
int i;
/*打印1~10*/
for (i = 1; i <= 10; i++) {
printf("%d ", i);
}

return 0;
}
  1. for循环的初始化、判断、调整都可以省略,但是,for循环的判断部分如果被省略,那判断条件就是:恒为真;如果不是非常熟练,建议不要随便省略。
for (; ; ) {
printf("hehe\n");
}

上面的代码就会一直打印 ​​hehe​

#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;
}

上面的代码会打印出9个 ​​hehe​​ ,那如果把初始化省略呢?

#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个 ​​hehe​

  1. for循环的变种
int x;
int y;
for (x = 0, y = 0; x < 2 && y<5; x++, y++)
{
printf("hehe\n");

}

会打印2个 ​​hehe​

  1. 注意事项
int x;
int y;
for (x = 0, y = 0; x = 0; x++, y++)
{
printf("hehe\n");
}

上面不会打印出来 ​​hehe​​​ ; 因为判断部分是 ​​x=0​​​ ,该表达式的值就是赋值后的 ​​x​​ 的值,所以不会进入到循环体;

3.3 do while 循环

循环语句至少要被执行一次,执行第二次循环语句前会使用while后面的表达式进行判断,为真才执行第二次循环语句;

#include <stdio.h>

int main() {
int i = 1;

do {
printf("%d\n", i);
i++;
} while (i <= 10);

return 0;
}

4. 题目

4.1 计算n的阶乘

int calc_factorial(int num)
{
int res = 1;
while (num)
{
res = res * num;
num --;
}
return res;
}

4.2 计算: 1!+2!+...+10!

int sum = 0;
for (int i= 1; i<=10; i++)
{
sum = sum + calc_factorial(i);
}

4.3 在一个有序数组中查找数字n

  1. 暴力查找:
#include <stdio.h>

int main()
{
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int num = 10;
int i = 0;
int length = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < length; i++)
{
if (arr[i] == num)
{
printf("找到了, 下标是%d\n", num);
break;
}
}
if (i == length)
printf("没找到\n");
return 0;
}

2:二分查找

#include <stdio.h>

int main()
{
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int num = 10;
int i = 0;
int j = sizeof(arr) / sizeof(arr[0]);
if (num > arr[j - 1] || num < arr[0])
printf("没找到\n");
else
{
while (i < j)
{
int mid = (i + j) / 2;
if (arr[mid] == num)
{
printf("找到了,下标为%d\n", mid);
break;
}
else if (arr[mid] < num)
i = mid;
else
j = mid;
}
if (i >= j)
printf("没找到\n");
}

return 0;
}
  1. 二分查找的更高效的写法
#include <stdio.h>

int main()
{
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int num = 7;
int i = 0;
int j = sizeof(arr) / sizeof(arr[0]);
if (num > arr[j - 1] || num < arr[0])
printf("没找到\n");
else
{
while (i <= j)
{
int mid = (i + j) / 2;
if (arr[mid] == num)
{
printf("找到了,下标为%d\n", mid);
break;
}
else if (arr[mid] < num)
i = mid + 1;
else
j = mid - 1;
}
if (i > j)
printf("没找到\n");
}

return 0;
}