C语言的知识

转义字符

 

 \130是8进制,转换成10进制是88,以88作为ASCII码值的字符是X。

1X8X8+3X8+0X1=88

\x30中的30是16进制,转换成10进制是48,以48作为ASCII码值的字符是O。

3X16+0X1=48

举个例子

#include<stdio.h>
#include<string.h>
int main()
{
    int len=strlen("C:\test\class111\123.c");//\c虽然不是转义字符,但是被编译器当成转义字符来识别的
    printf("%d", len);
    return 0;
}

结果:17

                                    c语言语句

C语言的代码是由一条一条语句构成的,C语言中的语句分为以下五类:

1、空语句:

#include<stdio.h>
int main()

{

    ;//空语句

    return 0;

}

2、表达式语句:

在表达式后边加上分号。

3、函数调用语句:

函数调用的时候,也会加上分号,就是函数调用语句

printf();//函数调用语句

4、复合语句:

代码块

5、控制语句:

控制语句用于控制程序的执行流程,以实现程序的各种结构方式,它们由特定的语句定义符组成,C语言有9种控制语句,可分为三类:

(1)条件语句:

if语句、switch语句;

switch

 switch语句中表达式的类型只能是:整形和枚举类型

case语句后一般放整形结果的常量表达式或者枚举类型,枚举类型也可以看成是一个特殊的常量

没有规定case必须在default之前,一般case最好放在default之前

switch语句中的default子句可以放在任意位置

switch语句中case表达式不要求顺序,但一般还是按照次序来

#include<stdio.h>
int main()
{
    int a = 0;
    int b = 0;
    func(a);
    scanf_s("%d", &a);
    printf("%d", b);
    return 0;
}
int func(int a)
{
    int b;
    switch (a)
    {
    case 1:b = 30;
    case 2:b = 20;
    case 3:b = 16;
    default:b = 0;
    }
    return b;

}

 

 

 switch的每个case之后如果没有加break语句,当前case执行结束后,会继续执行紧跟case中的语句。

  func(1)可知,在调用func时形参a的值为1,switch(a)<==>switch(1),case 1被命中,因为该switch语句中所有分支下都没有增加break语句,因此会从上往下顺序执行,最后执行default中语句返回。
 

if

#include <stdio.h>
int main() {
    int x = 3;
    int y = 3;
    switch (x % 2) {
    case 1:
        switch (y)
        {
        case 0:
            printf("first");
        case 1:
            printf("second");
            break;
        default: printf("hello");
        }
    case 2:
        printf("third");
    }
    return 0;
}

 switch的每个case之后如果没有加break语句,当前case执行结束后,会继续执行紧跟case中的语句。

进入的第一个case只是入口。

   即:先在内部switch的default位置打印hello,紧接着在外部case2中打印third

#include<stdio.h>

 int main()

  {

   int a = 0, b = 0;

    // for循环将a和b的初始值均设置为1

   for (a = 1, b = 1; a <= 100; a++)

   {

   if (b >= 20) break;

   if (b % 3 == 1)

   {

   b = b + 3;

   continue;

   }

   b = b-5;

   }

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

   return 0;

  }

  第一次循环:a = 1,b=1--->b小于20,if不成立,b%3==1%3==1成立,b=b+3, 此时b的值为4

  第一次循环:a = 2,b=4--->b小于20,if不成立,b%3==4%3==1成立,b=b+3, 此时b的值为7

  第一次循环:a = 3,b=7--->b小于20,if不成立,b%3==7%3==1成立,b=b+3, 此时b的值为10

  第一次循环:a = 4,b=10--->b小于20,if不成立,b%3==10%3==1成立,b=b+3, 此时b的值为13

  第一次循环:a = 5,b=13--->b小于20,if不成立,b%3==13%3==1成立,b=b+3, 此时b的值为16

  第一次循环:a = 6,b=16--->b小于20,if不成立,b%3==16%3==1成立,b=b+3, 此时b的值为19

  第一次循环:a = 7,b=19--->b小于20,if不成立,b%3==19%3==1成立,b=b+3, 此时b的值为22

  第一次循环:a = 8,b=22--->b大于20,if成立,循环break提出

  最后打印a:8

验证:

(2)循环语句:

do while语句、while语句、for语句。

                                          注释

一、注释是对代码的说明,编译器会忽略注释。好的适度的注释可以帮我们很好的理解代码。

1、/*      内容    */

2、

/*

内容

 */

3、内容/*.....*/内容   

编译时,  /*....*/被替换成空格

4、内容

      //注释

 5、   内容//注释

二、/*     */注释可以分行——以/*开始,*/结束的块式注释

// 注释只能单行——此种注释范围从//开始,以换行符\n结束的单行注释

三、

/**/不支持嵌套使用

四、双引号里面的注释符号,被视为普通字符,没有注释作用。

在字符串里的//和/*都不作为注释的开始。而是作为字符串的一部分。

​​​​​​​

                                C语言的数据类型和变量

数据类型

 整数变量声明为unsigned的好处是,同样长度的内存能够表示的最大整数值,增大了一倍。

 1、字符型 char

[signed] char                            取值范围;-128~127 

unsigned char                           取值范围;0~255

2、整型

  (1)整型 int=[signed] int           

unsigned [int]

(2)短整型 short [int]

[signed] short [int]                      取值范围;-32768~32767

unsigned short [int]                    取值范围;0~65535

   (3)长整型 long [int]

[signed] long [int]

unsigned long [int]

 (3)长长整型 long long [int]

[signed] long long [int]

unsignedlong long [int]

3、浮点型

单精度浮点型 float

双精度浮点型 double

long double

4、布尔类型    _Bool

0表示假,非0表示真。

布尔类型的使用得包含头文件<stdbool.h>

布尔类型变量的取值是:true或者false

               

                                    创建变量 

变量创建的本质是在内存上开辟空间。

int a=10;要向内存申请4个字节的空间,存放数据10

1、数据类型+变量名

2、变量在创建的时候就给一个初始值,就叫初始化。

3、变量的分类
全局变量:在大括号外部定义的变量就是全局变量
全局变量的使用范围更广,整个工程中想使用,都是有办法使用的。
局部变量。在大括号内部定义的变量就是局部变量
局部变量的使用范围是比较局限,只能在自己所在的局部范围内使用的。

