C语言学习

注:本文是基于Linux操作系统下运行的程序

文章目录

C语言学习第一天

一、写第一个c语言

1.创建c语言流程

 a.打开终端,创建.c文件
  b编辑.c文件
   vi +文件名.c    ; gedit +文件名.c
 c.写c语言代码
 d. 编译  gcc xxx.c -o 可执行程序名字
 e. ./可执行程序名    默认是a.out

2.解释c语言代码

#include <stdio.h> 预处理:头文件-包含函数定义。
//第一个c语言程序 注释–给人看,编译器当做空白,多行注释 /xx/
int main() 入口函数(main函数)–程序执行的入口
{
int i = 0; 定义变量----定义一个i变量
printf(“hello huqing\n”); 打印–屏幕上照常输出
return 0; 返回值: 返回给main的外部
}

二、常量

1.常量:不可以改变的量,不可以修改的量 (建筑物高度,地球直径)

            一般时候,常量是给变量赋值使用。

2.整形常量: -1 , 0 ,100 所有的值都是整数

  表示方式:10进制-满10进1, 16进制满16进1,用0到9+ABCDEF组成,加前缀0x或者H后缀。2进制常量只有1和0,8进制1到7表示,一般用0的前缀

3.浮点型常量:表示小数 -1.2, 1.0, 12.56 ,在内存中存储方式特殊。有误差。浮点型和0比较 float x =0; 不可以 x == 0

4.字符型常量: ‘a’, ‘1’, ‘\0’, ascii表

5.指针常量:指向某一个位置的常量(以后重点)

6.字符串常量: 多个字符用双引号串一起 “abc”

三、进制计算

1.进制关系

十进制: 用0到9表示,满10进1,9+1=10,99+1=100 ,100-1 =99
二进制:用0和1表示:满2进1,借1当2. 10 -1 = 1; 1 + 1 = 10
十六进制:用0到9和ABCDEF表示,满16进1, 9 +1=0XA   F+1=0X10
八进制:用0到7表示,满8进1,借1当8 ;7+1=10;7-1=6 ;77+1=100

2.二进制计算

移位运算:算数左移  <  ,把左边第一个删除,右侧添加0
          10010010  < 1  =   00100100
          10010010 < 8  =  0
          10010010 < 3 = 10010000    
         算数右移: >   ,把右侧删除一个,左侧添加0  
         10010010  > 3  =   00010010

   与: & ,相同位上都是1则结果为1,否则为0. (有0则0)
       10010  & 1011                                           00010010
                                                                  &     00001011
		                     ------------------
                                                                         00000010

  或: | ,相同位上有1则结果位1,否则为0,(有1则1)案例:    10010 | 1011 = 11011

 取反:~,如果是1则取反的结果位0,如果是0则取反的结果位1,案例   ~100110 = 011001

  按位异或: ^ ,同1则1,同0则0,不同则0;案例:110^101 = 100

3.进制转换

十六进制和二进制转换
 2进制转16进制:二进制的4个位,表示16进制中的1位。 案例:1000 1001 =  0x89
         案例: 11011 --> 0001 1011  =0x1B
 16进制转2进制:一个16进制位表示4个2进制位  案例: 0xA0B = 1010 0000 1011  

 十六进制和10进制转换:
 10进制     0~9  10   11  12  13  14  15   16
 16进制   0~9  A    B    C   D     E    F     0X10
8进制和2进制的计算
2进制转8进制,3个2进制位转换成1个8进制位
      011 011 010  --> 332
 8进制转2进制,1个8进制位转换成3个二进制位
    7024 = 111 000 010 100
10进制转换成2进制,把10进制短除法2后直到商0后得到的余数从下往上写就是2进制
2进制转10进制,用1 2 4 8 16   1101011 = 64+32 +  8+  2+1 = 107

四、变量:可以变的量,可以修改的量(64为系统)

1、整形是 int ,

表示整数如-20, 0, 1。 总共是4字节可以用sizeof(int)打印,表示的数值范围是-21亿~+21亿
短整形 short ,表示短整数。 总共是2字节16位,表示的数值范围是65535
长整形 long, 表示长整数。 总共是8字节。对long类型赋值,需要在常量后加L ,long x = 10L;

2. 浮点型: float ,

单精度,表示6位小数,表示小数类型,1.2,-2.3, 0.0,总共多少位,给float类型复制需要加f。
double,双精度,表示12位小数,总共多少位

3.字符类型: char ,

表示字符如‘a’,‘b’, 在内存中占1个字节。范围是0~255,sizeof(char) = 1;
ascii:是把字符和整形对应的一个表 ‘0’—48 ,‘A’—65,‘Z’–90, ‘a’—97,‘z’—122, ’ '—32 , ‘\0’—0
转义字符: 和原本意思不一样了。 \n —换行 \t----tab \—一个\ %%—表示一个% " ----表示双引号

4.字符串类型:

没有对应变类型,“aa”,char* p = “asdfgasdg”;

5.每个类型都分为有符号和无符号

   正数是无符号,负数是有符号,如果只想表示正数则用无符号。关键字     unsigned   
   例如:unsigned int  x = 123;
补充: 1字节 = 8位
           1KB = 1024B
           1MB = 1024KB
           1GB = 1024MB
           1TB = 1024GB
           1EB = 1024TB

五、输入和输出 加上#include<stdio.h>

1.在屏幕上输出,printf

    格式: printf("照常输出部分 占位符 ",变量);
    格式: printf("照常输出 %d %c\n",变量1,变量2);
              printf("int = %10d \nfloat = %10.5f\n",x,z);
    占位符:  %d      --------打印int整形的值 ,%10d 总共显示10位,不够的部分用空格替换,右对齐
                    %o(字母o) 打印8进制
                    %x------------打印16进制
                    %hd   --------打印short的值
                    %ld   ---------打印long的值
                    %u    ---------打印无符号数据的值
                    %c  --------- 打印字符类型
                     %f   --------- 单浮点型,%5.3f总共5位,小数点占3位。
                    %lf   %le--------- 双精度浮点型
                     %s  ----------字符串 
                    %p ------------指针

2.输入 scanf

       格式: scanf("占位符",&变量);
                  scanf("占位符,占位符",&变量1,&变量2);如果是逗号,则输入的时候也要用逗号隔开
                  scanf("占位符 占位符",&变量1,&变量2);如果是空格,输入的时候也是空格隔开
     练习:输入年龄和姓名(姓名用一个字符表示),把输入的内容打印出来。(代码day01/04test.c)

