<25>【掌握】fget()、fputs()函数使用/优缺点+【了解】const关键字介绍及作用+【理解】内存管理的概念和内存分区(没有整理记忆)+【掌握】常见的内存分配函数+【掌握】野指针和内存泄露+【了解】8-指针函数概念及定义+【应用】09-输出星期,取最大值

【掌握】02- fget()、fputs()函数使用

【了解】03-fgets()和fputs()优缺点

 

(一)

 1、fgets()

 

        该函数一个文件操作相关的函数

 

        暂时使用这个函数可以从键盘商接收一个字符串,保存到数组中

 

   原来接收字符串保存到数组中的方法

   

      char str[50];

 

     1) scanf("%s",str);  //缺点:不能接收空格

 

     2) gets(str);        //优点:可以接收空格

                           //会有一个警告,不安全的

                           //不安全:比如数组长度是50,如果我们输入的

                           //的长度正好是50个,此时把50个字符全部存到

                           //数组中,存在问题 因为没有空间存放字符串结束符

  

    fgets()是一个安全的字符串接收的函数

 

      char ch[5];  //如果使用fgets此时数组中最多存放4个可见字符

                   //会自动的把数组的最后一个元素存放\0

 fgets()使用格式:

 

          fgets(数组名,数组长度,stdin);

 

 

    fputs();也是一个文件操作相关的函数

    格式:

 

       fputs(数组名,stdout);

 

 

 1 #include <stdio.h>

 2 #include <string.h>

 3 

 4 int main(int argc, const char * argv[]) {

 5     

 6      char ch[5];

 7     //fgets从输入缓冲区读取一个字符串保存到字符数组中

 8     //当输入的字符串的长度大于数组的长度,此时fgets会自动的                                 

 9     //把数组的最后一个元素变成\0

10     //当输入的字符串的长度小于数组长度的时候,fgets还会接收回车

11   

12     fgets(ch, sizeof(ch), stdin);

13 

14     printf("---%s\n",ch);

15    

19     return 0;

20 }
fdsgdssafadg

---fdsg
ds

---ds
//此处有一换行

 

(二)

 1 #include <stdio.h>

 2 #include <string.h>

 3 

 4 int main(int argc, const char * argv[]) {

 5     

 6      char ch[5];

 7     //fgets从输入缓冲区读取一个字符串保存到字符数组中

 8     //当输入的字符串的长度大于数组的长度,此时fgets会自动的

 9     //把数组的最后一个元素变成\0

10     //当输入的字符串的长度小于数组长度的时候,fgets还会接收回车

11   

12     fgets(ch, sizeof(ch), stdin);

13 

14    // printf("---%s\n",ch);

15    

16    

17     //\n  它的ascii码值10

18    for (int i=0; i<5; i++) {

19     

20        printf("%d\t",ch[i]);

21     }

22     

23     return 0;

24 }
sss

115    115    115    10    0    //由此可以看出回车(就是\n)的ascii码值是10

 

(三)

#include <stdio.h>

#include <string.h>



int main(int argc, const char * argv[]) {

    

     char ch[5];

    //fgets从输入缓冲区读取一个字符串保存到字符数组中

    //当输入的字符串的长度大于数组的长度,此时fgets会自动的

    //把数组的最后一个元素变成\0

    //当输入的字符串的长度小于数组长度的时候,fgets还会接收回车

  

    fgets(ch, sizeof(ch), stdin);

  

     //去掉多余的\n

   if(ch[strlen(ch)-1]=='\n')

      ch[strlen(ch)-1]='\0';

    

    printf("---%s\n",ch);



  

    return 0;

}
ss

---ss
//现在没有空行了

 (三)

#include <stdio.h>

#include <string.h>



int main(int argc, const char * argv[]) {

    

     char ch[5];



     fgets(ch, sizeof(ch), stdin);



        //fputs是不会自动换行

        //fputs也不能进行格式化的输出

        //puts 可以自动换行

     fputs(ch, stdout);

   

    return 0;

}
saad