遵循就近原则:当局部变量和全局变量同名的时候,局部变量优先。

例子:

#include<stdio.h>

int a=2023;//全局变量

int main()

{

      {

        int a=2022;//局部变量

         printf("%d\n",a);//局部优先

       }

printf("%d\n",a);//全局优先

return 0;

}

结果:

2022

2023

4、全局变量和局部变量在内存中存储在哪里呢?

一般我们在学习C/G++语言的时候,我们会关注内存中的三个区域:栈区、堆区、静态区。
1.局部变量是放在内存的栈区
2.全局变量是放在内存的静态区
3.堆区是用来动态内存管理的

5、复合语句中定义的变量只能在复合语句中使用

                                              原码、反码、补码

原码、反码、补码

这里不涉及小数(浮点数)

整数的2进表示方法有二种,即原码、反码和补码。
三种表示方法均有符号位数值位两分,符号位都是用0表示“正”,用1表示“负”,
最高位的一位是被当做特号位,剩余的都是数值位。

整型占用4个字节=32个bit(可以参照本目录计算机的常见单位)
有符号的整数——正整数和无符号整数的原、反、补码都相同。

int a=1;

原码  00000000  00000000  00000000  00000001

反码  00000000  00000000  00000000  00000001

补码  00000000  00000000  00000000  00000001


有符号的整数——负整数的三种表示方法各不相司,

原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码。
反码:将原码的符号位不变,其他位依次取反就可以得反码。
补码:反码+1就得到补码,

int a=-1;

原码  10000000  00000000  00000000  00000001

反码  11111111  11111111  11111111  11111110

补码  11111111  11111111  11111111  11111111
 

加法和减法


对于整型来说:数据存放内存中其实存放的是补码,并且倒着存,打印出来的是原码。

在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理,

1+(-1)如果用原码计算
    1的原码  00000000 00000000 00000000 00000001
    -1的原码 10000000 00000000 00000000 00000001
    10000000 00000000 00000000 00000010=-2

X
    
    1+(-1)如果用补码计算
    1的补码   00000000 00000000 00000000 00000001
    -1的补码  11111111 11111111 11111111 11111111
    1 00000000 00000000 00000000 00000000因为int存不下,所以把1丢了
    00000000 00000000 00000000 00000000=0

\/

同时,加法和减法也可以统一处理(CPU只有加法器,有了补码就可以算减法),

此外,补码和反码相互转换,其运算过程是相同的,不需要额外的硬件电路。

原码 取反 +1 到补码

补码 取反 +1 到原码

补码 -1  取反 到原码

原码          10000000 00000000 00000000 00000001
取反       11111111 11111111 11111111 11111110

 +1         111111111 11111111 11111111 11111111
 取反       10000000 00000000 00000000 00000000
  +1         10000000 00000000 00000000 00000001

                                    操作符

                                   算数操作符

+、  -、  *  、 / 、  %、(双目操作符)

除法/

上图中m得到2,原因在于C语言里面的整数除法是整除,只会返回整数部分,丢弃小数部分。下图可证明。

如果希望得到小数部分的结果,两个运算数必须至少有一个是浮点数,这时C语言就会进行浮点数除法。

运算符%

1、只能用于整数之间

2、

                                       赋值操作符   

一、赋值

在变量创建的时候给一个初始值叫初始化,在变量创建好后,再给一个值,这叫赋值。

#include<stdio.h>

int main()

{

int a=1;//初始化

a=2;//赋值

return 0;

}

二、从右向左,连续赋值

int a=1;

int b=2;

int c=3;

b=a+3;//拆开写

c=b;

                                        复合赋值符

+=、-=、*=、/=、%=、>>=、<<=、&=、|=、^=

                                        单目操作符

++、--、+(正)、-(负)

 自增、减操作符:a++、++a、a--、--a、

a=a+1;

a+=1;

a++;

++a;

自增:三个作用相同

a前置和后置的区别,放表达式中观察:

b=++a;分为两步:a=a+1;b=a;

a后置计算口诀:先++,后使用     

b=a++;分为两步:b=a;a=a+1;

a前置计算口诀:先使用,后++

                                                         移位操作符

移位操作符的操作数只能是整数,不要移动负数位,这个是标准未定义的

                                                                     <<左移操作符

左边丢弃,右边补0

                                                                      >>右移操作符

逻辑右移:右边丢弃,左边补0

大部分采用 算术右移:右边丢弃,左边补符号位

-1的补码  11111111 11111111 11111111 11111111
算术右移 1 11111111 11111111 11111111 1111111
逻辑右移 0 11111111 11111111 11111111 1111111

                                                    位操作符

位操作符的操作数只能是整数,

   按位与&

两个都为1才为1

用法

判断a的二进制位的补码的最后一位

#include<stdio.h>

int main()

{

int a = 21;
    int b = 0;
    b = a & 1;
    if (b == 1)    printf("a的补码第一位是1");
    else printf("a的补码第一位是0");
    //21的补码00000000000000000000000000010101
    //1的补码 00000000000000000000000000000001
    // a&1       00000000000000000000000000000001
    return 0;
}


 

#include<stdio.h>

int main()

{

int a = 21;
    int b = 0;
    b =( a>>4) & 1;
    if (b == 1)    printf("a的补码第五位是1");
    else printf("a的补码第五位是0");

 //21的补码  00000000000000000000000000010101

//21>>4      0000 0000000000000000000000000001 

}

    按位或|

有一个为1就为1

应用

将a的二进制中第五位改成1

#include<stdio.h>

int main()

{

int a = 13;
    a = (1 << 4) | a;
    printf("%d", a);
    //00000000 00000000 00000000 00001101
    //00000000 00000000 00000000 00010000
    return 0;
}

   按位异或^

对应的二进制位上相同为0

按位取反操作符~ —>

应用

二进制位是0的变1,1的变0

#include<stdio.h>

int main()

{

int n = 0;
    int a = ~n;
     printf("%d\n",a);
     //00000000 00000000 00000000 00000000  0的补码
     // 11111111 11111111 11111111 11111111 取反后的补码
     //10000000 00000000 00000000 00000000
     //10000000 00000000 00000000 00000001  原码-1
    return 0;
}

