c_code基础

文章目录


typora-copy-images-to: image

c自学整理

2 C语言中的数据类型

2.1 常量

常量就是在程序中不可变化的量

2.1.1 # define
2.1.2 const
2.1.3 字符串常量

“hello world”

2.2 进制

我们习惯于十进制数,通常使用十进制数:如10,20,12等

%d 默认打印是带符号的

%u,表示无符号

int a = 11;
printf("%d\n",a);
2.2.1 二进制

一位只能表示 0、1两种状态简称 BIT

一个字节为8个二进制,成为8位,简称BYTE

一个字为两个字节,简称WORD

两个字为双字,简称DWORD

2.2.2 八进制

八进制为以8为基数的数制系统,常以0表示八进制:0673;

o: 打印八进制

int a = 11;
printf("%o\n",a);
2.2.3 十六进制

十六进制以16位基数的数制系统,常用0x表示十六进制:0xAADF;

x:为打印小写字符

X: 打印大写字符

int a = 11;
printf("%x\n",a);
2.3、计算机为什么用补码存储

熟悉:存储1个字节(8位),大小的数字(char)

2.3.1 原码(二进制)

1、用户的数字分为正负数,符号位的存储

2、最高位为符号位,0表示正数,1代表负数

3、1000 0001 左边是高位,右边为低位

//1
    +1 : 0000 0001
    -1 : 1000 0001
//0
    +0 : 0000 0000 
    -0 : 1000 0000    

源码存储导致两个为题:

1、0 有两种存储方式

2、正数和负数相加,结果不正确(计算机只会加,不会减)// 减法 会被执行成 正数 + 负数

// 原码计算 
//1-1 = 1 + -1
   1: 0000 0001
  -1: 1000 0001
      1000 0010 = -2
 
2.3.2 反码(为了算补码):

1、正数原码和反码是一样

2、求原码

3、在原码基础上,符号位不变,其他为去反(0变1 、1变0)

// 1
  +1 : 0000 0001
  -1 : 1111 1110
  +0 : 0000 0000    
  -0 : 1111 1111 

反码存储导致1个问题:

1、0 有两种存储方式

//反码计算的方式
// 1 - 1 = 1 + -1
  1: 0000 0001
 -1: 1111 1110
     1111 1111 = -0
2.3.3 补码

通过补码的方式来解决上面的问题:

计算机存储数字以补码的方式存储,(为了解决负数的问题)

1、正数的原码、反码、补码都是一样的;

2、补码为反码+1

//补码:
// 1
   +1 : 0000 0001
   -1 : 1111 1111
   +0 : 0000 0000    
   -0 : 10000 0000 (最高位丢弃)

以补码来计算

// 1
   +1 : 0000 0001
   -1 : 1111 1111
       10000 0000 = 0
2.3.4 原码与补码互转

1、提供原码\补码

2、通过原码\补码计算反码

3、通过反码+1 获得补码\原码

// 补码
补码: 1000 0001
反码: 1111 1110
原码: 1111 1111   = -127 
十六进制:0x81
2.3.5 总结

计算机系统中,数值一律用补码来存储主要原因:

1、统一了零的编码

2、符号位和其他为统一处理

3、将减法运算变为加法运算

4、用两个补码表示数相加,如果最高位(符号位有进位),则仅为被舍弃

2.3.6 有符号和无符号

1、有符号,最高位是符号位,如果1代表负数,如果为0 代表正数

2、无符号,最高位不是符号位,是数的一部分,无符号不可能是负数

 %d 默认打印是带符号的
 %u,表示无符号
 
 // 等价于 int a =-10
 // singed 表示有符号
 // unsigned 表是无符号
 signed int =-10 ;
 

数据类型范围:

char 1个字节“

有符号:

正数:0000 0000 -0111 1111 0-127

负数:-0 当做 -128 使用, 要不然就会有两个 0

无符号:0-255

赋值或者运算,记得不要越界:

 char a = 127 +2;
// 转换原码
// 129转换成二进制为 1000 0001 这个是负数的补码

 printf("%d\n",a); 
 // 获得结果为 -127

unsigned char b=255+2printf("%u\n",a); 
 // 获得结果为 1
2.4 sizeof关键字

1、sizeof 不是函数,所以不需要包含头文件,他的功能是计算一个数据类型的大小,单位为字节;

2、sizeof的返回值为size_t

3、size_t类型在32位操作系统下是unsigned int 是一个无符号的正数

2.5 int 类型
2.5.1 整型变量的定义和输出
打印格式含义
%d以十进制的方式输出
%o以八进制的方式输出
%x以十六进制方式输出,字母小写
%X以十六进制方式输出,字母大写
%u输出十进制无符号数
#include <stdio.h>