五、运算符

1.算数运算符

      + 加法     计算两个数的和,例如 int a = 10 ;int b = 20; a + b ,其中a和b的值不变,a+b得到的是a和b的结果。如果a修改需要赋值
       - 减法    同上
        *乘法   同上
       /  除法  整除,所有的小数部分丢弃。 12/21 = 0   12 / 4 = 3; 12/5=2
       %  取模,余数,得到相除后的余数  12%21=12 ,12%4 = 0; 12%5=2 ,值1%值2把结果限定在值2范围内,123%5=3

2.赋值运算符

  格式: 左值= 右值; 把右值给到左值
  复合赋值运算符:+=  ,*= ,-=,/= ; %=; |= ; &=; >>=;<<= (算数运算符,二进制运算符) 	
  例如: int x = 10;  int y = 20;   y *=x+2; 等价于 y = y*(x+2);是240
  注意: 左值不可以是常量  ,只可以是变量。不可以有其他的运算。

3.关系运算符

   关系运算符的结果只有两个,真或者假,非0为真,0表示假。
   >   如果左值大于右值,结果为真,否则为假
   >= 如果左值大于或者等于右值,结果为真
   <    如果左值小于右值结果为真
   <=  如果左值小于等于右值,结果为真
    ==  如果左值和右值相同则结果为真,否则为假
   !=    如果左值和右值不相同则结果为真
   注意:一般情况用于判断语句,比如说if语句中。
            在比较运算符==时候,需要把常量放前面,以防出现赋值运算符
            关系运算符连用是不正确的,例如:10 < time < 15

4.逻辑运算符:(双目)

 && : 表达式左值和右值都为真则结果为真,否则为假 。&表示按位与
    ||   :表达式左值或者右值有一个为真则结果为真。|表示安位或。
    ! :逻辑非,如果表达式为真则结果为假, !(2>6)
 注意:&&有截取功能,如果第一个表达式(左值)为假,右侧的值不计算。
           || 也有截取功能,如果第一个表达式为真,则第二个表达式不会计算。
 案例1:请输入你的年龄,和金钱。如果年龄小于18岁,并且钱大于10000,则是高富帅,否则为屌丝。(代码day01/gaofushuai.c)
 练习2:输入三个数,请判断哪个值最大,打印出最大值。

5.自增自减运算符 (单目)

  前加加:++x; 表示x= x+1;是先自己加1后再做其他事情
  后加加:x++; 表示x = x+1;是先计算完其他操作再自己加1(暂时理解遇到分号加1)
  前减减:--x:
  后减减:x--:表示x = x-1;是先计算完其他操作再自己减1(暂时理解遇

到分号减一)

6.三目运算符 (运算符有三个值)

格式: 表达式1 ? 表达式2:表达式3
执行:如果表达1为真则执行表达式2,如果表达式1为假则执行表达式3.
三目运算符可以代替简单的if语句使用。并且三目运算符可以嵌套使用。

7.运算符的优先级

优先级:先计算的运算符优先级高,否则优先级低
优先级顺序:括号–>单目–>算术运算符–>移位运算符–>关系运算符–>位运算符–>逻辑运算符–>三目运算符–>赋值运算符–>逗号运算符。

六、分支语句

1.if分支语句

 if格式:
  if(条件判断)
  {
     语句1
  }
  else
  {
     语句2
  }

2.执行:如果条件1满足则执行语句1,不满足执行语句2;
3.格式2:
if(条件判断1){
语句1;
}
else if(条件判断2) {
语句2;
}
else {
语句3;
}
执行: 先判断条件1是否满足,如果满足则执行语句1后结束if语句,如果条件1不满足继续判断条件2,如果条件2满足则执行语句2,否则执行语句3;
注意:有if不一定有else if和else 但有else必定有if ,有else if也必定有if。
练习: 判断某一个数是不是回文:12321 22222,32123 (day01/10same.c)

getc putc, gets puts getchar putchar sprintf sscanf的使用(了解)

C语言学习第二天

一、if嵌套

   格式:
if(条件1)   
{
    if(条件3)  
    {
          语句4;
    }
    else    
    {
          语句5;
    }
}
else if(条件2)  
{
 语句2;
}
else  
{
  语句3;
}

执行:先判断条件1是否满足继续判断条件3,如果条件3也满足则执行语句4后结束,如果条件3不满足则执行语句5结束,
如果条件1都不满足则继续判断条件2,如果条件2满足则执行语句2,如果条件2也不满足则执行语句3

2.开关语句:switch

格式: switch(表达式)
{
case 常量1:表达式1;break;
case 常量2:表达式2;break;
case 常量3:表达式3;break;
case 常量4:表达式4;break;

default: 表达式5; break;
}
执行: 先计算表达式的值,和case后的常量比较,当常量的值和表达式的值相同时,则执行后面的表达式,如果所有的case都不匹配,则执行defaul后的语句
注意:case后的常量不可以相同。
一般情况下 在每个case后都会加上break;
default不是必须有,可写可不写。但一定是最后一个匹配。
case常量后是冒号:
如果在case后需要定义变量,则要加上大括号使用。
练习: 输入成绩,用switch打印等级(day02/03sorce.c)

3.goto语句

作用:跳转到某一个位置,需要提前把位置设置好,遇到goto加标签则直接跳转到标签位置。
格式: goto 标志;
案例: DANNY:  //设置标志
           goto DANNY; //跳转到标志
练习: 使用goto计算1到100的偶数和(day01/05even.c)

二、循环语句

1.while循环语句

格式:while(条件)
          {
                   循环语句;
          }
2.流程:首先判断条件是否满足,如果满足执行循环语句,然后继续判断,满足则一直执行,知道条件不满足为止;
3.练习: 打印1到100的和(day02/06while.c);
4.练习:输入两个数,用while循环打印出两个数中间的所有整数(包含两个数)()
5.练习:打印斐波那契数列。
 注意:while后不可以加分号

6.continue 和break

  continue:退出当次循环,遇到continue后的代码不执行,继续执行下一次循环。
  break:退出当前循环,遇到break则退出循环;
7.死循环(无限循环)
 定义:当循环条件永远为真则循环不会结束,这种循环叫无限循环。无限循环不结束则后面的代码无法执行。
  比如说 while(1){}      while(1);

三、循环嵌套:

