顺序结构

程序从上往下运行。运行的结果跟你写的顺序有关系。

选择结构

if语句

语法形式1

if(表达式)

{

       语句;

}

如果表达式(条件)为真,就执行语句。如果是假,就结束了。

花括号一定要写。

eg.输入一个整数,判断它是否为奇数。

int a;

scanf("%d",&a);

if(s % 2 == 1)

{

        printf("%d是奇数\n",a);

}

如果表达式是真的就会执行花括号里面的。

注意if的小括号后面不要加分号。不要 加 分号。

if的花括号一定要记得写。因为不写花括号默认if下面的只有一行语句。要写多行语句一定要记得加花括号。为了保证可读性请一定要 加 花括号。

如果考试考了那就是只是为了考试而已。

语法形式2

if(表达式)

{

         语句1;

}

else

{

         语句2;

}

如果表达式为真就执行语句1,否则执行语句2。

eg.输入一个整数,判断是否为奇数。如果是奇数打印奇数,否则打印偶数。

int a;

scanf("%d",&a);

if(s % 2 == 1) //注意是两个等号。

{

        printf("%d是奇数\n",a);

}

else

{

        printf("%d是偶数\n",a);

}

如果是要多组输入的话就用一个while,把scanf放进去。

while(scanf("%d",a) != -1)

{

       if else巴拉巴拉的

}

语法形式3

if(表达式1)

{

       语句1;

}

else if(表达式2)

{

        语句2;

}

else

{

        语句3;

}

有一个东西。 n >= 5 && n < 10。&&是同时,并且的意思。

逻辑运算符

!逻辑取反

!真——>假

int a = 1;

printf("%d\n",!a); //0。c语言里,非0代表真,0代表假。

 a     !a

非0   0

 0      1

&&逻辑与

表达式1 && 表达式2

都真才真,一假全假。(联言判断)

a     b     a&&b

非0   非0    1

非0    0      0

0     非0     0

0       0       0

示例:输入一个月份,如果是在3月到5月之间则输出春季。

短路与  表达式1 && 表达式2

如果表达式1为假,就不去判断表达式2了。

if(month >= 3 && month <= 5)

如果month >= 3不成立,就不会执行month <= 5的表达式。

|| 逻辑或

有真就真,都假才假。(相容选言判断)

a       b     a||b

非0   非0   1

非0    0      1

0      非0    1

0       0       0

示例:输入一个月份,如果是在12月或者1月或者2月则输出冬季。

if(month == 12 || month == 1 || month == 2)

短路或:如果表达式1为真,就不执行表达式2了。

int month;

int a = 1;

scanf("%d",&a);

if(month == 12 || ++a)

{

         printf("冬季\n");

}

printf("%d\n",a);

如果输入的是12,那最后会输出冬季还有1,a的值还是1。因为短路或,如果第一个表达式是真就不会执行第二个表达式了。因为month == 12为真所以不会执行++a。

如果输入的是10,那最后会输出冬季还有2。首先month == 12不满足,所以会继续往下执行表达式2。++a的结果是2,非0,为真,所以if后的表达式为真,会输出冬季。同时运算过后的a现在的值是2。

练习:输入一个年份,判断是不是闰年。

思路:闰年的判断方法:

普通闰年:能被4整除但是不能被100整除的年份是闰年。

世纪闰年:能被400整除的年份是闰年。

if((year % 4 == 0) && (year % 100 != 0))

else if(year % 400 == 0)

else

代码可以合并

if((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))

else

老师说加括号是为了确保逻辑清晰所以还是加上吧加上又不会错。

switch语句

是一种特殊形式的if else结构,用于判断条件有多个确定结果的情况。它把多重的else if改成更易用,可读性更好的形式。

switch(整型表达式) //字符型,整型。浮点型就不行。

{

        case 整型常量1: 语句;

        case 整型常量2: 语句;

        ......

        default: 语句;

}

示例:输入一个数据,根据数据的值进行匹配。

int num;

scanf("%d",&num);

switch(num)

{

    case 1:

        printf("1\n");

        break;

    case 2:

        printf("2\n");

        break;

    default:

        printf("输入有误\n");

}

能不能不写break。如果case1后面不写break,输入了1。理论上应该要输出1,但是会发现输出的是1和2。是因为没有break的话会去找下一个break。break的作用是,当你匹配到了某一个case之后,这个switch就结束了。如果没有break,就会一直往后走直到找到下一个break。

不加也有应用。

int num;

    scanf("%d",&num);

    switch(num)

    {

        case 1:

        case 2:

        case 3:

        case 4:

        case 5:

            printf("工作日\n");

            break;

        case 6:

        case 7:

            printf("周末\n");

            break;

        default:

            printf("输入错误\n");

            break;

    }

一般用if会多一点。后面有例子。

循环结构

while循环

while(表达式)

{

    语句;

}

条件为真时重复执行代码,适合循环次数未知的场景。(不是硬性要求)

示例:在屏幕上打印1-10的值。

int i = 1;

    while(i <= 10)

    {

        printf("%d\n",i);

        i++;

    }

注意:初始化条件(i = 1) 判断条件(i <= 10) 条件的变化(i++)缺一不可

小心变成死循环。

如果初始条件为假,循环体一次也不执行。

练习1:输入一个正的整数,逆序打印这个整数的每一位。

1234——>4 3 2 1     521——>1 2 5

思路:123——>3 2 1 个位十位百位

怎么拿到各位数字3

十进制

123%10=3 123/10=12

12%10=2 12/10=1

1%10=1 1/10=0

0 结束

循环

// int main()

// {