int main(){
    
    int a= 123;// 十进制
    int b =0567;//
    int c=0xabc;//
    
     printf("a= %d\n",a);
     printf("a= %o\n",a);
     printf("a= %x\n",a);
     printf("b= %d\n"b);
     printf("c= %x\n",c);
     printf("c= %X\n",c);
     scanf("%d",&a);//输入
    
    return 0;         
    
}

2.5.2 整型的取值范围
数据类型占用空间(字节)取值范围
short2-215-215-1
int4-231-231-1
long4-231-231-1
unsigned short20-215-1
unsigned int40-231-1
unsigned long40-231-1
2.6 字符类型

字符型变量用于存储一个单一字符,在c语言中用char表示,其中没个字符变量都会占用1个字节。在给字符变量赋值时,需要用一个对英文半角的单引号,用来包裹字符。

char 本质 就是一个1字节大小的整型。

由来:

   1、内存中没有字符,只有数字

2、一个数字对应一个字符,这个规则就是ASCII

3、使用字符或数字给字符变量赋值是等级

4、字符类型本质就是一个1个字节大小的整型
#include <stdio.h>
int main(){
    
    char ch = 'a';
   	printf("ch =  %c ,ch =%d\n",ch,ch);

	ch=97//以ASCII 赋值,和ch='a' 等价
	printf("ch2 =%c\n" ,ch);   
    return 0;
}

[root@liu-node1 c_code]# gcc char.c 
[root@liu-node1 c_code]# ./a.out 
ch =  a ,ch =97
ch2 =a
// 验证上面的说法是正确的

 小写a 为 97  大写A 65

转义字符,有反斜杠组成的的特殊字符

\n 表示换行

\r 表示句首,并继续打印,前面的字符会被替换

\b 退格键,会删除前面一个字符,然后继续打印

2.7 实型(浮点型)float double

实型变量也称为浮点型变量,浮点型变量是用来存储小数数值。在C语言中,浮点类型分为两种,单精度、双精度

,但是double行变量所表示的浮点数比float型变量更精准。

数据类型占用空间有效数字范围
float4字节7位有效数字
double8字节15-16位有效数字

在使用过程中,尽量使用double变量,数据比较精确

#include <stdio.h>

int main(){
    float a = 100.9f;
    printf("%f\n",a); //100.900002  默认小数点后有6位
    
    double b =1.34;
    printf("%lf\n",b); // 1.340000  结果比较正常
    
     return 0;
}
2.8 类型限定符
限定符含义
extern声明一个变量,extern声明的变量没有建立存储空间
const定义一个常量,常量的值不能修改
volatile防止编译器优化代码
register定义寄存器变量,提高效率。register是建议型的指令,而不是命令型的指令,如果CPU有空闲的寄存器,那么register就生效,如果没有空闲的寄存器,那么register则无效。
2.9 格式输入与输出
2.9.1 输出
#include <stdio.h>

int main(){
    
    int a=123;
    
    //%% 在屏幕输出,表示输出一个%
    printf("%%d\n");
    
    // 5%,以5个字符输出,没有的字符以空字符填充,默认是右对齐
   	 printf("a ='%5d'\n",a); // '  123'
     printf("a ='%05d'\n",a); // '00123'
     printf("a ='%-5d'\n",a); // '123  '表示左对齐
    // 零和减号不能同时使用,数据就失效了,没有意义
    
    double b= 3.13;
    printf("b ='%lf'\n",b); // 3.130000 自动补零
    
    // 8.3 表示总共有8个字符,3代表小数点后有3位
    printf("b ='%8.3lf'\n",b); // ‘     3.130’ 自动补零
    
    char ch ='a';
    putchar(ch);// 把ch 内容输出到屏幕
    putchar("\n");
    
    return 0;
}

2.9.2 输入
#include <stdio.h>

int main(){
    
    int a;
    printf("请输入a:");    
    scanf("%d",&a);
    printf("a = %d\n",a);
        
    int b;
    int c;    
    printf("请输入b,c:");    
    scanf("%d %d",&b,&c);
    printf("b = %d ,c=%d\n",b,c); 
        
    return 0;      
       
}





int main(){
    
    char a;
    printf("请输入a:");    
    scanf("%c",&a);
    printf("a = %c\n",a);
        
    char b;
    printf("请输入b:");    
    scanf("%c",&b);
    printf("b = %c\n",b);
//     二次输出是一个 回车键 ascii 10
        
    return 0;  
}

出错的原因: 当用户通过 scanf 输入字符时候,编译器默认把输入的内容放到一块内存中(缓冲区),scanf自动在缓冲区读完内容。

[外链图片转存失败(img-NKZo4mpV-1566437796996)(E:\markdowm\image\1536117682601.png)]

解决方案:

   在做字符读取的时候,可以使用getchar();的方式将 "\n"先吃掉,然后在读取。

3 运算符与表达式