1.定义:在循环中加入另外一个循环
2.格式:  while(条件1)
         {
			语句1;
            while(条件2)
            {
				语句2
            }
       	    语句3;
 	     }
 3.执行:先判断条件1是否满足,如果满足执行语句1,后继续判断条件2,如果条件2满足则执行语句2后继续判断条件2,
    直到条件2不满足才会退出内部循环,然后执行语句3,再执行外部循环的条件1,如果满足继续刚才的流程,直到条件1不满足则退出循环。

注意:在循环嵌套中,如果遇到break,则会退出当前循环,break在哪个括号中则退出当前括号的循环。

4. do…while循环

格式:do
{
循环体;
}while(条件);
执行:先执行循环体,在判断条件是否满足,如果满足则继续执行循环体,如果不满足则退出循环。不管是否满足条件,至少会执行一次循环体。
随机值:电脑随机产生一个值,是随意的。
随机值产生步骤: 添加头文件 #include <stdlib.h>,需要用srand做种子,然后rand产生随机值。
案例:猜数小游戏,随机产生值,然后和输入的值比较,给出大小提示,直到用户猜对为止。(day02/11guess.c)
注意:在while后要加分号。

5.for循环

格式: for(语句1;条件2;语句3)
{
循环语句4;
}
注意:语句1一般为 定义变量语句
语句2一般为判断条件语句
语句3一般为自增自减语句
执行:先执行语句1,然后判断条件2是否满足,如果满足 则执行循环语句4,继续执行语句3后再判断条件2是否满足,
如果条件2还满足则继续执行循环语句4,直到条件不满足为止。

6. for循环嵌套

  格式:for(语句1;语句2;语句3)
         {
            for(语句4;语句5;语句6)
            {
                   循环体7;
            }
        }
 执行:先初始化语句1,判断条件2是否满足,进入到内循环中,执行语句4,判断语句5是否满足,如果满足则执行循环体7,
           再执行语句6后判断语句5是否满足,如果满足则一直执行循环体7中内容,如果不满足则执行语句3,在判断语句2是否满足。
练习:输入一个值,然后打印输入值的行数的三角形(day02/14triangle.c )  
      *
    *   *
 *    *   *  
练习: 九九乘法表

四、数组:

1.定义:相同数据类型的连续的集合。
2.格式:数据类型 数组名[数组元素个数] = {多个值};
例如: int arr[6]={1,2,3,4,5,6};
3.元素:数组的每个值是他的元素,用数组名和下标表示例如arr[2]
下标:数组的下标是从0开始到数组元素个数-1.不可以越界使用
4.数组的初始化:
int arr[4] = {1,2,3,4}; 全部初始化
int arr[4] = {1,2} 部分初始化,未初始化部分默认为0
int arr[4] = {0} 全部初始化成0;
int arr[ ] = {1,2,3,4} 缺省初始化,会根据初始化个数自动确定元素个数
练习:请打印斐波拉契数列:1 1 2 3 5 8 (20项)
5.补充知识: (头文件unistd.h)
sleep() 代码延时, (秒)
system(命令) 调用外部程序执行
exit() 结束程序 ,结束进程
注意:在Windows下是没有这个头文件的。

C语言学习第三天

一、一维数组

1.定义:数据类型 数组名[数组元素个数] = {1,2,3};

2.变长数组(伪):数组元素个数可以改变的数组叫变长数组

   实现: int a ; scanf("%d",&a); int arr[a]; 数组大小会随着输入的内容进行修改

3.练习:随机产生十个学生的学号(100以内),用户输入学号后判断在数组中是否存在,如果存在则打印出位置。(day03/02findStudent.c)

二、二维数组

1.二维数组:在一维数组中插入一维数组,每个二维数组中的元素都是一维数组。

2.格式: 数据类型 数组名[行数][列数] = {值};

   例子: int arr[3][5] = {1,2,3}; 

3.理解: (int ARR[3]) arr[3] = {1,2,3}; 只可以这么理解
int arr[3][3] = {1,2,3}; //3行3列

4.下标: 数组元素中,行下标= 行数 -1

                                 列下标 = 列数 -1

5.初始化方式:

     int arr[3][2] = {1,2,3,4,5,6};    全部初始化
     int arr[3][2] = {1,3};               部分初始化,没初始化的默认是0
     int arr[3][2] = {{1},{3,2},{4,1}}  第一行1和0,第二行3,2,第三行4,1分组初始化
    int arr[ ][2] = {1,2,3,4,5,6,7} ;   缺省初始化,默认是4行,第四行是7和0

6. 三维数组:int arr[2][3][4] ;

5.补充:fflush(stdout); //清空输出缓冲stdout. 其中stdin是输入缓冲
练习: 有5个学生,每个学生都有语数外的成绩,请输入学号和科目(0~2),打印出学生的成绩。(成绩随机生成)(day03/04findDoubleArr.c)

三、函数

1.函数:对某一部分重复代码进行封装,方便使用,增加代码的模块化。

2.格式:返回值类型 函数名(参数)

            {
                  函数体;
            }

3.注意: 如果没有返回值用void代替,如果没有参数可以空着也可以用void代替

               函数内部不可以定义函数,必须放全局。
               如果不写返回值类型也不写void则默认是int返回值。

4.参数:调用者给被调用者传递值

    格式:返回值类型 函数名(数据类型 变量名,数据类型 变量名){ }
    实参:实际参数,在内存中存在。比如main函数中的变量
    形参: 形式参数,函数调用前没有内存存储形参,只是形式。
              所有形参都是实参的拷贝。
    练习:请写一个函数,交换两个变量的值,然后再main中打印交换后的值,在函数中打印交换后的值。(day03/07change.c)
     注意:形参改变,不会影响实参的值,他们在不同的内存空间。

5.局部变量和全局变量

     局部变量:定义在局部,在某一个括号中的变量(小括号,大括号)
     全局变量:  定义在全局,没有定义在某一个括号中

6.作用域和生命周期

    作用域: 变量可以使用的范围,局部变量一般在某一个括号中,空间角度     
    生命周期:变量从在内存中存在到内存中释放的时间。时间角度

7.局部变量和全局变量的区别

     生命周期的区别:
              全局变量的生命周期:从程序运行到整个程序结束
              局部变量的生命周期:从定义开始到括号结束。
     作用域的区别:
              全局变量:在整个项目中都可以使用,不限于当前文件
              局部变量:从定义开始到大括号结束。

