C博客作业05-指针

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

0. 展示PTA总分

1. 本章学习总结

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

1) 指针定义

  • 指针是变量,如果在程序中声明一个变量并使用地址作为该变量的值,那么这个变量就是指针变量。但是指针的字节长度是固定的,因为指针保存的是地址,由操作系统的位数决定,32位机的字节是4,64位机的字节是8。
  • 定义多个指针变量的时候,每一个指针变量前面都必须加上 *。

2)指针相关运算

  • 取地址运算和间接访问运算
    例如:
int *p,a=3;
p=&a;//间接访问
  • 指针变量初始化
    如:
int a;
int *p1=&a;//此处**\***只表示该变量是指针变量,它不是间接访问符
int *p2=p1;
  • 指针自增(减)
int *p;
int a[10];
*p=&a;//p取数组首地址
p++;//表示p取数组下一个地址

3)指针做函数参数

  • 如果将某个变量的地址作为函数的实参,相应的形参就是指针。
    例如:
void Print(int *p);
int main(){
      int *p;
      int a=23;
      p=&a;
      Print(*p);
      }

1.2 字符指针

  • 如果定义一个字符指针接收字符串常量的值,该指针就是指向字符串的首字符。即字符指针。

例如:

char a[]="array";
char *p="point";
printf("%s",a);
printf("%s",p);
printf("%s\n","string");
printf("%s",a+2);
printf("%s",p+3);
printf("%s","string"+1);
//输出结果为:array point string
ray nt tring

1.3 指针做函数返回值

  • C语言允许函数的返回值是一个指针(地址),我们将这样的函数称为指针函数。
    例:
#include <stdio.h>
#define MAXS 30

char *search(char *s, char *t);
void ReadString( char s[] ); /* 裁判提供,细节不表 */

int main()
{
    char s[MAXS], t[MAXS], *pos;

    ReadString(s);
    ReadString(t);
    pos = search(s, t);
    if ( pos != NULL )
        printf("%d\n", pos - s);
    else
        printf("-1\n");

    return 0;
}

/* 你的代码将被嵌在这里 */

1.4 动态内存分配

  • 动态内存是相对静态内存而言的。所谓动态和静态就是指内存的分配方式。动态内存是指在堆上分配的内存,而静态内存是指在栈上分配的内存。

  • 以前所写的程序大多数都是在栈上分配的,比如局部变量、形参、函数调用等。栈上分配的内存是由系统分配和释放的,空间有限,在复合语句或函数运行结束后就会被系统自动释放。而堆上分配的内存是由程序员通过编程自己手动分配和释放的,空间很大,存储自由。

动态内存分配相关做法
1) malloc函数
其函数原型为
void malloc(unsigned int size);
其作用是在内存的动态存储区中分配一个长度为size的连续空间。此函数的返回值是分配区域的起始地址,或者说,此函数是一个指针型函数,返回的指针指向该分配域的开头位置。如:
malloc(100);/
开辟 100 个字节的临时分配域,返回值为其第一个字节的地址*/
注意指针的基类型为 void,即不指向任何类型的数据,只提供一个地址。如果此函数未能成功的执行(例如内存空间不足),则返回空指针(NULL)。

2)calloc函数
函数原型为
void calloc(unsigned n, unsigned size);
其作用是在内存的动态存储区中分配n个长度为 size 的连续空间。函数返回一个指向分配区域的起始位置的指针;如果分配不成功,则返回NULL。
采用 calloc 函数可以为一维数组开辟动态存储空间,n 为数组元素个数,每个元素长度为 size,这就是动态数组。如:
p = calloc(50,4) ,即 开辟 50
4个字节的临时分配域,把起始地址赋给指针变量p

俩者区别:
调用calloc函数时,自动初始化该内存空间为零,而调用malloc时则不初始化,里面的数据是随机的垃圾数据。

3) free函数
free 函数
函数原型为
void free(void*p);
其作用是释放指针 p 所指向的动态空间,使这部分空间能被其他变量使用。