//     int n;

//     scanf("%d",&n);

//     while(n != 0)

//     {

//         printf("%d ",n % 10); //3 2 1

//         n = n / 10; //12 1 0

//     }

// return 0;

// }

总结:要拿到十进制数的每一位,先%10后/10。同理,要拿到二进制数的每一位,先%2后/2。

练习2:求5的阶乘。

思路:要拿到1到5的所有整数。

// int main()

// {

//     int n;

//     scanf("%d",&n);

//     int i = 1;

//     int ret = 1;

//     while(i <= n)

//     {

//         ret = ret * i; //规定一个变量积累累乘的乘积。

//         i++;

//     }

// printf("%d\n",ret);

// return 0;

// }

讲了一个问题。

char a;

scanf("%c",&a);

char b;

scanf("%c",&b);

printf("%c,%c\n",a,b);

这个时候会发现一个事情。如果输入的是a b(中间有一个空格),输出的结果会是a,(没有b)。如果输入的是a回车,输出的结果还是a,(没有b)。

原因是定义的变量类型是字符,空格和回车也是字符,就把空格和回车赋进b里去了,输入的那个b就相当于没用。

解决这个问题的方法是getchar。把程序变成

char a;

scanf("%c",&a);

getchar(); //作用是把空格或者回车吸收进去。几个getchar几个空格。

char b;

scanf("%c",&b);

for循环

已知循环次数时使用,三种循环中使用最多的,适合遍历数组或集合。

for(表达式1;表达式2;表达式3)

{

    循环体语句;

}

表达式1用于循环条件初始化,表达式2用于循环结束时条件的判断,表达式3用于循环变量的调整。

for循环的执行顺序,第一次是表达式1,表达式2,循环体,表达式3。之后就是表达式2,循环体,表达式3,表达式1就没了,只用于变量的初始化。

int i = 1;表达式1

    while(i <= 10) 表达式2

    {

        printf("%d\n",i);

        i++; 表达式3

    }

变成for循环就是

for(int i = 1; i <= 10;i = i + 1) //要写那个定义变量的int。还有就是i = i + 1可以写成i++。

{

    printf("%d\n",i);

}

练习:求1到100之间2的倍数的数之和。

// int main()

// {

//     int sum = 0;//存和

//     for(int i = 1; i <= 100; i++)

//     {

//         if(i % 2 == 0)

//         {

//             sum = sum + i;

//         }

//     }

//     printf("%d\n",sum); //在循环外面打印

//     return 0;

// }

do-while循环

用的最少,保证循环体至少被执行一次。

do

{

    循环体语句;

}

while(表达式); //跟其他的区分,分号必须要写。

do-while是先斩后奏来的。很少用。

循环嵌套

练习:打印九九乘法表

思路:i*j=n

int main()

{

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

    {

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

        {

            printf("%d*%d=%d",i,j,i*j);

        }

    }

    return 0;

}

结果对。格式不对。而且多了。

int main()

{

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

    {

        for(int j = 1; j <= i; j++) //重复的不用打印

        {

            printf("%d*%d=%2d ",j,i,i*j); //一位数字右对齐。式子之间加空格。两个乘数换顺序。

        }

        printf("\n"); //换行

    }

    return 0;

}

总结:先写再改。

示例:求一个整数存储再内存中的二进制中1的个数。

思路1:按位与。

0000 0101

0000 0001        

——————

               1    

& 按位与1。最后一位结果是1原数字最后一位就是1,结果是0原数字最后一位就是0.然后原数字右移一位,再与1,跟上一次同理。

直到原数字全部为0了,就没有与的必要了。

问题:负数不行。符号位是1,不会全0,死循环。

思路2:要解决负数的问题。虽然负数不会变成全0,但是已知int有32个比特位,所以只要控制右移只进行三十一回就可以了。

思路3:再优化。

0000 0111  7

0000 0110  6

——————

0000 0110  6

0000 0101  5

——————

0000 0100  4

0000 0011  3

——————

0000 0000  0

num & (num -1)

每这样与一次,结果的二进制数里就少一个1。

break和continue

立即终止并跳出当前所在循环。

跳过本次循环尚未执行的语句,直接开始下一次循环的判断和执行。

while(i <= 10)

{

   if(i == 5)

    {

        break;

    }

printf("%d\n",i);

i++;

}

这个到i==4就停了。

输出结果是1 2 3 4。

练习:找到1-100之间第一个能被3整除的数。

while(i <= 10)

{

   if(i == 5)

    {

        continue;

    }

printf("%d\n",i);

i++;

}

把break换成continue了,代码死循环了。

continue是它下面的代码不执行了,重新开始循环。所以i到了5之后,就永远不会执行到i = i + 1那里了,永远都是5了,绕进去了。

while(i <= 10)

{

   if(i == 5)

    {

        i++;

        continue;

    }

printf("%d\n",i);

}

把i++放在continue上面,输出的结果就是1 2 3 4 6 7 8 9 10,没有5。因为等于5的时候不往下printf了,相当于把5那次循环跳过了。

break和return 0有什么区别。

break只用于循环和switch,return 0用于结束函数。两个用处不一样。

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

{

    if(i == 5)

    {

        continue;

    }

printf("%d\n“,i)

}

输出的结果还是1 2 3 4 6 7 8 9 10。。。我以为会死循环的。。为什么。。。

我明白了。是执行顺序没有理解好的问题。for循环的第三个表达式本来就是在循环节执行结束之后再执行的。所以在continue之外。

要区分while循环和for循环。

练习:找到1-100之间所有能被3整除的数,要求使用continue。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