8.静态变量和常量

  常量:不可以修改的量。用const修饰。 const int x = 123; 则x=234错误。
  静态变量:在变量前加static。
  全局静态变量:全局静态变量不会修改生命周期,但把作用域限定在本文件中。
  局部静态变量:局部静态变量作用域不变,生命周期从定义开始到整个程序结束吗,局部静态变量只会初始化一次。
 注意:在同一个作用域内不可以有相同的变量名
           在不同的作用域内可以有相同变量,如果全局变量和局部变量名相同时,优先使用局部变量,就近原则。
           全局变量只有一份,如果某个位置修改了全局变量的值,其他地方全部修改。一般情况下避免使用全局变量。

9.返回值

   作用:函数执行完代码后,把结果反馈给调用者。
   格式: int fun(int x){ return xx;}
   注意:如果有返回值类型,就必须加return关键字;
             return只可以返回一个值,例如 return x,y;是错误的。
             函数遇到return 则结束,后面的代码不会执行。
             如果返回值是void,可以使用return;结束函数。
             函数在使用前需要申明,如果没有申明会隐式声明成int返回值和int参数
  练习:请在main函数中输入一个行数和列数,通过调用函数返回杨辉三角对应的值。(day03/08return.c)

10.main函数的参数

 格式: int main(int argc,char* argv[ ]);
  参数: argc是参数的个数,argv是参数的内容。char* 表示字符串,[ ]字符串数组。
     
补充:
    #include <stdlib.h>
     int atoi(const char *nptr);    把字符串转换成int
     long atol(const char *nptr);  把字符串转换成long
     long long atoll(const char *nptr); 把字符串转换成longlong
     如果需要把某一个类型转换成其他类型,直接在前面加上转换后的类型加小括号 int x = 10;  float y = (float)x;这个叫强制类型转换。
     在32位系统中,long是4字节,longlong是8字节,在64位系统中,long是8字节,longlong也是8字节。

五、字符串:

1.字符串:字符串是由双引号括起来的,以\0结束的一串字符

 2. 字符串常量: “abc” , 每个字符串后默认会添加'\0', ascii是0
 3.表示方式: 
    char arr[10] = {'a','b','c'}; 部分初始化后面的部分是0,而\0的ascii是0
    char * arr = "abcasg";  指针表示方式。
    char arr[] = "abcde";
  4.字符串的长度包含\0,字符串的有效长度不包含\0,%s打印字符串。

2.字符串函数:

    1>字符串不可以使用==比较,strcmp
        #include <string.h>
        int strcmp(const char *s1, const char *s2);
        作用: 比较两个字符串是否相同
        参数:s1 第一个字符串
                  s2 第二个字符串
         返回值:如果相同返回0,如果第一个大返回正数,第一个小返回负数
                      返回值是第一个字符串中不相同的字母ascii值减去第二个字符串不同的字母的sacii。
   2> 计算字符串的长度 strlen
     size_t strlen(const char *s);
     作用:得到字符串的有效长度,不含\0
     参数: 需要计算长度的字符串
     返回值:返回字符串的有效长度
   3>字符串的拷贝 strcpy
     char*  strcpy(char *dest, const char *src);
     作用: 把stc中的内容拷贝到dest中
     参数: stc 源字符串
                dest是目的字符串,dest只可以用数组的表示方式
                dest必须有足够的空间存放stc的内容,比如说stc是“acd”,则dest中数组必须有4个元素。
       返回值:拷贝后的dest的首地址,dest字符串。

C语言学习第四天

一、字符串:

1.字符串比较函数 strcmp

   int strcmp(const char *s1, const char *s2);
   作 用: 比较s1和s2字符串是否相同
   参 数:s1是需要比较的第一个字符串
              s2是需要比较的第二个字符串
   返 回: 0   如果两个字符串相同
               <0 第一个字符串小于第二个字符串
               >0 第一个字符串大于第二个字符串
              比较的是第一个不相同字符的ascii的值的差。

2.得到字符串长度 strlen

    函数原型:  size_t strlen(const char *s);
          作用:  得到字符串的有效长度
          参数: 需要获取长度的字符串内容
          返回: s字符串的有效长度

3.字符串追加 strcat

    函数原型:char *strcat(char *dest, const char *src);
          作用:把src字符串拼接到dest字符串后面
          参数: src源字符串,需要拼接到dest后的字符串
                     dest目的字符串,需要存放src字符串。
          返回:返回拼接后的字符串内容。

4.字符串的拼接 sprintf

    函数原型:int sprintf(const char *format, ...);	比如:int arr[10],a,b;   sprintf(arr,"%d %d",a,b);
           作用:把可变长参数中的内容合并成一个字符串format
           参数:第一个部分:字符串变量,        
                     第二个部分: 双引号的内容,有占位符
                     第三个部分:各种变量,用来填充占位。
          返回:拼接后的字符串长度。

5.字符串的输入

        char *gets(char *s);
        作用:获取一个字符串,以回车结束输入。
        参数:输入后的内容保存的位置。
        返回值:输入的字符串内容。
        注意:会有危险警告,没法检测s的内存空间,避免使用。
       
       int getchar(void);
       作用:获取一个输入的字符
       参数: 无参数
       返回值:输入的字符的ascii值。
      
       注意:输入函数是堵塞函数,没有输入则一直等待直到输入结束为止。

6.字符串的输出

       int putchar(int c);
       作用:输出一个字符
       参数:需要输出的字符ascii值
       返回:也是输出的ascii值

       int puts(const char *s);
       作用:输出一个字符串
       参数: 需要输出的字符串内容
       返回值:输出的字符串的字符个数,包含\0

7.字符串的拷贝

      char *strcpy(char *dest, const char *src);
      作用:拷贝src的内容到dest中
      参数: src源字符串
                 dest 目的字符串
       返回值:拷贝好后的字符串  dest字符串。

     char *strncpy(char *dest, const char *src, size_t n);
      作用:拷贝src中的前n个字符。
      参数:  src源字符串
                  dest 目的字符串
                  n    需要拷贝的字符个数
      返回值:拷贝好后的字符串  dest字符串。

练习:输入gets两个字符串,通过strncmp比较前5个字符是否相同,如果相同则把第二个字符串的前3个字符拷贝到第一个字符串的后面。(day04/03strncat.c)
int strncmp(const char *s1, const char *s2, size_t n);
char *strncat(char *dest, const char *src, size_t n);

8.内存初始化函数

     函数原型: void *memset(void *s, int c, size_t n); 
          参 数: s 是字符串的首地址,内存的首地址(数组名)
                      c 需要初始化的值,比如说是0
                       n 需要初始化的内存大小。
           返回值:内存首地址
              注意: memset按照字节进行初始化;
    
     函数原型:       void bzero(void *s, size_t n);