3.1 常用的运算符分类
运算符类型作用
算术运算处理四则运算
赋值运算将表达式的值赋值给变量
比较运算表达式的比较,返回一个真或者假
逻辑运算符用于根据表达式的值返回真或者假
位运算符处理数据的位运算
sizeof运算符用于求字节数长度

3.2 运算符

3.2 运算符

其他的语法都是一样的,

3.2.1 除法

两个数相除,想到得到小数,分子分母必须有一个是小数,否则结果只会取整

 int a =5 ;
 int b =2 ;
 double c;
 c = a/b; //2.000000
 c=a*1.0/b ; // 2.500000
3.2.2 前置和后置

后置++,先用后加

前置++,先加后用

 int a=1;
 int b=0;
 b =a++; //b=1,a=2
 
 a=1;
 b=0;
 b=++a;// b=2 ,a=2


 a=1;
 b=0;
 a++;
 b=a;// b=2 ,a=2
3.3 赋值运算符
运算符术语实例结果
=赋值a=2;b=3;a=2;b=3;
+=加等于a=0;a+=2a=2;
-=减等于a=5;a-=2a=3;
*=乘等于a=2;a*=2a=4;
/=除等于a=5;a/=2a=2;
%=摸等于a=5;a%=2a=1;
3.4 比较运算符

和java一样,判断真假返回

3.5 逻辑运算

和java一样,判断真假返回

3.6 运算符优先级

和java 一样,短路规则

3.7 类型转换

强制类型转换原则,就是小的往大的转,大的往小的转,容易造成错误,或者精度丢失。

double a;
int b =10;
a=b ;// 这里存在隐式的转换,将b 的值转换成double 类型,然后赋值给a
a =(double)1/2; // 这种方式使用的强制类型转换
printf("%lf",a);
// 整型的变量不用%lf打印,除非进行强值类型啊的转换
int c=100printf("%lf",(double)c);

4 程序流程结构

4.1 概述

c语言支持最基本的三种程序运行结构,顺序结构、选择结构、循环结构

  • 顺序结构:程序按照顺序执行,不发生跳转
  • 选择结构:依据是否满足条件,有选择的执行相应功能
  • 循环结构:条件满足,循环多次执行某段代码
4.2 选择结构
4.2.1 if语句

[外链图片转存失败(img-Wo2G598j-1566437796997)(E:\markdowm\image\1536123968342.png)]

#include <stdio.h>

int main(){
    //if 是一个关键字,条件为真,执行if语句;假不执行
    // 非零就是真
    if-1{
        //这里的代码会被执行,非零即为真 一定要注意
    }
    
    if1{
        
    }
    //在if(4==a) 判断语句中,使用常量写在前面的方式可以,防止书写错误,编译不过去
    // 所以推荐使用这种写法
    int c =4;
    if(4 == c){
        
    }else if(4 < c){
        
    }else if(4 > c){
        
    }else{
        
    }
    // 在写的情况下注意效率,尽量使用 else if, 不单独使用if;
    
    
    
    
    return 0;
}



4.2.2 三目运算

同java 不需要深究

 int a=10int b=20int c = a >b ? a : b;  // 判断 a和b 大小,如果为真,则c =a ,否则 c=b;
4.2.3 switch 语句

同java 不需要深究

//1、switch 是关键字,没有分号
//2、switch 中值能传入 整型,或者字符型变量
//3、switch 用法类似于电梯模型

int num ;

switch(num){
    
    case 1:
    // TODO
    break ; //必须有,调出switch ,否则会击穿
    case 2:
     // TODO
     break;
     default:
     //TODO
     break;
     
}


4.3 循环语句
4.3.1 while 语句

int num =1;
int sum=0;

 while (num<100)
 {
  
	sum+=num;
	num++;

 }





4.3.2 do …while
// 无条件先执行一次 循环体
do{
    
}while();
4.3.3 for语句
for(;;){
    
}
4.3.4 嵌套循环
循环嵌套
for(){
  for(){
      
  }
}
4.4 跳转语句
4.4.1 break 语句

break 中断出这层循环;

4.4.2 continue 语句

continue 跳过 本次循环,继续循环;

4.4.3 goto 语句

goto 任意地方都可以使用,无条件跳转,建议不要用。

int main(){
    
    goto MIKE;
    
    //todo
    
    MIKE:
    //TODO
    
    //这样的话就会将代码 直接跳过,这样的跳转太霸道建议不要用。
    // 只能跳转到同一个作用域的 即{}
}

5 数组和字符串

5.1 概述

在程序设计中,为了方便处理具有相同类型若干变量按有序形式组织起来,称为数组

数组在内存中**连续的相同类型**的变量空间。同一个数组所有成员都是相同的数据类型,同时所有的成员在内存中的**地址是连续的**。
5.2 一维数组

5.2.1 以为数组定义和使用

