zoukankan      html  css  js  c++  java
  • C博客作业05--指针

    这个作业属于哪个班级 C语言--网络2011/2012
    这个作业的地址 C博客作业05--指针
    这个作业的目标 学习指针相关内容
    姓名 吴俊豪

    0. 展示PTA总分

    1. 本章学习总结

    1.1 指针定义、指针相关运算、指针做函数参数

    int fun(int *a);
    int *p;//指针定义
    int n;
    int num[50];
    p = num;
    num[0]=1;
    *(p)++;//指针所指内容自增
    p++;//指针移动到下一位
    n=fun(p);//向函数传入指针的地址
    

    常用的string指针库函数

    函数名 函数格式 作用 备注
    strcpy strcpy(a,b) 把b字符串内容赋给a字符串 可以使用strncpy能自定义赋值的位数
    strcmp strcmp(a,b) 将a串与b串比较 1.a大值为1,b大值为-1,相等值为0. 2.可以使用strncmp自定义比较位数
    strcat strcat(a,b) 把b串从头接到a串末尾 可以使用strncat自定义追加位数
    strstr strstr(a,b) 在a串中找到b串首次出现的地址 不会包含结束符

    更多string库函数请移步C 标准库 - <string.h>

    1.2 字符指针

    1. 定义字符指针:char *p;
    2. 字符指针的内容为字符串,字符数组是一种特殊的字符指针.
    3. 使用printf("%s",p);来输出字符指针的内容.
    4. 使用指针指向字符串,例:p=(str+i);

    1.3 指针做函数返回值

    1. 指针在函数内无返回值时应return NULL;
    2. 指针在不同定义类型的函数内的返回值应切合题意返回,诸如int,double,int *,char *等等

    1.4 动态内存分配

    1. 堆区与栈区
      (1)栈区:存放函数的参数值、局部变量等,由编译器自动分配和释放,效率很高,但是分配的内存量有限.
      (2)堆区:就是通过new、malloc、realloc分配的内存块,编译器不会负责它们的释放工作,需要用程序区释放。分配方式类似于数据结构中的链表。“内存泄漏”通常说的就是堆区.

    2. 使用函数:

    函数名 函数格式 作用 备注
    calloc calloc(n,s) 分配n个大小为s的堆区 返回值类型为void,通常需要进行强转
    malloc malloc(s) 分配一个内存大小为s的堆区 返回值类型为void,通常需要进行强转

    注:申请堆区空间后要记得在使用完之后释放.

    1. 举例多个字符串做动态内存要如何分配
    #include<stdio.h>
    #include<string.h>//函数malloc的库;
    int main()
    {
    char* a;
    char* b;
    a = (char*)malloc(m*sizeof(char));//给a申请m个char单位的空间;
    b = (char*)malloc(n*sizeof(char));//给b申请n个char单位的空间;
    Function(a,b);//使用a,b字符串;
    free(a);
    free(b);//使用完手动释放内存;
    return 0;
    }
    

    1.5 指针数组及其应用

    二维字符数组:一旦定义,那么每个字符串的最大长度、首地址都不能改变了.
    字符指针数组:由于它仅用来存放指针,所以它指向的每个字符串的首地址可以改变,字符串最大长度也可以改变,相较二维字符数组更加灵活.

    1.6 二级指针

    二级指针就是指向指针的指针.

    1.7 行指针、列指针

    (1)行指针:通常写作p+i,取值时为(p+i);
    (2)列指针:通常写作p[0]+i,取值时为
    (p[0]+i);

    2.PTA实验作业

    2.1 藏尾诗

    2.1.1 伪代码

    ch[20][20]//用于存放诗句
    d[20]//用于存放尾巴
    i<-0
    j<-0
    while i<4
          do scanf ch[i]
          d[j] <- *(ch[i] + strlen(ch[i]) - 2)
          d[j+1] <- *(ch[i] + strlen(ch[i]) - 1)//一个汉字占两个字节
          j+=2
          i++
    end while
    d[j]<-0//添加结束符
    printf d
    

    2.1.2 代码截图

    2.1.3 代码比较

    同学的代码:

    #include <stdio.h>  
    #include <stdlib.h>  
    #include "math.h"  
    #include "string.h"  
      
    int main()  
    {  
       char *p[4],str[20];  
       int i;  
       for(i=0;i<=3;i++){  
           fgets(str,19,stdin);
           p[i]=(char *)malloc(sizeof(str)+1);  
           strcpy(p[i],str);  
      
       }  
      
       int n;  
      
       for(i=0;i<=3;i++){  
          n=strlen(p[i])-1;  
          printf("%s",p[i]+n-2);  
       }  
      free(p);
       return 0;  
    }  
    

    两份代码最大的区别在于同学使用了动态内存申请,我则选用二维字符数组,相较之下同学的代码可以适应更加极端的情况(诗句数量特别多时).

    2.2 合并2个有序数组

    裁判测试程序:

    #include <stdio.h>
    #include <stdlib.h>
    
    void printArray(int* arr, int arr_size);  /* 打印数组,细节不表 */
    void merge(int* a, int m, int* b, int n); /* 合并a和b到a */
    
    int main(int argc, char const *argv[])
    {
        int m, n, i;
        int *a, *b;
    
        scanf("%d %d", &m, &n);
        a = (int*)malloc((m + n) * sizeof(int));
        for (i = 0; i < m; i++) {
            scanf("%d", &a[i]);
        }
    
        b = (int*)malloc(n * sizeof(int));
        for (i = 0; i < n; i++) {
            scanf("%d", &b[i]);
        }
        merge(a, m, b, n);
        printArray(a, m + n);
    
        free(a); free(b);
        return 0;
    }
    

    2.2.1 伪代码

    void merge(int* a, int m, int* b, int n)
    static hash[100001]
    i,j
    for i=0 to m
        hash[a[i]]++
    end for    
    for i=0 to n
        hash[a[i]]++
    end for  
    for i=0 to 100001
        for j=0 to hash[i]
            *a = i;
            a++
        end for
    end for
    

    2.2.2 代码截图

    2.2.3 代码比较

    同学代码:

    void merge(int* a, int m, int* b, int n, int* c)
    {
        int i=0,j=0,k=0;
        while(i<m&&j<n)
        {
            if(*a>=*b)
            {
                c[k]=*b;
                b++;j++;k++;
            }
            else
            {
                c[k]=*a;
                a++;i++;k++;
            }
        }
        if(i<m)
        {
            while(k<=m+n-1)
            {
                c[k]=*a;
                a++;
                k++;
            }
        }
        if(j<n)
        {
            while(k<=n+m-1)
            {
                c[k]=*b;
                b++;
                k++;
            }
        }
        for(i=0;i<m+n;i++)
        {
             a[i]=c[i];
        }
    }
    

    两份代码几乎就是两个不同的思路,同学是先将a,b数组按次序存入c数组,然后再把c数组的内容赋给a数组;我则是使用一个新数组将a,b中出现的数字在数组hash内计次,最后把hash内的数组下标赋值给a数组.

    2.3 说反话-加强版

    2.3.1 伪代码

    ch[500100]
    flag<-0
    fgets ch
    int *endp -> ch
    while *endp != '' && *endp != '
    '
          do endp++
    end while/*把指针移动到最后*/
    while p != ch /*循环至字符串开头*/
          do if *p != '.'
                   then len++
                   用flag控制空格并输出p
                   len<-0
              end if
          p--
    end while
    if *ch!=' '
        then 用flag控制空格并输出p
    return 0
    

    2.3.2 代码截图


    2.3.3 与超星视频的区别

    我的代码是基于超星视频的思路编写的,所以除了一些小细节外几乎没有太大的区别.

  • 相关阅读:
    kernel pwn 入门环境搭建
    linux下sh脚本/bin/bash^M问题解决
    Linux下的C#连接Mysql数据库
    使用docker Hub
    使用ajax+php+mysql实现数据库定时刷新
    docker 安装LAMP环境
    解决Mysql错误:ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111)
    php实现socket简单的例子
    一次mysql调优过程
    一次mysql主从同步问题及解决过程
  • 原文地址:https://www.cnblogs.com/konjac-wjh/p/14194040.html
Copyright © 2011-2022 走看看