作用:  把s内存初始化成0
         头文件: #include <strings.h>
             参数:s 字符串--内存首地址
                       n 需要初始化的内存大小
           返回值:无
         
       memcpy;
       sscanf;

二、函数高级

1.递归函数;

     含义: 函数自己调用自己。
     案例: int add(int x){      add(20);     }
     规律: 1> 找到特殊值,也就是函数出口
                 2> 找到公式,普通情况下的处理方式 

三、结构体

1.结构体:不同数据类型的集合,属于自定义类型。
 2.案例:用一个东西来存学生的信息,学号,姓名等,int age,int id 

3.格式: struct 机构体名{数据类型 变量名1;数据类型 变量名2;… };

 4.变量:struct 结构体名 变量名;
 5.定义全局结构体变量
     struct person{
int id;
int age;
char name[20];
   }lzf;
     lzf是一个struct person的变量。

     typedef struct person{
int id;
int age;
char name[20];
   }per;
per是一个struct person的类型,也叫做它的别名。
    6.使用: 结构体变量名.成员变量;
                 lzf.id = 123;
    7.初始化: 和数组的初始化方式一样。初始化的类型要和结构体定义类型匹配
                       struct person danny = {10,20,"abcd"};
    8.改名: typedef个关键字,在结构体struct前加上typedef

9.结构体的对齐和补齐

        因为结构体的成员变量类型不一样,所以cpu在找数据的时候会比较麻烦,为了使cpu访问速度提高,
        以空间还时间的方式,给结构体中空余一部分空间,使之对齐,提高访问速度。
       节省空间办法:
         小类型放前面,大类型放后面(char --short ---int ---float--long---double--超过8的数组)

四、结构体数组

数组:相同数据类型的集合,

结构体数组:数组中的每个元素都是结构体类型、

  例如: struct student arr[10];
             arr[0].id = 123;
             
 补充:数组名就是数组的首地址,在scanf的时候直接传入数组名就行不需要加&

C语言学习第五天

一、共用体:

共用体:多个变量公用一块内存空间    
关键字: union 共用体名{
                 类型 变量名1;
                 类型  变量名2;
            };
 大小:共用体大小是最大类型的大小,如果有char int 则大小是4字节
         在同一个时间点,共用体中的变量只有一个存在。
 场景:在网络通信中,发送端发送数据后接受端不知道什么类型的数据,接收端通过共用体,一块内存不同的类型表示来接受数据。
 定义: union 共用体名  变量名; 
             不可以直接用大括号初始化,因为只有一个变量有内存。
  使用:共用体名.成员变量名 = 值;

二、枚举类型

枚举:用一个名字代替一个值,为了代码的可读性更好。
格式: enum 枚举名{枚举常量1,枚举常量2.....};
使用: 直接把枚举常量当做普通常量使用。
枚举值:枚举中的常量值默认从0开始,后面常量值自动加一处理
注意:可以在switch中使用,在case后当做常量使用。
           枚举类型在64位系统占4字节,相当于一个int。
案例:
  enum day{mon,tue=3,wen=2,thu,fri,sat,sun};
 //从第一个赋值的元素开始加以
int main(){
printf("mon = %d\n",mon);//默认是0
printf("tue = %d\n",tue);//赋值3
printf("wen = %d\n",wen);//赋值2
printf("thu = %d\n",thu);//默认2+1
printf("fri = %d\n",fri);//默认2+1+1
printf("sizeof(enum day) = %d\n",sizeof(enum day));
return 0;
 }

三、预处理指令

1.编译过程:   预处理,编译,汇编,链接。
2.预处理指令:以#开头的部分。不是c语言的语句,不需要加分号。
             包含:头文件,宏定义,条件编译。
3.宏定义:用一个名字代替一个值
       格式1:#define 宏名称 替换文本(值) 
       格式2:#define 宏名称                   (定义一个标志)
       格式3:#define 宏(参数) 表达式
4.注意:#define CJ(X,Y) ((X)*(Y))  //宏函数需要给每个参数加上括号,整体加上括号。以为宏函数只替换内容,不会自动加括号。