5.2.1 以为数组定义和使用
//定义一个 数组,
// 定义数组的类型,定义数组的元素个数
// 数组在内存中是连续存储的
//  通过下标访问数组元素,下标从0开始
// 有多少个[] 就代表是几维数组
#define SIZE 10;


int array[10]; 
// 定义一个的数组名在相同的作用域内,不能和其他的定义相同,会冲突 error
// 在[] 中最好是常量,要不然可能使得其他编译器 编译不过

//定义数组时候,[] 最好是常量,就是固定数组的个数

int a[SIZE];
// 使用数组的时候,下标可以是常量,可以是变量,也可以是表达式
 a[0] =1;
 int i ;
a[i]=2;
a[i+2]=3;
// 在使用数组的时候,不能越界使用,不然报错,或者编译不过去;






5.2.2 一维数组的初始化

结论: {} 内部的变量或者数组不初始化,就是随机数



 int a[10];
 for(int i= 0;i<10;i++){
     
     printf("%d\n",a[i])
 	//	 不初始化、就是随机数
    //  {} 内部的变量或者数组不初始化,就是随机数
 }

5.2.3 数组名

结论:

1、数组名是常量,

2、为数组首元素的地址

3、sizeof(数组名)测数组总大小

4、元素个数,sizeof(数组名)/sizeof(a[0])

int a[10];
// 数组名为常量, 不能修改
// 数组名是数组首元素地址
printf(" a = %p\n ,&a[0]= %p\n", a , &a[0]);
// 

5.2.4 常用操作
// 求最大值

int a =10;
int b =20;
int c =30 ;

int max ;

//if 的方式就不实现了

//三目运算的方式实现 大小比较
max = ( a > b ? a : b ) > c ? ( a > b ? a : b ) : c;

//求 数组最大值
 int aa[] ={1,2,4,6,7,3,1,6,2,76,2,48,5,2}; //定义并初始化数组
 int n = sizeof(aa)/sizeof(aa[0]);// 求计算数组的长度
 int max=a[0];
    for(int i=1;i<n;i++){
        
        if(a[i] > max){
            max = a[i];
        }
    }
 printf("数组的最大值为:%d\n",max)



5.2.5 数组翻转
int main(){

  int aa[] ={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; //定义并初始化数组
  int n = sizeof(aa)/sizeof(aa[0]);// 求计算数组的长度
  int i = 0;
  int j = n-1;
  int tmp;
while( i < j ){
    tmp =aa[i];
    aa[i] = aa[j];
    aa[j] = tmp;
    j--;
    i++;
}
for(i = 0;i < n;i++){
    printf("%d ,", aa[i]);
}
  printf("\n");
 return 0;
  
}


shell 测试:

//通过linux 测试

[root@liu-node1 c_code]# vim arraysort.c 
[root@liu-node1 c_code]# gcc arraysort.c 
[root@liu-node1 c_code]# ./a.out 
15 ,14 ,13 ,12 ,11 ,10 ,9 ,8 ,7 ,6 ,5 ,4 ,3 ,2 ,1 ,
5.2.6 冒泡排序

#include <stdio.h>
int main(){
  int a[] ={1,2,4,6,7,3,1,6,2,76,2,48,5,2}; //定义并初始化数组
  int n = sizeof(a)/sizeof(a[0]);// 求计算数组的长度
  int i = 0;
  int tmp;
  int j=0;   
      
printf("排序前 \n ");
 for(i = 0;i < n-1;i++)
  {
    printf(" %d ,", a[i]);
  }
   printf("\n"); 
      
  for(i=0;i<n-1;i++){
     for(j=0;j<n-1-i;j++){
         if(a[j]>a[j+1]){
         	tmp =a[j+1];
         	a[j+1]=a[j];
         	a[j]=tmp;
         }
     }
 }
    
   printf("排序后\n");
   for(i = 0;i < n-1;i++){
	  printf(" %d ,", a[i]);
     }
 	printf("\n"); 
  return 0;   
}

linux 测试

[root@liu-node1 c_code]# vim arrsort.c 
[root@liu-node1 c_code]# gcc arrsort.c 
[root@liu-node1 c_code]# ./a.out 
排序前 
  1 , 2 , 4 , 6 , 7 , 3 , 1 , 6 , 2 , 76 , 2 , 48 , 5 ,
排序后
 1 , 1 , 2 , 2 , 2 , 2 , 3 , 4 , 5 , 6 , 6 , 7 , 48 ,
5.3 二维数组

1、内存中没有多维数组,都是一维数组,多维数组是一个特殊的以为数组

2、有多少个[] 就是多少维数组

3、二维数组a[m][n],可以理解为m行和n列

5.3.1 二维数组初始化
第一种方式:
      int a[3][4]={
          
          {},
          {},
          {}
      };
第二种方式:
      int a1[3][4]={0,1,2,3,4,5,6,7,8,9}

// 如果定义时,同时初始化,第1个[] 可以不写内容。
// 如果第一个[] 不写,必须初始化
int a1[3][4] ={1,2,3,4} //没有初始化的元素赋值为0

// 所有元素初始化为0
int a2[3][4] ={0};


5.3.2 二维数组名

int a[5][10]
// 数组名是常量,不能修改
// sizeof(数组名),测数组的总大小,  

printf("sizeof(a) %d",sizeof(a));// 4*5*10 // 测的二维数组 总大小 200

printf("sizeof(a[0]) %d",sizeof(a[0]));// 4*10 // 测的二维数组第0个元素的大小 40

printf("sizeof(a[][]) %d",sizeof(a[0][0]));// 4 // 测的二维数组 第0行 第0列 大小 4

 //求行数
 int n =sizeof(a)/sizeof(a[0]) ;// 200/40 =5
 
 //求列数
 n =sizeof(a[0])/int // 40/4 = 10 
 
 //行*列        10*5
 
 


5.4 字符数组与字符串

1、C语言没有字符串型,用字符数组模拟的。

2,字符串一定是字符数组,字符数组就不一定是字符串。

3、字符数组以字符结尾’\0’,那么这个字符数组就是字符串。


char a[10];
char b[];

//1、常用的初始化,使用字符串初始化,在字符串结尾自动加结束符数字0
//2、这个结束符,用户看不到,但是存在的。通过sizeof 来获取长度可以看到、。

char a7[10]="abc";
sizeof(a7) =4;// 这里默认隐藏了 一个结束符号
 
 //转义字符后\0 后面最好不要加入数字,可能会生成一个新的转义字符
 
 
 char a[] ={1,2,3}; //3个字符
 char B[] ="123";// 4个字符
 char a[10] = "123456789"; // 最多只能写9个 要不然,结束符不能插入
 
 


5.4.1 输入
char a[100];
scanf("%s",a);//a 没有& ,原因是数组的名称就是地址
5.4.2 输出

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

5.5.3 函数调用:随机数

当调用函数的时候,需要关心5个要素

  • 头文件: 包含指定头文件
  • 函数名:函数名字必须和头文件声明的名字一样
  • 功能:需要知道函数能干什么
  • 参数:参数类型要匹配
  • 返回值:根据需要接受返回值

#include <stdio.h>

#include <time.h>
#include <stdlib.h>

int main(){
// 设置种子
// 如果种子是一样 ,他随机数参数的值也是一样的
 srand((unsigned)time(NULL));
 int i = 0;
 int num ;

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

        num = rand();// 产生随机数
        printf("%d\n",num);

  }
    
}