练习1:比较a和b的大小

 a^a=0

0^a=a

3^3^5=5

3^5^3=5

支持整数交换律 

方法一:

#include<stdio.h>

int main()

{

int a = 3;
    int b = 5;
    int temp = 0;
    temp = a;
    a = b;
    b = temp;
    printf("a=%d,b=%d", a, b);
    return 0; 

}

方法二:

#include<stdio.h>

int main()

{

int a = 3;
    int b = 5;
    int c=a + b;
    a = c - a;
    b = c - a;
    printf("a=%d,b=%d", a, b);
    return 0;
}


 

 方法三:不创建临时变量,实现两个数的交换

#include<stdio.h>

   int main(

 {

int a = 3;
    int b = 5;
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    printf("a=%d,b=%d", a, b);
    return 0;
}
 

 练习2:求一个整数存储在内存中的二进制中1的个数。

#include<stdio.h>

int main()

{

int a = 15;
    int count = 0;
    while (a)
    {
        if (a % 2 == 1)
        {
            count++;
         }
        a = a / 2;
    }
    printf("count=%d\n", count);
    return 0;
}

负数不适用

负数%2==负数

负数/2==0

退出循环

#include<stdio.h>

int main()

{

int a = 0;
    int count = 0;
    scanf_s("%d", &a);
    int i = 0;
    for (i = 0; i < 32; i++)
    {
        if (((a >> i) & 1) == 1)
            count++;
    }
    printf("count=%d\n", count);
    return 0;
}

//00000000 00000000 00000000 00001111   15的原码、反码、补码

//10000000 00000000 00000000 00000001    -1的原码

//11111111  11111111  11111111  11111110         -1的反码

//11111111  11111111  11111111  11111111         -1的补码

负数也适用

n = n & (n - 1);

n = 13;
1101-n
1100-n-1
1100-n&(n-1)

1100-n
1011-n-1
1000-n(n-1)
n的二进制序列中,最右边的1就消失了

#include<stdio.h>

int main()

{

int a = 0;
    int count = 0;
    scanf_s("%d", &a);
    while (n)
    {
        n = n & (n - 1);
        count++;
    }
    printf("count=%d\n", count);
    return 0;
}


 

负数也适用 

 练习3:判断一个数是否是2^n次方

#include<stdio.h>

int main()

{

int n = 0;
    scanf_s("%d", &n);
    if((n & (n - 1)) == 0)
    {
        printf("yes\n");
    }
    else printf("no\n");
    return 0;
}

                                                逗号操作符

优先级最低

逗号表达式:用逗号隔开的多个表达式。

从左到右依次执行。整个表达式的结果是最后一个表达式的结果。

#include<stdio.h>

int main()

{

    int a = 1;

    int b = 2;

    int c = (a > b, a = b + 10, b = a + 1);

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

    return 0;

}

//13

改造后

while(a=test1(),test2(a),a>0)

改造前

while(a>0)

{

a=test();

test2(a);

}

                                                   下标访问[]

操作数:一个数组名+一个索引值 (下标)

#include<stdio.h>
int main()
{
    int a[3] = { 1,2,3 };
    printf("%d\n", a[2]);//[]下标引用操作符//[]的操作数a,2
    return 0;
}

                                                    函数调用()

接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的 参数。

#include<stdio.h>
int main()
{
    int ret=Add(2, 3);//函数调用操作符()//()的操作数:Add,2,3
    printf("%d\n", ret);
    return 0;
}
int Add(int x, int y)//函数定义
{
    return x + y;
}

                                                 

                                  操作符的属性:优先级、结合性

 优先级相同,看结合性

优先级运算符描述结合性
1

++     - -

()

[]

->

(type){list}

后缀自增与自减

函数调用

数组下标

结构体与联合体成员访问

结构体与联合体成员通过指针访问

复合字面量(C99)

从左到右
2

++  - -

+  -

!~

(type)

*

&

sizeof

_Alignof

前缀自增与自减

一元加与减

逻辑非与逐位非

转型

间接访问(解引用)

取地址

取大小

对齐要求

从右到左
3* / %乘法、除法及余数从左到右
4+ -加法及减法从左到右
5<< >>逐位左移及右移从左到右
6

<   <=

>  >=

分别为小于与小于等于的关系运算符

分别为大于与大于等于的关系运算符

从左到右
7==   !=分别为等于与不等于关系从左到右
8&逐位与从左到右
9^逐位异或从左到右
10|逐位或从左到右
11&&逻辑与从左到右
12||逻辑或从左到右
13?:三元条件从右到左
14

=

+=   -=

*=  /=  %=

<<=   >>=

&=  ^=  |=

简单赋值

以和及差赋值

以积、商及余数赋值

以逐位左移及右移赋值

以逐位与、异或及或赋值

从右到左
15逗号从左到右

                                   表达式求值

表达式求值之前要进行类型转换,当表达式中的值转换到适当的类型,才开始计算。

整型提升

C语言中整型算术运算总是至少以缺省整型类型的精度来进行的。

为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。                                 char     short                                               int/unsigned int

规则:

1、有符号整数提升是按照变量的数据类型的符号位来提升的

有符号的整数,1个符号位和31个数值位

 2、无符号整数提升,高位补0

无符号的整数,没有符号位,32位都是数值位

算数转换

如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的类型转换成另一个操作数的类型,否则操作就无法进行。下面的层次体系称为寻常算术转换。

1、long double

2、double

3、float

4、unsigned long int

5、long int

6、unsigned int

7、int

从下到上

表达式求值

                                                  强制类型转换

int a=(double)3.14;//强制类型转换

                                              printf

基本用法

printf()的作用是将参数文本输出到屏幕。它名字里面的f代表 format (格式化),表示可以定制输出文本的格式。按照指定的格式打印数据。

printf()不会在行尾自动添加换行符,运行结束后,光标就停留在输出结束的地方,不会自动换行。

为了让光标移到下一行的开头,可以在输出文本的末尾,添加一个换行符\n。

 printf()是在标准库的头文件stdio.h定义的。使用这个函数之前,必须在源码文件头部引入这个头问文件。

占位符

printf()可以在输出文本中指定占位符。

所谓“占位符”,就是这个位置可以用其他值代入。

 上面示例中,love you %d days\n是输出文本,里面的%d就是占位符,表示这个位置要用其他值来替换。

占位符的第一个字符一律是%,第二个字符表示占位符的类型,%d表示这里代入的值必须是一个整数。

printf()的第二个参数就是替换占位符的值,上面的例子是整数1314替换%d,执行后的输出结果就是lova you 1314。

常见的占位符除了%d,还有%s表示代入的是字符串。

输出文本里面可以使用多个占位符。

printf()参数与占位符是一一对应关系,如果有n个占位符,printf()的参数就应该有n+1个。如果参数个数少于对应的占位符,printf()可能会输出内存中的任意值。

                                                          输出格式

printf()可以定制占位符的输出格式。

printf(%5d)允许限定占位符的最小宽度。
上面示例中,5d表示这个占位符的宽宝至少为5位。如果不满5位,对应的值的前面会添加空格。
输出的值默认是右对齐,即输出内前面会有空格;如果希望改成左对齐,在输出内容后面添加空格,可以在占位符的%的后面播入一个-号。

 对于小数,这个限定符会限制所有数字的最小宽度。

小数点默认打印6位。

 

                                                            限定小数位数

输出小数时,有时希望限定小数的位数。举例来说,希望小数点后面只保留两位,占位符可以写成%.2f。

 最小宽度和小数位数这两个限定值,都可以用*代替,如下:

 %.数字s限定输出部分字符串。

                                                       占位符列举

printf()的占位符有许多种类,与c语言的数据类型相对应。下面列出常用的占位符。

%a:16进制浮点数,字母输出为小写。

%A:16进制浮点数,字母输出为大写。

%c:字符。除了%c外,都会自动忽略起首的空白字符,返回当前第一个字符,无论该字符是否为空格,如果要强制跳过字符前的空白字符,可以写成" %c",即%c前加上一个空格,表示跳过0个或者多个空白字符。

%d:10进制整数。

%i:整数,基本等同于%d。

%e:使用科学计数法的浮点数,指数部分的e为小写。

%E:使用科学计数法的浮点数,指数部分的E为大写。

%f:小数(包含float类型和double类型)。

%g:6个有效数字的浮点数。整数部分一日超过6位,就会自动转为科学计数法,指数部分的e
为小写。
%G: 等同于%g,唯一的区别是指数部分的E为大写。
%hd: 十进制short int类型。
%ho: 八进制short int类型,
%hx: 十六进制short int类型。
%hu:  unsigned short int类型
%ld: 十进制long int类型。
%lo:  八进制long int类型。
%lx: 十六进制long int类型。
%lu: unsigned long int类型。

 %s:从当前第一个非空白字符开始读起,直到遇到空白字符(即表格、换行符、制表符等)为止。因为%s不会包含空白字符,所以无法用来读取多个单词,除非多个%s一起使用。scanf()遇到%s占位符,会在字符串变量末尾存储一个空字符\0。scanf()将字符串读入字符数组时,不会检测字符串是否超过了数组长度。所以,存储数组时,很可能会超过数组的边界,导致意想不到的结果。为了防止这个结果发生,使用%s占位符时,应该指定读入字符串的最长长度,多余的字符串会被丢弃。 %.数字s限定输出部分字符串。

%zd:size_t类型。

%%: 输出一个百分号。

                                                       scanf 

  'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.


方法一:scanf_s

scanf_s函数是VS这个IDE提供的,不是C语言标准库中的函数。
那就意味着你在你代码中使用了scanf_s函数。你的代码在其他的编译器上是不能通过编译的,使得代码就降低了可移植性。

#include<stdio.h>
int main()
{
    int n;
    scanf_s("%d", &n);
    printf("%d", n);
    return 0;
}

方法二:#define _CRT_SECURE_NO_WARNINGS放开头

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
    int n;
    scanf("%d", &n);
    printf("%d", n);
    return 0;
}