saad

 

【了解】4-const关键字介绍及优点

 (一)

  const使用的地方

 

 

    1)修饰变量

 

    2)修饰指针变量

 

    3)修饰数组

 

 
#include <stdio.h>

/**

 *  const修饰变量,使得变量变成常量

 */

void test1(){



    //使用const修饰变量a

    const int a = 10;

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

    

    //a = 200;//read-only        //报错了,不能再次这样赋值了

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



}

/**

 *  用指针强制修改const常量

 */

void test2(){





    //使用const修饰变量a

    const int a = 10;

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

    

    

    int *p = &a;  //

    *p = 100;     //强制修饰常量     这种修改的方式是无解的,因为内存地址都是一样的,但值的确修改了,就知道能这样改,不必深究 

    

    printf("%d,%d\n",a,*p);   // 10,100 

}



int main(int argc, const char * argv[]) {

    

    test1();

    test2();

  

    return 0;

}

(二)

#include <stdio.h>

int main(int argc, const char * argv[]) {



    

    int a = 10;

    int b = 20;

    

    //定义个指针变量,p指向a

    //此处的const的作用是指针变量p的指向可以改变,但是指向的变量的值

    //不能改变的

    

    //1、const修饰的指针变量指向可变,指向的变量的值不可变

    const int *p = &a; //给p初始化

               p = &b;  //重新修改了p的指向

    //*p = 1000;     再重新赋值就报错来

    

    int const *p1 = &a;

               p1 = p;  //p1的指向也是可以改变

//    *p1 = 100;  p1指向的变量的值是不能改变的

    

    //2、const修饰的指针变量,指针变量指向的变量值可以变,指向不能变

    

    int * const p2 = &a;

    *p2 = 2000; //值可以改变

    //p2  = &b;  //p2的指向不能变

    

    //3、const修饰的指针变量的指向和值,都不能改变

      const int * const p3 = &a;

//     p3  = &b;   //只想不能变

//    *p3 = 100;  //指向的变量的值也不能变

    

    

    /*

     

     记忆技巧:

     

        看 const 和 * 的位置

     

        如果 const 在 * 的左侧  表示指针变量指向的变量的值不能变,但是指向可以改变

     

        如果 const 在 * 的右侧  表示指针变量指向的变量的值可以改变,但是指向不可以改变

     

        如果 const 出现在 *的两侧,表示指针变量的指向和值都不能改变

     

     

     */

    

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



    

    return 0;

}

 

【理解】5-内存管理的概念和内存分区

 

【掌握】6-常见的内存分配函数

 

 C语言中提供了3个动态内存分配函数:

 

    1malloc 函数

 

      格式: void * malloc(unsigned size);

 

      从内存的堆区分配大小为size个字节的连续的内存空间

      如果内存分配成功  返回内存的首地址

 

                失败  NULL
2)
callloc

3)realloc
 
  
#include <stdio.h>

#include <stdlib.h>

/**

 *  malloc函数的使用

 */

void test1(){



    //从内存中申请一块内存空间,可以存储4个整数

    // = 赋值,要求等号的左右两侧的类型要一致

    //p中存放的事新申请的内存空间的首地址

    //注意:malloc 申请的内存空间,如果我们不赋值?

    //     是垃圾数

    int *p = (int *)malloc(4*sizeof(int));   //16个字节

    

    //使用一个函数给malloc申请的空间进行初始化

    //  memset(p,'a',16);

    

    if (p!=NULL) {

        

        //申请成功做的事情

               *p = 10;

               *(p+1) = 100;

               *(p+2) = 1000;

               *(p+3) = 10000;   //存放4个整数

        

    }else{

        //内存申请失败

        printf("内存申请失败!\n");

        

    }

    

    for(int i=0;i<4 ;i++){

        

        printf("%d\t",*(p+i));

        

    }



}





int main(int argc, const char * argv[]) {

      

         test1();

 

         return 0;

}
10    100    1000    10000    

(二)