5.条件编译
   满足某一个条件则编译一块代码,不满足则不编译。
   格式1:#ifdef 宏
                  编译代码1
                #else 
                    编译代码2
                 #endif
    编译:如果宏存在(#define 宏)则编译代码1,如果不存在则编译代码2
    格式2:#if 条件
                 编译代码1
                 #else
                    编译代码2
                #endif
  编译:  如果条件为真则编译代码1如果条件为假编译代码2
  格式3: ifndef  宏
                     编译代码1
                #else 
                    编译代码2
                 #endif
  编译:如果宏不存在则编译代码1,如果存在则编译代码2.

四、头文件

   作用:定义结构体,函数的申明,宏定义,文件的包含
	   #ifndef __FILE_H__
       #define  __FILE_H__

       #include <stdio.h>   
       struct student{};
       #define xxx 10
       void fun();

       #endif

后缀:头文件后缀是.h
使用:在include自定义的头文件时,使用“”而不用<>,使用系统库头文件时,使用<> 而不适用“”
区别: #include <xxx.h> 默认先从库文件目录查找,如果没找到再从PATH路径找,如果还没找到则报错。
而#include""先从当前目录开始查找,如果没找到继续查找库文件目录,如果没找到继续查找PATH路径,还没找到则报错。(系统库目录:/bin/include)
防止头文件重复包含
#ifndef _ _ XXXX_H_ _ 下划线之间不要空格,这里是格式原因
#define _ _ XXXX_H_ _
头文件内容;
#endif

或者 #pragma once

五.指针(所有以下内容都是基于64位系统)

1.指针:是指向地址的变量,保存的是地址

   地址: 变量存储的位置编号,理解成门牌号。常量。

2.定义指针

  数据类型*  指针变量名 = &变量;
  int a= 10;
  int* p = &a;
  解引用: 得到指针所指向内存空间的内容
 *p = 123; 则表示把a的值修改成123,printf{"a=%d",*p};

3.指针类型

  指针的类型是所指向的内存空间类型后加*; 比如int a; int*p =&a;
  指针所指向内存空间的类型:指针类型去掉星号

4.指针运算

  指针可以做++ ; --;  +常量 ; -,-常量; 地址+地址
  地址相减:实际减的是个数,理解成相隔几个房间。
 定义一个指针,指向double类型的变量,打印出指针的值。(%p)

C语言学习第六天

一、指针的定义

1.int* p = &a;

   指向改变: p = &b;
   指向内容改变:*p = 123;

2.指针运算

     指针和指针相加是非法。 
     指针和指针相减是可以的;
      double a[2] = {0}; 
      double* p=&arr[0];
      double*q = &arr[1]
      q指向a[1], 计算q-p =1;表示相差几个double
      指针加常量是可以的 p+1是可以的  p+2越界是错误的; 
      指针可以++ ,--

3.解引用

      得到指针所指向的内存空间的值。
      在指针前加*,
      例如 int a = 10;  
              int* p = &a;  
              *p=110;
      给指针赋值 指针指向发生改变。(非常重要)

4.野指针

      野指针:不指向某一个固定位置的指针。要防止野指针出现
      空指针:指向NULL的指针。当指针不知道指向哪里时,则赋值为NULL;
      段错误:核心已转储,操作了一块不允许操作的内存控件,数组越界,操作了野指针,用空指针解引用。

5.常指针(面试题):只有const挨着指针的时候才是修饰指针,指针指向不可以改变。

   指针常量:指针所指向的内存空间是不可以修改的
   const int *p = &a;   p=&b 允许;但*p= 22是错误的; b=22可以的;

   常量指针:指针的指向不可以修改
   int  * const p = &a; p=&b不允许;但*p= 22可以;

   const int* const p=&a; 指针的指向和所指向的内存空间都不允许修改

   补充1:如果定义一个const变量,用指针指向变量后,可以通过解引用修改
      const int a = 123;
      int *p = &a;
      *p=222;  允许;

  补充2: 直接用指针给指针赋值是可以的
            int a = 123;
            int *p = &a;
            int *q = p;  是可以的,可以用指针直接给指针赋值。

二、二级指针

1.二级指针:保存的是一级指针的地址;同样是8个字节。

     一级指针:保存的是变量的地址。

2.格式:数据类型** 二级指针变量名 = &一级指针变量名;

     案例: int a = 123;     
                 int*     p  = &a;
                 int**  pp= &p;
命名规则:         pp_num;  ppNum;  PpNum;

3.使用案例:

   int main(int argc,char *argv[])
   {
int a = 123;
int b = 234;
int* p = &a;
int * q = &b;
printf("*p  %d\n",*p);

int **  pp = &p;//二级指针不可以是野指针
*pp = &b;  //*pp等同于p等同于&b,改变了p的指向,pp=&&a 错误
printf("*p =%d,**pp =%d\n",*p,**pp);

pp = &q; //pp指向q,
printf("*p =%d,**pp =%d\n",*p,**pp);
            return 0;

  } 

三:动态内存分配

总共分为:代码区,数据区,堆区,栈区
根据地址从小到大分布如下:
代码区:存放代码,不可以修改
数据区: 静态常量区 :静态变量和常量
  全局变量区:已初始化的全局变量
  bss段:未初始化的全局变量

堆区:动态内存申请,自己申请自己释放,先从低地址分配,再分配高地址。
栈区:存放局部变量,自动申请自动释放,先从高地址分配,再分配低地址空间,堆区和栈区无明显的分割线。
 

2.  动态内存申请

   void *malloc(size_t size);
    作用:在堆空间中申请内存。
    参数: size 需要申请的内存大小
    头文件: #include <stdlib.h>
    返回值:申请到的内存空间的首地址。
                   int* p = (int*)malloc(8);
    注意:malloc申请的内存空间没有初始化时,存放的是乱值。
              malloc的返回值需要强制类型转换才能使用。
              malloc申请的内存空间,用完后需要释放。
    案例:用malloc申请一块内存,存放3个学生的信息,学生(id,age);代码如下:
  	#include<stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct student
{
	int id;
	int age;
}stu;

int main(int argc,char *argv[])
{
  	//连续内存空间可以使用下标操作
  	// 结构体数组 stu arr[3];  p=&arr[0];
stu* p = (stu*)malloc(3*sizeof(stu));
if(NULL == p)
{
	perror("malloc");//打印错误信息
	exit(0);  //结束程序
}
memset(p,0,sizeof(stu)*3);//malloc申请的空间是乱值。
for(int i = 0; i < 3;i++)
{
	printf("请输入学生id和age\n");
	scanf("%d %d",&p[i].id,&p[i].age);

}
for(int j = 0;j < 3;j++)
{
	printf("第%d个学生的id是%d age是%d\n",j+1,p[j].id,p[j].age);
}
//相同数据类型连续的集合
int* pa = (int*)malloc(10*sizeof(int));
printf("%p,%p\n",pa+1,pa);//相差4字节
//如下会出现野指针
//int a = 123;
//pa = &a;   malloc申请的内存pa不再指向,导致内存泄露
   return 0;

}

    备注: 对于连续的内存空间可以使用下标操作(重点)
   	 int* p = (int*)malloc(5* sizeof(int));
             p[0] = 123;
             接受malloc返回值的变量指针,不允许被修改,不可以指向其他位置。如果修改会导致malloc申请的内存没有指针指向,内存泄漏。


  void free(void *ptr);
  作用:释放动态申请的内存空间,如果不释放内存泄漏
  参数:malloc返回的指针
  返回值: 无
 
   void *calloc(size_t nmemb, size_t size);
   作用:动态申请内存。申请的内存默认初始化成0.
   参数:nmemb申请的内存块的个数
             size 每一块内存的大小
   返回值:申请的内存空间的首地址。

  void *realloc(void *ptr, size_t size);
  作用:重新申请内存空间。重新分配内存空间
  参数: ptr   从ptr地址开始申请,一般malloc的返回值。
             size  一共申请size大小。
  返回值:重新申请的内存空间首地址。
  注意:realloc申请的内存不一定是从ptr开始,当ptr开始的内存不足以有size个的时候,会先释放当前内存后,重新在另外一个区域申请。

四、指针和函数的关系

 1.函数:存在代码区(不允许修改)
 2.函数名: 就是函数的首地址。  void  fun(int x);
 3.练习: 请写一个函数,修改两个参数的值。形参和实参都需要修改。
              void change(int *a ,int * b);  

4.注意:不可以返回局部变量的地址。因为函数结束后局部变量就被释放了。

               malloc申请的内存空间函数结束依然存在。只有free释放之后才不会存在。 

学习fopen fread fwrite fgets fputs fgetc fputc fclose fseek rewind ftell 的使用。

C语言学习第七天

1.函数和指针的关系

int a = 123;
int b = 234;
int *pa = &a;
int * pb = &b;
请用一个函数,修改pa和pb的指向,实参和形参同时修改(day07/01fun.c))。
备注:在函数中,如果想修改形参一级指针指向,需要传入二级指针。
注意: 不可以返回局部变量的地址。()