方法三:#pragma warning(disable:4996)放其他地方也可以

#pragma warning(disable:4996)

#include<stdio.h>
int main()
{
    int n;
    scanf("%d", &n);
    printf("%d", n);
    return 0;
}

*赋值忽略符,只要把*加在任何占位符的百分号后面,该占位符就不会返回值,解析后将被丢弃。

scanf()时 数组和指针变量不需要&。

 数组

数组是一组相同类型元素的集合。

数组分为一维数组和多维数组。

把一维数组做为数组元素的数组就是二维数组,二维数组作为数组元素的数组被称为三维数组,二维数组以上的数组统称为多维数组。

数组创建

一维数组                                                              二维数组

type arr_name[常量值]                                        type arr_name[常量值1][常量值2]

数组中存放数据的类型 数组名[数组的大小]

#include<stdio.h>                                               #include<stdio.h>
int main()                                                             int main()
{                                                                          {
    int math[3];                                                     int math[3][4];
    return 0;                                                          return 0;
}                                                                         }

数组的初始化

创建数组的时候,需要给定一些初始值,这种就称为初始化。

#include<stdio.h>
int main()
{

 int math[3] = { 1,2,3 };//一维数组

 int math[3][4] = { {1,2,3 ,4},{5,6,7,8},{9,10,11,12} };//二维数组//先放满一行

//行可以省略,列不行


    int math[3] = { 1,2,3 };//完全初始化
    int math1[3] = { 1,2 };//不完全初始化,剩余的元素初始化为0
    int math2[] = { 1,2,3 };//数组的大小,是编译器根据初始化的内容确定的
    return 0;
}

数组的类型

数组算是一种自定义类型,去掉数组名就是数组的类型。

#include<stdio.h>
int main()
{
    int math[3] = { 1,2,3 };//math的类型是int [3]
    int math1[3] = { 1,2 };//math1的类型是int [3]
    return 0;
}

数组下标

C语言规定数组是有下标的,从0开始,假设数组有n个元素,最后一个元素的下标是n-1,下标就相当于数组元素的编号,如下:

int arr[10]={1,2,3,4,5,6,7,8,9,10};