5.5.4 字符串处理函数

5.5.4.1

5.5.4.1 输入


 char buff[100]={0};

 printf("输入你想要的字符:");
 scanf("%s",buff);// 不需要取地址&,默认以空格进行分割
 printf("%s" ,buff);

// 和getchar 差不多,都是缓冲区作怪

//scanf() 的缺陷,不做越界检查,可能你输入的数据超出边界范围
//gets 已经废弃,也不是安全的,不做安全检查
// 目前主要是用fgets 这个方法
// fgets(char* ,int size,File* stream )


char buf[10];
fgets(buf,sizeof(buf),stdin);

#include <stdio.h>

int main(){

 char buf[10];
 fgets(buf,sizeof(buf),stdin);
    //注意换行符也被读取了
  printf("%s\n",buf);

 return 0;

}




[外链图片转存失败(img-zVzulsxS-1566437796997)(E:\markdowm\image\1536220678204.png)]

5.5.4.2 输出


puts(char*char buf[]="aaabc";
puts(buf);//把buf内容输出到屏幕,会自动换行

stdout //屏幕,代表标准输出
fputs(buf,stdout);

5.5.4.3 字符串长度
#include <string.h> 
char buf[]="aaabc";
// strlen 需要使用返回值,返回值就是字符串的长度
//从首元素开始到结束符的长度,结束符不算
 int len =strlen(buf);
char buf2[]="\0hello";
sizeof(buf2); // 结果为7 
strlen (buf2);//0

5.5.4.3 字符串拷贝
#include <string.h>

char src[]="hello mike"char dst[100]//功能上src 字符串数组内容 拷贝给dst所代表的数组;
strcpy(dst,src)//拷贝的时候,遇到\0 结束拷贝


strncpy(dst,src,strlen(src)+1);//使用的时候注意要拷贝字符串长度+1
//可以把\0拷贝过去,但是\0 后面的数据 是不能拷贝的



5.5.4.4数组越界

char src[100] ="121321321313131";
char dst[10];
strcpy(dst,src);
// 出现段错误,就是内存错误,数组越界

5.5.4.5 字符串比较

比较字符串的每一个字符的ASCII

// int strcmp(char1*,char2*)
// 0 相等
// 大于 >0
// 小于 <0    
//int strncmp(s1,s2,num) 比较的是一定范围的数值


5.5.4.6 字符串追加

字符串内容追加


srtcat(char1,char2);//把char2 追加到char1  
srtncat(char1,char2,len);//把char2的n个长度 追加到char1

5.5.4.7 格式化字符串

网络上可以叫做组包,拆包

sprintf(dest,printf); //将打印的内容,输出到目标char数组
fprintf(dest,printf); //将打印的内容,输出到目标文件  

sscanf(dest,scanf);//从dest数组中,读取内容 代替屏幕输入

   char buf[]="1 2 3";
   int a,b,c;
// 注意提取指定格式的内容,char数组的内容和读取内容要一致,如下图所示:
  sscanf(buf,"%d %d %d",&a,&b,&c); //读取 buf 值,赋值给 a b c 默认以空格进行分割
    
 //在做字符串输入的时候,默认以空格进行分割,不能使用逗号进行获取。  

[外链图片转存失败(img-0Pcl0BOR-1566437796998)(E:\markdowm\image\1536282704601.png)]

5.5.4.8 字符串查询

char buf[] ="dfadsfdsf";
char *p =strchr(buf,'d');
// 在buf中查询 d ,如果找到就返回d 所在的地址,如果找不到则返回NULL



if(p==NULL){
 printf("查询失败!\n")
 }else{
 printf("p= %s\n",p);
 
 }
//  查询字符串所在的位置的地址,如果查询不到返回NULL
strstr(buf,"ads");



5.5.4.9 字符串切割
 
char buf[] ="abc,mike.,jiang,250";
char tmp[100];
strcpy(tmp,buf);

//第一次调用,第一个参数为目标字符串,第二个为切割方式,返回值为字符串数组
// 在匹配字符切割的地方会替换成结束符
// 使用strtok 会破坏原来字符串的结构
// 如果要使用该函数,最好复制一份数组,当做备份
char *p=strtok(buf,",");
printf("%s",p)
 char *p1 ;
 p1 =strtok(tmp,",");
while(p1!=NULL){
     printf("%s",p1);
     p1 =strtok(NULL,",");
   
}


5.5.4.10 字符串切割

在转换的过程中,需要是数字,或者符号,要不然转换失败,跳过空格遇到\0 结束

atoi 字符串转换成int

atof 字符串转换成float

atol 字符串转换成long

这里还可以用sprintf、sscanf 来格式化字符串,来转换成相应的格式。用%c %d %s 等来操作

6 函数

6.1 函数的概述

c 程序是有函数组成的,我们写的代码都是由主函数main 开始执行的,函数是C 程序的基本模块,

是用于玩成特定任务的程序代码单元。

从函数的定义来看,函数可以分为系统函数和用户自定义函数两种;

  • 系统函数,即库函数:由编译系统提供的,用户不必自己定义这些函数,可以直接使用它们;
  • 用户定义函数:用来解决用户专门需要,由用户自己编写的函数;
6.1.2 函数的作用
  • 函数的作用,减少代码重复,提高代码复用率;

  • 函数可以让程序更加的模块化,从而有利于程序的阅读、修改和完善。

6.1.3 函数定义分类

1、函数内部、包含()内部的变量(局部变量),只有在调用时分配空间,调用完毕自动释放;

2、同一个文件不能出现相同的函数名;

3、不同的函数,内部是变量是没有关系;(原因参看第一条)

4、定义函数的参数叫做形参,形参的格式必须为: 类型+ 变量,不能赋值

5、函数没有调用,形参变量不会分配空间,函数调用完毕,行参变量自动释放

6、有返回值的函数,可以不适用返回值。

7、函数的类型和返回类型不一致,以返回类型为准

  • 无参无返回

    void functionName(){

    }

  • 有参无返回值

  • 无参有返回值

  • 有参有返回值

6.2 exit 和return 的区别

return 中断函数,程序结束

exit 退出结束整个函数,或者结束进程

6.3 函数的声明和定义
  • 函数的声明,告诉编译器,整个函数是有定义的,只是在别的地方;

  • 调用函数前就需要声明,就不会有警告;

  • 函数 只能定义一次,可以声明多次;

  • 函数声明的的方式可以在main 函数前,也可以在函数内部;

  • 声明的函数的形参名称可以和定义的形参不同

  • 声明函数,形参类型一定要写,形参名称可以不写,但是定义的时候,形参名称一定要写


// 声明
int my_strlen(char str[]);

int main(){
    
    
    return 0;
}
// 此处为定义
int my_strlen(char str[]){

    int i = 0 ;
    while(str[i] !='\0'){
        
        i++;
    }
    return i;
}

6.4 分文件

1、创建工具类函数

2、创建头文件,声明函数

3、创建主函数,包含用户自定义头文件,用户的头文件 用冒号“” 来包裹

4、多文件中,不能出现同名函数定义,static 除外

5、不要再头文件中做定义,分文件系统被多次引入后,会出现同名文件,就类似于java 的导包

6、包含多次只有一次生效 #pragma once

#pragma once // 去重

#ifndef _MYSTRLEN_H
#define
extern int my_strlen(char buf[]);

#endif


7 指针

7.1 概述

[外链图片转存失败(img-FcFzBBXM-1566437796998)(E:\markdowm\image\1536295120152.png)]

7.1.1 内存地址

1、将内存抽象成一个很大的以为字符数组

2、编码就是对内存的每个字节分配一个32或者64位的编码

3、这个内存编号我们称为 内存地址

内存中没一个数据都会分配相应的地址

  • char 站一个字节分配一个地址
  • int 占4个字节,分配四个地址
  • float、struct函数,数组等
7.1.2 存储
  • 存储器:计算机的组成中,用来存储程序和数据的,辅助CPU进行运算处理的重要部分;

  • 内存:内部存储器,暂存程序/ 数据 --掉电丢失 SRAM DRAM DDR DDR2 DDR3

  • 外存:外部存储器,长时间保存程序/数据,掉电不丢失,ROM ERRROM FLASH NAND NOR 硬盘 光盘

    内存是沟通CPU 和硬盘的桥梁

  • 存放CPU中的运算数据

  • 暂存与硬盘灯外部存储器交换的数据

7.1.3 指针和指针变量
  • 内存的每一个字节都有一个编号,这个编号就是地址;
  • 如果在程序中定义了一个变量,在对程序进行编译或者运行时,系统就会这个变量分配内存单元,并确定它的内存地址
  • 指针的实质就是内存地址,指针就是地址,地址就是指针
  • 指针是内存单元的编号,指针变量是存放地址的变量
  • 通常我们叙说的指针变量简称为指针;
7.1.4 指针的定义和使用

[外链图片转存失败(img-OHffgvuf-1566437796998)(E:\markdowm\image\1536296876436.png)]


 // 指针也是一种数据类型 
 // p是一个变量,p的类型为 int *

int * p;




7.1.4 指针变量和指针锁指向的 内存

int a =100;
//定义变量时候,* 代表类型,它是指针类型int *
int * p;

p =&a;
// 在使用变量时候,* 代表操作指针所指向的内存

*p =10;

printf("%d",a); //10


int b =11;
p=&b;
*p = 200;

printf("%d %d",a, b); //10,200



int a =10;
int *p =&a;

*p =111; //a=111

int *q;
q=p ;

*q =222;
printf("&a =%p ,p=%p ,q=%p",&a,p,q); // &a &a &a
printf("&a =%d ,p=%d ,q=%d",a,*p,*q);// 222 222 222


7.1.5 野指针

1、只有定义后的变量,此变量的地址才是合法的地址;

2、野指针就是保存没有意义的地址的指针变量;

3、操作也指针变量本身不会有任何问题;

4、操作野指针所指向的内存才导致错误。

7.1.6 空指针

//1、空指针 就是给指针变量赋值为NULL
 int *p =NULL;
 int a =111;
 p = &a;

if(p!=NULL){
    *P = 20;
}
// 这样就可以操作a 变量的内存,a 变量的值变成了20


7.1.7 指针大小

// 32位编译器32位大小(4字节)保存地址

// 64位编译器64位大小(8字节)保存地址

int a =sizeof(int *);
int b =sizeof(char *);
int c sizeof(double *);
printf("a =%d,b=%d,c=%d",a,b,c);

[root@liu-node1 c_code]# vim ch.c
[root@liu-node1 c_code]# gcc ch.c 
[root@liu-node1 c_code]# ./a.out 
a =8,b=8,c=8
[root@liu-node1 c_code]# 


7.1.8 多级指针

//若果定义一个合适类型的变量保存另一个变量的地址

// 如果需要保存变量地址的类型就在基础上一个*

int a =10;
int *p =&a;
int **q =&p;
int ***m =&q;

[外链图片转存失败(img-pE0uhPsf-1566437796999)(E:\markdowm\image\1536304642069.png)]

[外链图片转存失败(img-VrY7zNzx-1566437796999)(E:\markdowm\image\1536305074507.png)]

7.1.9 [] 不是数组 专用

[外链图片转存失败(img-MepSPsYb-1566437797000)(E:\markdowm\image\1536305637672.png)]

7.1.10 万能指针和指针步长

1、不可以定义void 类型的普通变量,不能确定类型

2、可以定义 void * 变量, void * 也叫做万能指针

3、void * 可以指向任何类型的变量,使用指针所指向的内存时,最好转换成他本身的指针类型



 void * p=NULL;
 int a = 10 ;
 p =&a;
 *((int *)p) =222;
printf("*p %d",*((int *)p)) // 222




[外链图片转存失败(img-L8NghDQA-1566437797000)(E:\markdowm\image\1536309179725.png)]

总结:指针的加法,不是传统的加法

步长有指针指向的类型类决定。

7.2 指针和函数

指针数组:他是数组,每一个元素都是指针。

数组指针:他是指针,指向数组的指针。

7.2.1 地址传递

无论什么类型,只要是变量传递,就是值传递;

如果通过函数改变实参,必须地址传递

[外链图片转存失败(img-JXyRyCTF-1566437797001)(E:\markdowm\image\1536539568255.png)]

7.2.2 形参中的数组

形参中的数组,不是数组,他是普通的指针变量

参数数组:int[10000],int[],int *a 对编译器而言,没有任何区别,编译器都当做int * 处理

形参中的数组和非形参数组的区别:形参中的数组是指针变量,非形参数组就是数组。

总结:在传递过去方法体重的,数组的长度要传递过去。要不然无法计算出数组的长度和个数,操作就无法完成。


void print_array(int *a){
    
    int i = 0;
   // 在64位系统中,a是指针变量,长度为8 
    // a[0] 是int 类型,是4 最重结果为2 
    int n = sizeof(a)/sizeof(a[0]);
    a =NULL;
    //形参中的数组,不是数组,它是普通的指针变量
    
}




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: ite_ec_c_code_program_guide是一份关于ITE电子创客编程的指南,该指南主要介绍了如何使用C语言编程来实现电子设备的控制和功能扩展。该指南包含了许多基础知识,如C语言语法、数据类型、变量、运算符、流程控制和函数等,并通过实际项目示例来展示如何使用这些知识实现电子创客项目。 在该指南中,使用的编程开发平台是Arduino和Raspberry Pi,这两个平台非常适合初学者和电子爱好者,因为它们易于使用、功能强大,而且有很多社区和论坛可以获得支持和帮助。 指南中还介绍了各种传感器和执行器的基础知识,如温度传感器、湿度传感器、光线传感器、电机、继电器和舵机等,并演示了如何通过编程控制这些设备,实现各种电子创客项目。 通过该指南的学习,可以了解到电子创客编程的基础知识和实践方法,并学会如何使用C语言编程实现电子设备的控制和功能扩展。这对初学者和电子爱好者来说是非常有益的,因为这可以帮助他们更好地理解和掌握电子创客领域的知识和技能。 ### 回答2: ite_ec_c_code_program_guide是一份关于ite_ec_c代码编程的指南。ite_ec_c是一个支持ARM Cortex-M3/M4的嵌入式控制器,该指南提供了有关如何使用该控制器编写c代码的详细信息。 该指南主要包括以下部分: 1.介绍了ite_ec_c控制器的基本功能和特性,以及如何配置控制器的寄存器和引脚。 2.详细介绍了ite_ec_c的编程环境和工具链,包括编译器、调试器、仿真器等。 3.详细说明了如何使用C语言编写控制器的各种功能,包括GPIO、串口、定时器、ADC、DMA、中断等。 4.提供了一些常用的代码示例和实验,帮助读者更好地理解和掌握ite_ec_c的编程。 该指南对于嵌入式系统的开发者非常有用,特别是那些使用ARM Cortex-M3/M4架构的控制器的开发者。同时,该指南也适用于那些对嵌入式系统编程感兴趣的人,他们可以通过该指南学习如何设计和实现简单的嵌入式系统。 总之,ite_ec_c_code_program_guide提供了一个全面的指导,帮助读者更好地理解和掌握ite_ec_c控制器的编程,并帮助他们在嵌入式系统的开发中更加高效和准确地实现自己的想法和设计。 ### 回答3: ite_ec_c_code_program_guide是指ITe公司的EC C Code编程指南,旨在指导初学者学习EC C Code编程语言。 EC C Code是一种适用于嵌入式系统编程的高级编程语言,在工业控制、物联网、汽车和航空等领域应用广泛。EC C Code编程指南从编程语言基础、编译器配置、Debug调试、内存管理等方面入手,深入浅出地讲解EC C Code编程的必要知识,帮助初学者快速入门。 在EC C Code编程指南中,首先介绍了EC C Code的基本语法和语句结构,并提供了大量的代码实例和练习题。其次是介绍EC C Code编译器的配置方法和调试技巧,让读者能够熟练运用编译器进行程序开发和调试。同时,指南还介绍了EC C Code编程中常见的内存管理技术,如堆、栈的概念及其使用方法,有助于读者理解软件程序运作的内部动态。 总之,ite_ec_c_code_program_guide对于学习EC C Code编程的初学者来说是一本非常实用的指南,它提供了全面的教学内容和规范的编程实践方法,能够帮助读者快速提升编程技能,在实际应用中更加得心应手。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值