1.5 指针数组及其应用

  • 多个字符串用二维数组或指针数组表示
    例如:
    定义
    int a[3][4];
    其中,a 是二维数组名
    a[0] 表示的就是元素 a[0][0] 的地址,即 a[0]&a[0][0];a[1] 表示的就是元素 a[1][0] 的地址,即 a[1]&a[1][0];
    则a[0]+1 就表示元素 a[0][1] 的地址,a[0]+2 就表示元素 a[0][2] 的地址,a[1]+1 就表示元素 a[1][1] 的地址;
    故a[i]+j == &a[i][j] &a[i][0]+j == &a[i][j] *(a+i)+j == &a[i][j]

1.6 二级指针

  • A(即B的地址)是指向指针的指针,称为二级指针,用于存放二级指针的变量称为二级指针变量.根据B的不同情况,二级指针又分为指向指针变量的指针和指向数组的指针。
    简单来说就是存储一级指针地址的地址。

1.7 行指针、列指针

定义:
在一个二维数组中每一行的首地址可以称为行指针,注意:第一行的首地址,是指首行一整行,并不是指某个具体元素。
如a[4][4]中a+0;a+1;a+2;等等都是“行指针”。

而第一个元素的地址,也就是a[0]+0。a[0]和a[0]+0都是指具体的元素。
对于这种,我们称之为“列指针”。

由上面的比较可以得出:

行指针:指向某一行,不指向具体的元素。

列指针:指向行中具体的元素

用途:
对于元素a[1][2],其地址用列指针表示为a[1]+2,等价表示为(a+1)+2,那么内容是(*(a+1)+2);

2.PTA实验作业

2.1藏尾诗

2.11 伪代码

char *poem[诗行数];
每一行诗的长度for(i=0;i<诗行数;i++){
                  len[i]=strlen(*(poem+i));
                  }

	for (i = 0; i < 诗行数; i++) {
		printf("%s", (*(str+i)+len[i]-2));\\指针指向那一行的倒数第三个位置(倒一是‘\')
	}

2.22 代码截图

我的

同学的

我的特点就是遍历“诗”以指针锁定地址输出,他的则是重新定义一个p指针数组保存之前找到的地址再输出。
各有特点,但仍能学到许多。

2.2 合并两个有序数组

  • 伪代码
void merge(int* a, int m, int* b, int n)
定义一个数组c分配内存c = (int*) malloc((m + n) * sizeof(int));
遍历数组for (i = j = k = 0;i<m并且j<n;) {
        if (a中元素a[i]<b的元素b[j]) {
            c[k++] = a[i++];//c储存小的那个数
        }
        else {
            c[k++] = b[j++];
        }
    }

剩下的元素分配
  if (m > n) {
            while (i < m)
            c[k++] = a[i++];
    }

    else {
        while (j < n)
            c[k++] = b[j++];
    }

将c赋值给a
  for (i = 0; i < k; i++) {
        a[i] = c[i];
    }

  • 代码截图
    我的

同学的

我的代码特点是比较简洁,但牺牲了运行速度。同学的以代码量换取了运行速度,值得借鉴。

2.3说反话-加强版

伪代码:

定义指针数组char* str1[250001];
分配内存
for (i = 0; i < 2000; i++) {
		str1[i] = (char*)malloc( 250000* sizeof(char));//不建议,太耗内存了。。。
	}
长度len=strlen(str)-1;//fgets输入的多一个‘\n’。

if (前一个是‘ ’后一个不是‘ ’) {
			*(str + i + count) = '\0';//将每个单词“打包”
			strcpy(str1[j], str + i);//赋值到二维数组中
			j++;
			count = 0;
		}


		if (i == 0 && *(str + i) != ' ') {
			*(str + i + count) = '\0';
			strcpy((str1[j]), str + i);
			j++;
		}//对首字母特殊处理

输出

代码截图:

与超星视频比较
我的做法是定义了一个指针数组用strcpy来储存每一个单词,这样子每一个字符数组都分配一样的内存,很耗内存,所以最后一个测试点没过。
看了超星视频以后,感觉没必要这么做了,它用printf("%.*s",长度len,地址p )就能直接将所需单词输出。
其他的思路差不多。
只能说get到了一个很有用的知识点。

posted @ 2020-12-27 23:00  此处应该有名字  阅读(122)  评论(0编辑  收藏  举报