void test1(){



    //从内存中申请一块内存空间,可以存储4个整数

    // = 赋值,要求等号的左右两侧的类型要一致

    //p中存放的事新申请的内存空间的首地址

    //注意:malloc 申请的内存空间,如果我们不赋值?

    //     是垃圾数

    int *p = (int *)malloc(4*sizeof(int));   //16个字节

    

    //使用一个函数给malloc申请的空间进行初始化

    memset(p,'a',16);

    //(空间,内容,空间大小)赋值内容的目的是空间里不是一个随机数,好像存的只能是字母,或者数字 对应的阿斯克吗

 

    for(int i=0;i<4 ;i++){

        

        printf("%c\t",*(p+i));

        

    }



}







int main(int argc, const char * argv[]) {

    

    

    test1();



    return 0;

}
a    a    a    a    
1667457891    1667457891    1667457891    1667457891      //改成99,下面是%d
c    c    c    c                          //改成99 ,下面改成%c

(三)

#include <stdio.h>

#include <stdlib.h>

void test2(){
//callloc 分配指定块数和长度的内存空间 //格式:calloc(块数,长度) //分配了4块,每一块内存长度为4的内存空间 //他们的地址也是连续的 //注意事项: //calloc 它使可以帮我们自动的初始化为0 int *p = (int *)calloc(4, sizeof(int)); //16个字节 if (p!=NULL) { //申请成功做的事情 *p = 10; *(p+1) = 100; *(p+2) = 1000; *(p+3) = 10000; //存放4个整数 }else{ //内存申请失败 printf("内存申请失败!\n"); } for(int i=0;i<4 ;i++){ printf("%d\t",*(p+i)); } } int main(int argc, const char * argv[]) { test2(); return 0; }
10    100    1000    10000    

(四)

#include <stdio.h>

#include <stdlib.h>

int main(int argc, const char * argv[]) {

    

  

    int *p = (int *)malloc(4*sizeof(int));   //16个字节

   

    printf("old %p\n",p);

    

    //realloc 函数可以给已经存在的空间扩充大小(如果扩充的空间被其他函数占据,也可能另辟一个空间,将原来空间的数据自动复制过去)

   

    p = realloc(p, 40*sizeof(int));

   

    printf("new %p\n",p);

    //40个内存空间

    if (p!=NULL) {

        

        //申请成功做的事情

        *p = 10;

        *(p+1) = 100;

        *(p+2) = 1000;

        *(p+3) = 10000;   //存放4个整数

        

        *(p+39)= 1;

        printf("%d\n",*(p+39));

        

    }else{

        //内存申请失败

        printf("内存申请失败!\n"); 

    }

    

    for(int i=0;i<4 ;i++){

    

        printf("%d\t",*(p+i));    

    }  

    return 0;

}
old 0x1003031a0

new 0x1003031a0                        //这里说明老空间下面的空间并未被其他函数占据

1

10    100    1000    10000    

 

【掌握】07-野指针和内存泄露

 

 1)野指针:所指空间已经释放 ,所谓释放就是其他函数一旦调用到这块内存,这块内存的值就改变而不受保护

2)内存泄露:空间占据内存没有释放, 但没有指针指着

解决方法:在指针p释放之前,先释放堆区中的内存空间

 

内存泄漏也称作“存储渗漏”,用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏。



内存泄漏形象的比喻是“操作系统可提供给所有进程的存储空间正在被某个进程榨干”,最终结果是程序运行时间越长,占用存储空间越来越多,最终用尽全部存储空间,整个系统崩溃。所以“内存泄漏”是从操作系统的角度来看的。
这里的存储空间并不是指物理内存,而是指虚拟内存大小,这个虚拟内存大小取决于磁盘交换区设定的大小。由程序申请的一块内存,如果没有任何一个指针指向它,那么这块内存就泄漏了。

(一)

#include <stdio.h>

#include <stdlib.h>



