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

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

    0.展示PTA总分(0----2)

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

    1.1.1 资料查询

    通常,管理大量数据的有效方法不是直接处理数据本身,而是使用指向数据的指针。例如,如果需要对大量的大型记录进行排序,对指向该记录的指针列表进行排序效率要比直接对记录排序高得多,因为这样无需在内存中移动数据。

    1.1.2 指针定义

    C语言中,指针类型描述的是一个地址,这个地址指向内存中另外一个对象的位置。简单地说,指针表示的是它所指向对象的地址。

    • 定义:变量类型*变量名(char * ch;)
    • 其中变量名(ch)的值为指针地址,变量名(ch)才为指针地址中包含的值。
    • 定义多个指针变量时,每个指针变量前都必须加上*。

    1.1.3 指针相关运算

    • 指针的运算优先级与正常变量不同就如ch++ !=(ch)++,前一个为地址自增,后一个为内容自增。写代码时要注意指针运算的优先级。
    • *表示取值的运算符,运算对象是地址; 运算的值是内容。
    • &表示取地址的运算符,运算对象是内容; 运算的值是地址。
    • ch=0 和 ch=NULL表示指向空地址。

    1.1.4 指针做函数参数

    void dete1(char *p,char *q)
    {
       p=strstr(p,q);
       while(*(p+l)!=''){
       	*p=*(p+l);
       	*p++;
       }
       *p=*(p+l);
       return ;
    }
    

    其中传入的为指针的地址,在函数中运算时直接在地址中更改,在需要输出数组时更加简便,运算的速度更快。

    1.2 字符指针

    1.2.1 字符指针

    • 定义:指向字符型数据的指针变量。每个字符串在内存中都占用一段连续的存储空间,并有唯一确定的首地址。即将字符串的首地址赋值给字符指针,可让字符指针指向一个字符串。
    • 例:
    char ch[]="hahahaha";
    char *ch1=ch;
    

    1.2.2 字符串相关函数及函数代码原型的理解

    • strcat( str1, str2) (连接str2到str1后面)
    char *strcat( char *str1, const char *str2 )
    {
    	char *tempstr;
    	tempstr=str1;
    	if(!str1||!str2) return NULL;//防止空指针传入。否则程序奔溃。
    	while(*str1)  str1++;
    	while(*str2) {
    		*str1=*str2;
    		str1++;str2++;
    	}
    	*str1=''; 
    	return tempstr;  //连接后字符串的的首地址。
    }
    

    定义局部变量tempstr来保存首地址,然后对str1和str2直接操作,通过指针将str2接到str1后面。

    • strcpy(strDest, strSrc) (将strSrc复制到strDest)
    char *strcpy(char *strDest, const char *strSrc)  
    {  
       assert((strDest != NULL) && (strSrc!= NULL)); 
        if (strDest == strSrc)  
            return strDest;  
        char *tempDest = strDest;  //保存首地址    
        while((*strDest++ = *strSrc++) != '');  //??
        *strDest=0;
        return tempDest;  
    } 
    
    • strcmp(用于比较两个字符串)
    #include "assert.h"  
    int strcmp(const char *str1,const char *str2)  
    {    int len = 0;  
         assert((str1!= NULL) && (str2 != NULL)); 
        while(*str1 && *str2 && (*str1==*str2))  
        {  
            str1++;  
            str2++;  
        }  
        if((*str1-*str2)>0)     
            return 1;  
        else if((*str1-*str2)<0)  
            return -1;  
        else  
            return 0;  
    } 
    

    对于大于等于小于三种情况分别输出1/0/-1。

    1.2.3 字符串相关函数用法

    <string.h>

    • strpbrk(str1,str2)
      char *strpbrk(const char *str1, const char *str2)
      检索字符串 str1 中第一个匹配字符串str2 中字符的字符

    • strrchr()
      char *strrchr(const char *str, int c)
      参数 str 所指向的字符串中搜索最后一次出现字符 c的位置。

    • strstr()
      char *strstr(const char *haystack, const char *needle)
      字符串 haystack 中查找第一次出现字符串 needle 的位置
      <ctype.h>

    • islower():如果 c 有相对应的小写字母,则该函数返回 c 的小写字母,否则 c 保持不变。

    • toupper():如果 c 有相对应的大写字母,则该函数返回 c 的大写字母,否则 c 保持不变。

    • isdigit():判断c是否是数字字符。

    <stdlib.h>

    • atoi():该函数返回转换后的长整数,如果没有执行有效的转换,则返回零

    1.3 指针做函数返回值

    • C语言允许函数的返回值是一个指针(地址),我们将这样的函数称为指针函数。
    • 用指针作为函数返回值时需要注意的一点是,函数运行结束后会销毁在它内部定义的所有局部数据,包括局部变量、局部数组和形式参数,函数返回的指针请尽量不要指向这些数据,C语言没有任何机制来保证这些数据会一直有效,它们在后续使用过程中可能会引发运行时错误。
    • 例:
        #include <stdio.h>
        #include <string.h>
        char *strlong(char *str1, char *str2){
            if(strlen(str1) >= strlen(str2)){
                return str1;
            }else{
                return str2;
            }
        }
        int main(){
            char str1[30], str2[30], *str;
            gets(str1);
            gets(str2);
            str = strlong(str1, str2);
            printf("Longer string: %s
    ", str);
            return 0;
        }
    

    1.4 动态内存分配

    • 指针是存储内存地址的变量。当我们声明了一个指针变量后,使用该指针时系统会根据指针内的地址索引内存块,读取内存内的值。指针因为是用来存地址的,所以一般固定长度为4个字节。void指针指向内存块的指针。
    • eg:
    p=(int *)calloc(n,sizeof(int)))==NULL
    
    • 动态存储分配函数malloc( )
      void *malloc(unsigned size)
      再内存的动态存储中分配一连续空间,长度为size。申请成功,返回指向所分配内存空间的
      的起始地址的指针;否则返回NULL;
    • 计数动态存储分配函数calloc( )
      void *calloc(unsigned n,unsigned size)
      在内存的动态存储区中分配n个连续空间,每一存储空间的而长度为size,并且分配后还把存储块
      里全部初始化为0。申请成功,返回指向所分配内存空间的的起始地址的指针;否则返回NULL;
    • 动态存储释放函数free()
      viod free(void *ptr)
      盛放动态存储分配函数申请到的整块内存空间,ptr为指向要释放空间的首地址。
      释放后不允许再通过该指针去访问已经释放的块。
    • 分配调整函数realloc()
      void *realloc(void *ptr,unsigned size)
      更改以前的存储分配。ptr必须是以前通过动态存储分配得到的指针。参数size为现在
      需要的空间大小。分配失败,返回NULL;分配成功,返回一片能存放大小为siza的区块。

    1.5 指针数组及其应用

    在实现排序功能的时候,一般都是通过交换值的形式,通过循环逐渐得到我们想要的顺序。但是有时候排序通过值的交换实现起来比较麻烦,因此我们可以引用指针数组,通过交换地址的方式来得到我们想要的顺序。
    例:

    char a[4][10]={"CHINA","china","ABC","abcdef"}; // 将四个字符串通过从小到大的顺序依次排序,如果用交换值的形式,实现起来就会比较麻烦。但是通过指针数组实现起来就很容易。
    char  *b[4]={a[0],a[1],a[2],a[3]};  // 定义一个指针数组分别依次指向字符数组
    

    1.6 二级指针

    • 指针可以指向一份普通类型的数据,例如 int、double、char 等,也可以指向一份指针类型的数据,例如 int *、double *、char * 等。如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针。假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量.
    • eg:
    int a =100;
    int *p1 = &a;
    int **p2 = &p1;
    

    1.7 行指针、列指针

    • 行指针
      常用的二维数组,如:
    int a[3][5];
    

    行指针是指向数组的指针,即上面几种指针类型中的 int (*a)[5];所以,当二维数组要被当做参数进行传递时

    void funcByRowPtr(int (*p)[5],const int row);
    //或
    void funcByRowPtr(int p[][5],const int row);
    
    写法 解释 指针类型
    a+0或&a[0] 指向第1个一维数组的地址(指向第1行) 行指针
    a+1或&a[1] 指向第2个一维数组的地址(指向第2行) 行指针
    a+2或&a[2] 指向第3个一维数组的地址(指向第3行) 行指针
    • 列指针
    写法 解释 指针类型
    a[0]+0或&a[0][0] 指向第1行第1列的地址 列指针
    a[0]+1或&a[0][1] 指向第1行第2列的地址 列指针
    a[1]+0或&a[1][0] 指向第2行第1列的地址 列指针
    a[1]+1或&a[1][1] 指向第2行第2列的地址 列指针

    所以如果用列指针进行函数传参,可以直接声明如下:
    void funcByColPtr(int * const colPtr,const int row,const int col);

    • 综上所述:对行指针解引用,可以得到列指针,对列指针解引用,可以得到具体的元素值:
      但是这并不表示行指针可以作为二级指针进行函数传参.

    2.PTA实验作业(7分)

    2.1 二分法查找(2分)

    2.1.1 伪代码

    设置下表常量max,min
    while(min<=max)//判断min和max是否重合
    {
          count的值自增;
          取中间数下标;
          判断输入值的大小;
          如果等于则return该下表;
    }
    return 非正数(-1)//不能有与下标重合的可能
    

    2.1.2 代码截图


    2.1.3 找一份同学代码(尽量找思路和自己差距较大同学代码)比较,说明各自代码特点。

    都差不多。。。。。

    2.2 合并2个有序数组(2分)

    2.2.1 伪代码

    定义动态指针p;
    do
    {
          if((n && *(a + i) > *(b + j)) || m == 0)//判断数组中某一元素的大小
          {
                *(p + i + j) = *(b + j);//将对应b的值赋给p
                j++;
                if (j == n)//找到a中比b中的数并将a中那几个数输入p中
                {
                    for (; i + j < m + n; i++)//
                    {
                        *(p + i + j) = *(a + i);
                    }
                }
            }
            else//同上
            {
                *(p + i + j) = *(a + i);
                i++;
                if(i == m)
                {
                    for (; i + j < m + n; j++)
                    {
                        *(p + i + j) = *(b + j);
                    }
                }
            }
        } while (i + j < m + n);//当所有数都输入完成时离开
    }
    将p中的数赋给a;
    

    2.2.2 代码截图



    2.2.3 找一份同学代码(尽量找思路和自己差距较大同学代码)比较,说明各自代码特点。

    智康的代码:

    我的代码是将啊a和b输入到另一个数组中,智康是从后往前输入,避免了数据的冲突,减少使用了一个指针有利于代码运算速度的提高

    2.3 说反话-加强(3分)

    2.3.1 伪代码

          for重最后一个往前数
          {
                do if 不为‘ ’;
                记录下标i;
                for向前遍历
                if遇到空格离开
                break;
           head=j+i;指向下一单词首字母
           if 如果不是输出第一个单词,即原字符串最后一个单词,要输出一个相隔的空格
           for(k=head; k<=real; k++)//从该单词的开头字符逐个输出到末尾字符
           count++;
           从遇到的空格那个位置开始,继续向前查询
          } 
          return 0;
    

    2.3.2 代码截图



    2.3.3 请说明和超星视频做法区别,各自优缺点。

    在超星视频中使用了printf("%.*s,len,p")从len开始输出的输出方法。
    视频中是在判断是否为最后一个数分两种情况输出,而我自己是对空格分开判断是否需要输出空格,我自己的方法优点是不需要再对第一个单词再次进行判断,而超星中的代码可以减少很多代码量。

  • 相关阅读:
    UVA 562 Dividing coins --01背包的变形
    HDU 2602 Bone Collector --01背包
    Topcoder SRM 618 Div2 --900
    【转】Python 列表排序
    线段树之区间最大连续和问题
    【转】Python中string的strip,lstrip,rstrip用法
    《Python核心编程》部分代码习题实践(持续更新)
    《Python核心编程》部分错误纠正(勘误表)(持续更新)
    UVA 103 Stacking Boxes --LIS
    POJ 1836 Alignment --LIS&LDS
  • 原文地址:https://www.cnblogs.com/WangBo020809/p/14198441.html
Copyright © 2011-2022 走看看