下标0~9

二维数组的行和列都是从0开始的。

下标引用操作符

在C语言中数组的访问提出了一个操作符[],这个操作符叫:下标引用操作符。
有了下标访问操作符,我们就可以轻松的访问到数组的元素了,比如我们访问下标为7的元素,我
们就可以使用arr[7],要访问下标是3的元素,就可以使用arr[3]。

#include<stdio.h>
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    printf("%d\n%d\n", arr[7], arr[3]);//下标访问操作符
    return 0;
}

#include<stdio.h>

int main()

{

int a[3][2]={1,2,3,4,5,6};

printf("%d\n",a[1][2]);

return 0;

}

#include<stdio.h>
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        printf("%d\n", arr[i]);
    }
    return 0;
}

#include<stdio.h>
int main()
{
    int arr[3][5] = { {1,2,3,4,5},{5,6,7,8,9},{1,2,34,4,5} };
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        int j = 0;
        for (j = 0; j < 5; j++)
        {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
    return 0;
}

C99 

#include<stdio.h>

int main()

{

    int n = 0;

    scanf_s("%d", &n);

            int arr[n];

    return 0;

}

C99之前数组的大小只能是常量、常量表达式指定,不能使用变量

C99之后为什么就是用了变量?变长数组C99中,引入了变长数组的概念,允许数组的大小是变量的。

VS虽然支持了C99的语法,但是不是全部支持,变长数组在VS上是不支持的。

变长数组不能初始化的。

数组大小可以指定。

数组的输入

#include<stdio.h>
int main()
{
    int a[10];
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        scanf_s("%d", &a[i]);
    }
    for (i = 0; i < 10; i++)
    {
        printf("%d\n", a[i]);
    }
    return 0;
}

#include<stdio.h>
int main()
{
    int arr[2][5];
    int i = 0;
    for (i = 0; i < 2; i++)
    {
        int j = 0;
        for (j = 0; j < 5; j++)
        {
            scanf_s("%d", &arr[i][j]);
        }
    }
    printf("\n");
    for (i = 0; i < 2; i++)
    {
        int j = 0;
        for (j = 0; j < 5; j++)
        {
            printf("%d  ", arr[i][j]);
        }
        printf("\n");
    }
    return 0;
}

 一维数组在内存中的存储

#include<stdio.h>
int main()
{
    int num[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        printf("num[%d]=%p\n", i,&num[i]);//%p用来打印地址的
    }
    return 0;
}

 10进制

0 1 2 3 4 5 6 7 8 9

2进制

0 1

8进制

0 1 2 3 4 5 6 7 

16进制

0 1 2 3 4 5 6 7 8 9   a   b   c   d   e    f

                              10 11 12 13 14 15

#include<stdio.h>
int main()
{
    int num[3][3] = { 1,2,3,4,5,6,7,8,9};
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        int j = 0;
        for (j = 0; j < 3; j++)
        {
            printf("num[%d][%d]=%p\n", i,j, &num[i][j]);//%p用来打印地址的

        }
    }
    return 0;
}

1、数组在内存中是连续存放的

2、随着下标的增长,地址是由低到高变化的

sizeof

sizeof中C语言是一个关键字,是可以计算类型或者变量大小的,其实sizeof也可以计算数组的大小。