int main(int argc, const char * argv[]) {

  

    int *p = (int *)malloc(4*sizeof(int));   //16个字节



    if (p!=NULL) {

        

        //申请成功做的事情

        *p = 10;

        *(p+1) = 100;

        *(p+2) = 1000;

        *(p+3) = 10000;   //存放4个整数

        

        

    }else{

        //内存申请失败

        printf("内存申请失败!\n");

        

    }

    

    

    //应该使用free()函数释放内存空间

    //free(要释放的空间的首地址)

    free(p);

    //free(p)以后,p是一个野指针

    //p = NULL;   // 在没有这句话的时候,被释放的内存并没有其他函数去占用,所以还遗留了以前的数据

    

    

    printf("%d\n",*p);

    

    return 0;

}
10

 

(二)

#include <stdio.h>

#include <stdlib.h>



//分配指定大小的内存空间

int * mall(int n){



    return (int *)malloc(n);



}





int main(int argc, const char * argv[]) {

   

      int *x = mall(4);

    //释放函数中分配的内存

      free(x);

    

    

   //for (int i=0; i<1000000; i++) {

   //     造成严重的内存泄露

   //         mall(100);

   //   }

   

    return 0;

}

 

 

【了解】08-指针函数概念及定义

   指针函数:

 

      返回值是指针的函数

 

   指针函数的定义

 

      指针类型 * 函数名(){

 

 

          return 地址;

      }

 

 

(一)

#include <stdio.h>



//返回的事两个数中大数的地址

//返回的是形参x和 y的中大数的地址

int* max(int x,int y){



    printf("行参max x = %p\n",&x);

    printf("行参max y = %p\n",&y);

    return x>y?&x:&y;



}



int main(int argc, const char * argv[]) {

    

    //返回a 、b两个数中大数的地址

    int a = 3,b = 4;

    printf("a = %p\n",&a);

    printf("b = %p\n",&b);

    int *p =max(a,b);

    printf("p = %p\n",p);

    

    

    return 0;

}
a = 0x7fff5fbff72c

b = 0x7fff5fbff728

行参max x = 0x7fff5fbff6fc

行参max y = 0x7fff5fbff6f8            //清楚地看到实数和行参的地址是不一样的 ,证实了调用函数的时候行参变量是新分配的空间,实参和行参只是值传递

p = 0x7fff5fbff6f8

(二)

#include <stdio.h>



int *max2(int *x,int *y){

    printf("max x = %p\n",x);

    printf("max y = %p\n",y);

    return *x>*y ?x :y;



}



int main(int argc, const char * argv[]) {

    

    //返回a 、b两个数中大数的地址

    int a = 3,b = 4;

    printf("a = %p\n",&a);

    printf("b = %p\n",&b);

    int *p =max2(&a,&b);

    printf("p = %p\n",p);   

    return 0;

}
a = 0x7fff5fbff72c

b = 0x7fff5fbff728

max x = 0x7fff5fbff72c

max y = 0x7fff5fbff728

p = 0x7fff5fbff728
                              //清楚地看到实数和行参的地址是一样的 ,证实了调用函数的时候行参变量不是新分配的空间,实参和行参是地址传递
 
  

【应用】09-输出星期

需求:

     1)  通过指针函数,输入一个1~7之间的整数,输出对应的星期名。
2) 通过指针寻找给定数组中的最大值

 

#include <stdio.h>

#include <stdlib.h>
char * getDay(int n){ //这是定义一个字符串指针数组 char *days[]={ "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日", }; return n<8&&n>0 ? days[n-1]:"输入错误!"; } int getMax(int *p,int len){ //假设max是第一个元素 int max=*p; for (int i=1; i<len; i++) { //找出最大值 if (*(p+i)>max) { //找到最大值后,把最大值赋值给max max = *(p+i); } } return max; } int main(int argc, const char * argv[]) { printf("%s\n",getDay(1)); int a[10]={123,45,22,111,34,56,888,11,45,109}; int m = getMax(a,10); printf("m = %d\n",m); return 0; }
星期一

m = 888

 

你可能感兴趣的:(Const)