2.malloc和函数的关系

案例:
int*  funmalloc()
{
  //	int a = 123;
int* p =(int*)malloc(sizeof(int));
  //	p = &a;
*p = 123;
//	return p;	 
 }
注意: 在函数中动态申请的内存,需要在函数内部释放,要么需要返回首地址给调用者,否则会出现内存泄漏。
注意:
 /* 错误 p所指向的内存空间不允许修改,*p指向一级指针,所以不可以修改一级指针指向(查看大门01fun.c)查看图片(函数和malloc)
  void funconst( const int** p)
 {
*p = (int*)malloc(sizeof(int));

  }*/

3.函数指针和指针函数

指针函数:是返回值是指针的函数 int* fun(int a){ }
函数指针:是一个指针,指向某一个函数。
函数指针格式: int (fun)(int a); fun是指针,指向参数是int 返回值是int的函数,指针的类型 int () (int a); fun指向的类型 int p(int a);
使用:函数指针名(参数); 例如void (*pfun)(int a) = fun; pfun(10);
命别名: typedef int (pf)(int a,int b) ;其中pf是指针类型。
定义了一个函数指针类型为int (
)(int ,int)
定义指针变量: 函数指针类型 指针变量= 函数名
注意:给指针变量赋值,需要匹配相同的指针类型,则返回返回值和函数的参数要和指针类型相匹配,否则是类型不匹配错误。
一般情况下 函数指针名都会用callback
当数组作为函数参数时,会隐式转换成指针使用。
回调函数:把函数指针当做函数参数,系统回调函数是系统自动调用函数。

案例如下:用一个函数计算两个数的加减乘除。
 #include<stdio.h>
   void fun(int a){printf("a = %d\n",a);}
   //定义一个函数指针类型
   typedef int (*pf)(int a,int b) ; 其中 pf是类型,不是变量名
   //可以这么理解typedef int(*)(int a)   pf; pf是别名,是类型,这个格式会语法错误。
    void fun(int a){	printf("a = %d\n",a);}
  int add(int a,int b){	printf("add = %d\n",a);}
 	  int sub(int a,int b){	return a-b;}
   int jisuan(int a,int b,pf function)//pf function = sub 
  {
	return function(a,b);
           //function只是一个变量,实参是什么则funciotn是什么。
    }
int main(int argc,char *argv[]){
//pfun是指针名,是变量,不是类型
void (*pfun)(int a) = fun;
pfun(10);//实际调用的是fun函数,打印a=10;
pf pmyfun = add;//pmyfun指向add函数,
pmyfun(1,3);
printf("a-b=%d\n",jisuan(2,4,sub));
           return 0;

}

二、数组和指针的关系

1.数组名: 数组名就是数组的首地址。数组名是const指针,不可以指向其他的位置,只可以指向数组的首地址。int arr[10] = {0},arr 和&arr[0]相同。arr++是错误的。

练习:定义一个数组,10个指向int类型的指针。int* arr[10];

2.指针数组: 是数组,在数组中存放 指针 int* arr[10];

3.数组指针:是指针,指向某一个数组。
意义: int (*arr)[10]; 一个指针,指向一个数组,数组大小是10个元素; int (*arr)[10] = &arr;
定义一个结构体数组指针。指向3个元素的数组。结构体(id ,age)(代码:day07/04arrPointTest.c)

4.指针数组指针:是一个指针,指向一个数组,数组中存放的是指针。

 int* (*arr)[10];  stu* (*arr)[10]   ;
 自学: 定义一个数组指针,数组中存放的是10个元素的数组指针。

5.二维数组和指针关系

   二维数组名是指针,指向第一行的第一个元素。
   二维数组名加1实际加了一行元素
   二维数组名[下标] 表示某一行的首地址。类型是一维数组,加一实际加了一行。
   二维数组名[行标][列标];某一行行的某一个元素,加一实际加了一个元素的值。
  案例:
 #include<stdio.h>

 typedef struct student
 {
int id;
int age;
  }stu;
int main(int argc,char *argv[])
   {
//定义结构体数组
stu arr[3]={{1,2},{2,3},{3,4}};
  //strcpy 给字符串赋值才用
//定义一个结构体数组指针。
stu (*parr)[3] = &arr;
//如下代码,理解方式如下
//parr = &arr;   *parr = arr =&arr[0]
//**parr=arr[0];
(**parr).id = 123;  //arr[0].id
(*parr)[1].id =  234;//arr[1].id
printf("parr = %p\nparr+1=%p\n",parr,parr+1);//加24,指针加一加的是一个类型大小。

stu doubleArr[2][3] = {0};
parr = doubleArr;
printf("parr        = %p\n",parr);
printf("parr+1      = %p\n",parr+1);
printf("doubleArr   = %p\n",doubleArr);
printf("doubleArr+1 = %p\n",doubleArr+1);
printf("doubleArr[0] = %p\n",&doubleArr[0]);
printf("doubleArr[0] +1 = %p\n",&doubleArr[0]+1);
printf("doubleArr[0][0]+1 = %p\n",&doubleArr[0][0]+1);

printf("doubleArr[1]    = %p\n",&doubleArr[1]);
printf("doubleArr[1][0] = %p\n",&doubleArr[1][0]);

return 0;

}

三、指针和结构体关系

  1.定义结构体 :struct 结构体名{  };
  2.定义结构体指针:struct student* pa;
  3.案例:
  4.使用:通过结构体指针操作结构体中的成员变量,需要用到->
  5.例子:
     #include<stdio.h>
struct student
{
int id;
int age;
char name[10];
};

int main(int argc,char *argv[])
{
struct student danny;
struct student huqing;
struct student* pd = &danny;
danny.id = 123;
pd->age = 12;
//pd.id = 123; 错误
pd=&huaqing;
pd->id = 12;
printf("%d\n",huaqing.id);
printf("%d\n",pd->id);


return 0;

}
  案例:定义一个结构体指针数组,有3个学生信息(int id;int age;char name[10];)请通过scanf输入的方式对结构体数组进行赋值。
     #include<stdio.h>
    #include <stdlib.h>
    typedef struct student{	int id;	int age;	char name[10];}stu,*pstu;
  //这么理解typedef struct student* pstu;
  //这么理解typedef struct student  stu;

  int main(int argc,char *argv[]){
pstu pa[3] = {0};//等价于struct student* pstu
pa[0] = (pstu)malloc(sizeof(stu)*3);
printf("请输入学生信息(id,age,name)");
scanf("%d %d %s",&(pa[0]->id),&(pa[0]->age),pa[0]->name);
printf("%d\t%d\t%s\n",pa[0]->id,pa[0]->age,pa[0]->name);
return 0;
}