#include<stdio.h>
int main()
{
    int arr[10] = { 1,2,3 };//10*4=40
    printf("%d\n", sizeof(arr));//sizeof(数组名)计算的是数组的所占内存空间的大小
    printf("%d\n", sizeof(arr[0]));
    printf("%d\n", sizeof(arr)/sizeof(arr[0]));//计算的是数组的元素个数
    int sz = sizeof(arr) / sizeof(arr[0]);
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

strlen

 


c语言中的strlen函数用于计算一个字符串中元素的个数,即从数组头部计数,直到遇到字符串结束符'\0'为止,计数结果不包括'\0'。

 sizeof和strlen

1.sizeof:在程序中计算字符串时把末尾'\0'计入在内。
2.strlen:是计算字符串的有效长度,不把末尾'\0'计入在内,直接是测量字符串长度。

函数的概念

C语言中的函数就是一个完成某项特定的任务的一小段代码。

这段代码是有特殊的写法和调用方法的。

C语言的程序其实是由无数个小的函数组合而成的,也可以说:一个大的计算任务可以分解成若干个较小的函数(对应较小的任务)完成。同时一个函数如果能完成某项特定任务的话,这个函数也是可以复用的,提升了开发软件的效率。

库函数和自定义函数

函数设计应该追求高内聚低耦合

高内聚低耦合即:函数体内部实现修改了,尽量不要对外部产生影响,否则:代码不方便维护

库函数
C语言标准中规定了C语言的各种语法规则,C语言并不提供库函数;C语言的国际标准ANSI C现定了一些常用的国数的标准,被称为标准库,那不同的编译器厂商根据ASI提供的C语言标准就给出了一系列函数的实现。这些函数就被称为库函数。
我们前面内容中学到的printf、scanf都是库函数,库函数的也是函数,不过这些函数已经是现成的,我们只要学会就能直接使用了。有了库函数,一些常见的功能就不需要程序员自己实了,一定程度提升了效率:同时库函数的质量和执行效率上都更有保证。
各种编译器的标准库中供了一系列的库函数,这些库函数根据功能的划分,都在不同的头文件中进行了声明。

自定义函数

ret_type fun_name(形式参数)

{

}

ret type是函数返回类型

fun_name是函数名

括号中放的是形式参数

{}括起来的是函数体

#include<stdio.h>
int main()
{
    int a = 0;
    int b = 0;
    scanf_s("%d %d", &a, &b);
    int c = add(a, b);
    printf("%d\n", c);
    return 0;
}
int add(int x, int y)
{
    int z = 0;
    z = x + y;
    return z;
}

简化:

#include<stdio.h>
int main()
{
    int a = 0;
    int b = 0;
    scanf_s("%d %d", &a, &b);
    int c = add(a, b);
    printf("%d\n", c);
    return 0;
}
int add(int x, int y)
{
    return (x+y);
}

形参和实参


#include<stdio.h>
int main()
{
    int a = 0;
    int b = 0;
    scanf_s("%d %d", &a, &b);
    int c = add(a, b);//a和b是真实传递给add的参数,是实际参数,简称实参
    printf("%d\n", c);
    return 0;
}
int add(int x, int y)//形式上的参数,简称形参
{
    return (x+y);
}
形式参数只有在函数被调用的过程中为了存放实参传递过来的值,才向内存申请空间,这个过程就是形式的实例化。

我们在调试的时候可以观察到,x和y确实得到了a和b的值,但是x和y的地址和a和b的地址是不一样的,所以我们可以理解为形参是实参的一份临时拷贝。

 exec((vl,v2),(v3,v4),v5,v6) 总共有四个参数

 (v1, v2)属于第一个实参,逗号表达式,真实的参数是v2

 (v3,v4)属于第二个实参,逗号表达式,真实的参数是v4

 v5属于第三个实参

 v6属于第四个实参

return语句

一、return+数值;

return+表达式;

return;

函数中需要提前结束,但是函数的返回类型是void,不需要返回任何值的时候,就使用return;

二、return的返回值和函数返回类型不一致,系统会自动将返回的值隐式转换为函数的返回类型。

#include<stdio.h>
int main()
{
    int n = test();
    printf("%d", n);
    return 0;
}
int test()
{
    return 3.14;
}

3

三、函数中可以没return语句,只有需要返回值,或者提前结束函数的是才使用retutrn。

return语句执行后,函数就彻底返回,后边的代码不再执行。

如果函数中存在if等分支的语句,则要保证每种情况下都有return返回,否则会出现编译错误。不是所有的路径都有返回值。

#include<stdio.h>
int main()
{
    int n = test();
    printf("%d", n);
    return 0;
}
int test()
{
    int m = 0;
    if (m == 5)//n=5才有返回
        return 1;

//else return -1;
}

数组做函数参数

函数的形参要和函数的实参个数匹配

函数的实参是数组,数组大小可以省略不写

形参如果是二维数组,行可以省略,但是列不能省略

数组传参,形参是不会创建新的数组的

形参操作的数组和实参的数组是同一个数组

#include<stdio.h>

int main()

{

int arr[]={1,2,3,4,5,6,7,8,9,10};

int sz=sizeof(arr)/sizeof(arr[0]);

set_arr(arr,sz);

print_arr(arr,sz);

return 0;

}

void set_arr(int arr[],int sz)

{

for(int i=0;i<sz;i++)

{

arr[i]=-1;

}

}

void print_arr(int arr[],int sz)

{

for(int i=0;i<sz;i++)

{

printf("%d ",arr[i]);

}

printf("\n");

}

嵌套调用和链式访问

一、嵌套调用

就是函数之间的互相调用。

int is_leap_year(int y)
{
    if ((y % 400 == 0) || ((y % 4 == 0) && (y % 100 != 0)))
        return 1;
    else
        return 0;
}
int get_days_of_month(int y, int m)
{
    int days[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
    int day = days[m];
    if (is_leap_year(y) && m == 2)
        day += 1;
    return day;
}
#include<stdio.h>
int main()
{
    int y = 0;
    int m = 0;
    scanf_s("%d %d", &y, &m);
    int d = get_days_of_month(y, m);
    printf("%d\n", d);
    return 0;
}

 二、链式访问

将一个函数的返回值作为另一个函数的参数,像链条一样将函数串起来。

 printf的返回是什么

printf函数返回的是打印在屏幕上的字符的个数 

 

解析:

第三个printf打印43,在屏幕上打印2个字符43,再返回2

第二个printf打印2,在屏幕上打印一个字符2,再返回1

第一个printf打印1

所以屏幕上最终打印:4321

函数的声明和定义

 先声明后使用

一、单个文件

这种情况下是函数的定义在函数调用后面

这是因为C语言编译器对源代码进行编译的时候,从第一行往下扫描的,当遇到函数调用的时候,并没有发现前面有函数定义,就报出了警告。

方法一:

如果我们将函数的定义放在函数调用的前面

函数的定义也是一种特殊的声明

 方法二:

在函数调用之前先声明一下函数

声明函数:函数的返回类型,函数名和函数的参数(只保留类型,省略掉名字也是可以的)

 二、多个文件

函数的声明放在头文件(.h)中,函数的定义和主函数放在源文件(.c)中。

全局变量:

大括号外部定义的变量

局部变量:

大括号内部定义的变量

内存

一、栈区

局部变量

函数参数

二、静态区

全局变量

静态变量

三、堆区

C语言中关键字static和extern

static是静态的意思,可以用来:

1、修饰局部变量

这是之前的我

代码1

                                                      这是之后的我 

                                                            代码2

a的作用域没有发生变化,生命周期变长了

 对比上面两个代码的效果,理解static修饰局部变量的意义。

代码1的test函数中的局部变量i是每次进入test函数先创建变量(生命周期开始)并赋值为0,然后++,再打印,出函数的时候变量生命周期将要结束(释放内存)。

代码2 中,我们出输出结果看,i的值有累加的效果,其实test函数中的i创建好后,出函数的时候是不会销毁的,重新进入函数也就不会重新创建变量,直接上次累积的数值继续计算。

结论:

static修饰局部变量改变了变量的生命周期,生命周期改变的本质是改变了变量的存储类型,本来一个局部变量是存储在内存的栈区的,但是被static修饰后存储到了静态区。存储在静态区的变量和全局变量是一样,生命周期就和程序的生命周期一样了,只有程序结束,变量才销毁,内存才回收。但是作用域不变的。

使用建议:

未来一个变量出了函数后,等下次进入函数继续使用,就可以使用static修饰。

2、修饰全局变量

extern是用来声明外部符号的。

全局变量是具有外部连接属性的

 extern是用来声明外部符号的,如果一个全局的符号在A文件中定义的,在B文件中想使用,就可以使用ertern声明,然后使用。

结论:

一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。本质原因是全局变量默认是具有外部链接属性的,在外部的文件中想使用,只要适当的声明就可以使用;但是全局变量被static修饰之后,static int g_val = 2024;或者static int add(int x,int y);外部链接属性就变成了内部链接属性,只能在自己所在的源文件内部使用了,其他源文件,即使声明了,也是无法正常使用的。

使用建议:

如果一个全局变量,只想在所在的源文件内部使用,不想被其他文件发现,就可以使用static修饰。

 3、修饰函数

                               函数默认也是具有外部链接属性 

使用建议:

如果一个函数,只想在所在的源文件内部使用,不想被其他文件发现,就可以使用static修饰。

作用域

作用域是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效(可用)的,而限定这个名字的可用性的代码范围就是这个名字的作用域。

局部变量的作用域是变量所在的局部范围。

全局变量的作用域是整个工程。

生命周期

生命周期指的是变量的创建(申请内存)到变量的销毁(收回内存)之间的一个时间段。

局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。

全局变量的生命周期是:整个程序的生命周期。

   

                               指针( 补充:计算机中常见的单位)

生活中,每个房间有了房间号,就能提高效率,能快速的找到房间。

如果把上面的例子对照到计算中,又是怎么样泥?
我们知道计算上CPU(中央处理器》在处理数据的时候,需要的数据是在内存中读取的,处埋后的数据也会放回内存中,那我们买电脑的时候,电脑上内存是8GB/16GB/32GB等,那这些内存空间如何高效的管理呢?
其实也是把内存划分为一个个的内存单元,

每个内存单元的大小取1个字节。
一个比特位可以存储一个2进制的位1或者0。


其中,每个内存单元,相当于一个学生宿舍,一
个人字节空间里面能放8个比特位,就好比同学们
住的八人间,每个人是一个比特位。
每个内存单元也都有一个编号,(这个编号就相当
于宿舍房间的门牌号),有了这个内存单元的编
号,CPU就可以快速找到一个内存空间。
生活中我们把门牌号也叫地址,在计算机中我们
把内存单元的编号也称为地址。C语言中给地址起
了新的名字叫:指针。
所以我们可以解为:

内存单元的编号==地址==指针

 

 指针变量就是用来存放地址的。

存放在指针变量中的值,都会被当作地址使用。

指针变量的大小

#include<stdio.h>
int main()
{
    int num = 10;
    int* p = &num;
    char ch = 'w';
    char* pc = &ch;
    printf("%d\n", sizeof(p));
    printf("%d\n", sizeof(pc));
    return 0;
}

4

4

习题

一、多个字符从两端移动,向中间汇聚。

#include<stdio.h>
#include<windows.h>
int main()
{
    char arr1[] = "welcome to bit!!!!!!!!!";
    char arr2[] = "***********************";
    int left = 0;
    int right = strlen(arr1)-1;
    printf("%s\n", arr2);
    while(left<=right)
    {
        arr2[left] = arr1[left];
        arr2[right] = arr1[right];
        printf("%s\n", arr2);
        Sleep(1000);//休眠,单位毫秒
        system("cls");//用来执行系统命令的
        left++;
        right--;
    }
    printf("%s\n", arr2);
    return 0;
}

二、逆序输出

#include <stdio.h>


int main()
{
    int arr[10] = {0};
    for(int i=0; i<10; i++)
    {
        scanf_s("%d", &arr[i]);
    }
    for(i=9; i>=0; i--)
    {
        printf("%d ", arr[i]);
    }
    
    return 0;
}

三、有序数列合并

描述

输入两个升序排列的序列,将两个序列合并为一个有序序列并输出。

数据范围: 1 \le n, m \le 1000 \1≤n,m≤1000  , 序列中的值满足 0 \le val \le 30000 \0≤val≤30000 

输入描述:

输入包含三行,

第一行包含两个正整数n, m,用空格分隔。n表示第二行第一个升序序列中数字的个数,m表示第三行第二个升序序列中数字的个数。

第二行包含n个整数,用空格分隔。

第三行包含m个整数,用空格分隔。

输出描述:

输出为一行,输出长度为n+m的升序序列,即长度为n的升序序列和长度为m的升序序列中的元素重新进行升序序列排列合并。

#include <stdio.h>


int main()
{
    int n = 0;
    int m = 0;

    int arr1[1000] = {0};
    int arr2[1000] = {0};
   
    scanf("%d %d", &n, &m);

  
    for(int i=0; i<n; i++)
    {
        scanf("%d", &arr1[i]);
    }
    for(int i=0; i<m; i++)
    {
        scanf("%d", &arr2[i]);
    }
  
    int j = 0;
   int i = 0;

    while(i<n && j<m)
    {
        if(arr1[i] < arr2[j])
        {
            printf("%d ", arr1[i]);
            i++;
        }
        else
        {
            printf("%d ", arr2[j]);    
            j++;
        }
    }
    if(i == n)
    {
        for(; j<m; j++)
        {
            printf("%d ", arr2[j]);
        }
    }
    else
    {
        for(; i<n; i++)
        {
            printf("%d ", arr1[i]);
        }
    }
    return 0;
}

四、空心正方形

打印用“*”组成的“空心”正方形图案。

输入描述:

多组输入,一个整数(3~20),表示输出的行数,也表示组成正方形边的“*”的数量。

输出描述:

针对每行输入,输出用“*”组成的“空心”正方形,每个“*”后面有一个空格。

#include <stdio.h>


int main()
{
    int n = 0;
    while(scanf_s("%d", &n) != EOF)
    {
   
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<n; j++)
            {
                if((i==0) ||( i==n-1)||(j==0)||(j==n-1))
                    printf("* ");
                else
                    printf("  ");
            }
            printf("\n");//输一层就换行
        }
    }
    return 0;
}

五、X形图案

打印用“*”组成的X形图案。

输入描述:

多组输入,一个整数(2~20),表示输出的行数,也表示组成“X”的反斜线和正斜线的长度。

输出描述:

针对每行输入,输出用“*”组成的X形图案。

#include<stdio.h>

int main()

{

int n = 0;

while (scanf_s("%d", &n) != EOF)

{

int i = 0;

int j = 0;

for (i = 0; i < n; i++)

{

for (j = 0; j < n; j++)

{

if ((i == j) || (i + j == n-1))

printf("*");

else printf(" ");

}

printf("\n");

}

return 0;

}

六、判断三角形

已经给出的三条边a,b,c能否构成三角形,如果能构成三角形,判断三角形的类型(等边三角形、等腰三角形或普通三角形)。

输入描述:

题目有多组输入数据,每一行输入三个a,b,c(0<a,b,c<1000),作为三角形的三个边,用空格分隔。

输出描述:

针对每组输入数据,输出占一行,如果能构成三角形,等边三角形则输出“Equilateral triangle!”,等腰三角形则输出“Isosceles triangle!”,其余的三角形则输出“Ordinary triangle!”,反之输出“Not a triangle!”。

#include <stdio.h>

int main()

{

  int a = 0;

  int b = 0;

  int c = 0;

  while (scanf_s("%d %d %d", &a, &b, &c) != EOF)

  {

    if ((a + b) > c && (a + c) > b && (b + c) > a)

    {

      if (a == b && b == c)

        printf("Equilateral triangle!\n");

      else if (a == b || a == c || b == c)

        printf("lsosceles triangle!\n");

      else printf("Ordinary triangle!\n");

    }

    else printf("Not a triangle!\n");

  }

  return 0;

}

 七、乘法口诀表

#include<stdio.h>

int main()

{

    int i = 0;

    int j = 0;

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

    {

        for (j = 1; j <= i; j++)

        {

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

            if (i == j)printf("\n");

        }

    }

    return 0;

}

 八、求输入的10个整数中的最大值

#include<stdio.h>

int main()

{

    int a[10] = {0 };

    int max = 0;

    int i = 0;
    for (i = 0; i < 10; i++)
    {
        scanf_s("%d", &a[i]);
    }

    for (i = 0; i < 10; i++)

    {

        if (a[i] > max)

            max = a[i];

    }

    printf("%d", max);

    return 0;

}

 九、分数求和

计算1/1-1/2+1/3-1/4+1/5 …… + 1/99 - 1/100 的值,打印出结果

#include<stdio.h>

int main()

{

int i = 0;

double sum = 0;

int f = 1;

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

{

sum = sum + 1.0 / i * f;

f = -f;

}

printf("%f", sum);

return 0;

}

十、数9的个数 

编写程序数一下 1到 100 的所有整数中出现多少个数字9

#include <stdio.h>


int main()
{
    int i = 0;
    int count = 0;


    for (i = 1; i <= 100; i++)
    {
        if (i % 10 == 9)//通过% 的方式取当前数据的个位,检测个位数据是否为9,如果是,给计数器加1
            count++;
        if (i / 10 == 9)//通过/的方式取当前数据的十位,检测十位数据是否是9, 如果是,给计数器加1
            count++;
    }
    printf("%d\n", count);
    return 0;
}

个位上:9,19,29,39,49,59,69,79,89,99

十位上:90,91,92,93,94,95,96,97,98,99

 十一、素数

1、判断一个数是不是素数

素数:即质数,除了1和自己之外,再没有其他的约数,则该数据为素数,具体方式如下

#include<stdio.h>

int main()
{
int count = 0;
for(int i=101; i<=200; i+=2)
{
  for(int j=2; j<=sqrt(i); j++)
  {
   if(i%j == 0)
   {
    break;
   }
  }
  if(j>sqrt(i))
  {
   count++;
   printf("%d ", i);
  }
}

 printf("\ncount = %d\n", count);
return 0;
}


2、实现一个函数is_prime,判断一个数是不是素数。利用上面实现的is_prime函数,打印100到200之间的素数。

int is_prime(int n)
{
	for(int i=2; i<=sqrt(n); i++)
	{
		if(0 == n%i)
		{
			return 0;
		}
	}
	return 1;
}

十二、求最大公约数

#include <stdio.h>

int main() 
{
    int a = 0;

int b = 0;
    int c = 0;

  printf("请输入两个数字:");
    scanf_s("%d%d", &a, &b);
    c = a % b;
    while (c != 0) 
    {
        a = b;
        b = c;
        c = a % b;
    }
    printf("最大公约数为%d\n", b);
    return 0;
}

十三、判断闰年

#include<stdio.h>

int main()

{

int year = 0;

scanf_s("%d", &year);

runnian(year);

return 0;

}

int runnian(int y)

{

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

printf("%d是闰年\n",y);

else printf("%d是平年",y);

return 0;

十四、计算斐波那契数1 1 2 3 5 8 13 21

#include<stdio.h>

int main()

{

    int n = 0;

    int m = 0;

    scanf_s("%d", &n);

    m=f(n);

    printf("%d", m);

    return 0;

}

int f(int n)

{

    if (n <= 2)return 1;

    else return f(n - 1) + f(n - 2);

}

 十五、递归实现n的k次方

#include<stdio.h>

int main()

{

    int n = 0;

    int k = 0;

    int c=0;

    scanf_s("%d %d", &n,&k);

    c=Pow(n, k);
    printf("%d\n", c);

    return 0;

}

int Pow(int n, int k)

{
    if (k == 0)return 1;
    else if (k >= 1)
        return n * Pow(n,k-1);
    }

 十六、计算一个数的每位之和(递归实现)

#include<stdio.h>

int main()

{
    int n = 0;
    int m = 0;

    scanf_s("%d", &n);

    m=DigitSun(n);
    printf("%d\n", m);

    return 0;

}

int DigitSum(int n)

{

    if (n >9)return DigitSum(n / 10) + n % 10;

    else return n;

}

十七、求阶乘

#include<stdio.h>

int main()

{

    int n = 0;

    int m = 1;
    scanf_s("%d", &n);
    for (int i = 1; i <= n; i++)

    {

        m = i * m;

    }

    printf("%d", m);

    return 0;

}


 


#include<stdio.h>

int main()

{

    int n = 0;

    int m = 0;

    scanf_s("%d", &n);

    m=test(n);

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

    return 0;

}

int test(int n)

{

    if (n <= 1)
        return n;

    else 
        return n * test(n - 1);

}

 

十八、递归方式实现打印一个整数的每一位 

#include<stdio.h>

int main()

{

    int n = 0;
    scanf_s("%d", &n);

    t(n);
    return 0;

}


void t(int n)

{


    if (n > 9)
    {

        t(n / 10);


        printf("%d ", n % 10);


    }
    else printf("%d\n", n);
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值