四、指针和字符串的关系

1.字符串的保存方式
字符串数组: char arr[10] = “abc”;
字符串指针: char * p = “bac”;
2.字符指针指向的是字符串的首地址,第一个字符的地址
3.相同的字符串常量在内存中只会存储一份,但凡有字母不一样则是不同的字符串。

五、文件操作

1. 文件存在磁盘中,是长期存储的。
 2.使用:一般用于写日志文件,日志是程序运行中的各种信息,当程序出现bug时定位问题的位置。一般日志文件都是.log结束,和txt文件一样。
 3.文件可以长期保存信息,比如passwd文件。
 文件:存储在外部介质上的数据的集合,操作系统管理数据的最小单位。长期存储,不会因为断电而丢失,分为文本文件和二进制文件。
 4.读文件:从磁盘上的文件中读取到计算机内存中
    写文件:从计算机内存中的内容写入到文件中。
 5.文件操作四步骤(文件FILE,和文件操作相关的函数是以f开头)
    1> 打开文件:fopen
     FILE *fopen(const char *path, const char *mode);
     作用:打开文件或者创建文件
     参数: path 需要打开或者创建的文件路径,默认是当前目录下,也是字符串
                mode:打开或者创建的模式,是字符串
     返回值:FILE的指针,文件指针,保存的是文件的基本信息(文件大小等)后续所有的函数操作都需要用到文件指针FILE*
      模式如下:
   r      只读的方式打开文件.文件指针在文件的开始位置,如果文件不存在则打开失败

   r+ 以读写的方式打开文件,指针在文件开始的位置.如果文件不存在则打开失败

   w   以写的方式打开文件,文件的长度初始化成0,所有内容会清空.如果文件不存在则创建.

  w+ 读写的文件打开文件,如果文件存在则清空,不存在则创建
  a      追加(只写)的方式打开文件,文件不存在则创建,光标在文件末尾;

   a+   读写的追加方式打开文件,光标在文件末尾,如果文件不存在则创建,存在不会清空。

       读写文件:fgets fputs fgetc fputs fscanf fprintf fread   fwrite
       文件偏移:ftell  fseek  rewind
       文件关闭:fclose
        int fclose(FILE *stream);          
        作用:关闭文件
        参数:stream是文件指针,是fopen的返回值。

C语言学习第八天

一、文本文件读写

1. int fgetc(FILE *stream);

  作用:从文件中读取一个字符。(内存获取--从文件读出来)
  参数:stream 是fopen的返回值。文件结构体。
  返回值:如果成功获取到的字符的sacii值,如果失败返回EOF 就是-1;
  请把danny.log文件的所有内容全部读取出来。   

2. int fputc(int c, FILE *stream);

   作用:写一个字符到文件中(内存中数据到文件中)
   参数:c 是需要写入文件是字符ascii
             stream 是fopen的返回值
   返回值:如果成功返回写入的字符,失败返回EOF 
   补充: perror是打印错误信息,使用perror(字符串);
              在文件中会有一个全局变量errno,记录的是最后一次的错误信息
               错误信息对应一个字符串,perror会把字符串内容打印。

3. char *fgets(char *s, int size, FILE *stream);

     作用: 从文件中读取一个字符串
      参数:s  缓冲区,用来存放读取到的字符串。
               size 大小,一次性读取的字符个数
               stream :fopen的返回值
    返回值:如果成功返回读取到的字符首地址,如果失败返回NULL
    注意:实际读取到的字符是size-1个,会自动在后面加‘\0’;

4.int fputs(const char *s, FILE *stream);

    作用:写入字符串到文件中
    参数: s  需要写入的字符串首地址
               stream:fopen的返回值
     返回值:如果成功返回实际写入文件的字符个数,失败返回EOF
     注意:写入的时候不会把字符串的'\0'写入到文件中

5. 在文件内部,有一个专门处理光标位置的指针,文件偏移指针

6.int fseek(FILE *stream, long offset, int whence);

      功能:移动文件偏移指针到指定位置, 
      参数: offset:偏移多少字节,负数则往左偏移,整数往右偏移
                  whence:  SEEK_SET 从文件头开始
                                    SEEK_CUR 从当前位置开始
                                    SEEK_END 从文件末尾开始

7. 函数原型:long ftell(FILE *stream);

    功能:返回文件偏移指针位置
    参数:fopen的返回值
    返回值:光标所在位置,文件偏移指针位置。

8.void rewind(FILE *stream);

      作用:把文件光标移动在文件头
      参数:fopen返回值
      返回值:无
 
   练习:请写代码,把abc.log文件复制一份到abc-bak.log中(day08/copyfile.c)

9.int feof(FILE *stream);

    作用:判断文件是否结束
    参数: 文件结构体指针 fopen返回值
    返回值:如果文件结束返回真,如果文件未结束返回假(0)
    注意:错误信息保存在errno,可以用perror打印、

10. size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

     作用:读二进制文件到内存中
     参数: ptr  是缓冲区,用来存放读取的二进制内容,
                size 每一块的大小
               nmemb:读的块数,总共读取几块,总大小是size* nmemb
               stream : 文件的结构体指针,fopen的返回值
      返回值:实际读取到的块个数。小于等于nmemb的值。

11.size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);

        作用:写入二进制到文件
       参数: ptr  是缓冲区,用来存放写入文件的内容,
                  size  写入每一块的大小
                 nmemb:写的块数,总共写入几块,总大小是size* nmemb
                stream : 文件的结构体指针,fopen的返回值
      返回值:实际写入文件的个数。小于等于nmemb的值。

###     12.int fscanf(FILE *stream, const char *format, ...);   (自学内容)
         作用:读取文件内容到内存中
         参数:stream 文件指针 fopen返回值
                   format 格式化处理字符串

13. int fprintf(FILE *stream, const char *format, …); (自学) 例如:fprintf(fp,“%d %d”,a,b);

          作用:写入内容到文件中
          参数:stream 文件指针 fopen返回值
                   format 格式化处理字符串
  
    练习: 在文件中写入3个结构体,结构体中有id age和name,请把读取到的所有name写入到另外一个文件中。把文化a中所有学生信息的名字提取出来放入文件  b中

未完结,持续更新中…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值