C博客作业05--指针

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

0.展示PTA总分

1.本章学习总结

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

1.1.1定义:

数据在内存中的地址也称为指针,如果一个变量存储了一份数据的指针,我们就称它为指针变量。这样的一份数据可以是数组、字符串、函数,也可以是另外的一个普通变量或指针变量。定义指针变量要在变量名前面加星号*。

1.1.2运算:

    int    a = 10,   *pa = &a, *paa = &a;
    double b = 99.9, *pb = &b;
    char   c = '@',  *pc = &c;
    //最初的值
    printf("&a=%s, &b=%s, &c=%s\n", &a, &b, &c);
    printf("pa=%s, pb=%s, pc=%s\n", pa, pb, pc);
    //加法运算
    pa++; pb++; pc++;
    printf("pa=%s, pb=%s, pc=%s\n", pa, pb, pc);
    //减法运算
    pa -= 2; pb -= 2; pc -= 2;
    printf("pa=%s, pb=%s, pc=%s\n", pa, pb, pc);
    //比较运算
    if(pa == paa){
        printf("%d\n", *paa);
    }else{
        printf("%d\n", *pa);
    }

指针变量保存的是地址,而地址本质上是一个整数,所以指针变量可以进行加法、减法、比较等运算。并且运算以后可以发现:pa、pb、pc 每次加 1,它们的地址分别增加 4、8、1,正好是 int、double、char 类型的长度;减 2 时,地址分别减少 8、16、2,正好是 int、double、char 类型长度的 2 倍。所以指针变量加减运算的结果跟数据类型的长度有关,而不是简单地加 1 或减 1。

1.1.3指针做函数参数:

用指针变量作函数参数可以将函数外部的地址传递到函数内部,使得在函数内部可以操作函数外部的数据,并且这些数据不会随着函数的结束而被销毁。像数组、字符串、动态分配的内存等都是一系列数据的集合,没有办法通过一个参数全部传入函数内部,只能传递它们的指针.有的时候,对于整数、小数、字符等基本类型数据的操作也必须要借助指针,一个典型的例子就是交换两个变量的值。

void swap(int *p1, int *p2){
    int temp;  
    temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}

1.2 字符指针:

字符串中的所有字符在内存中是连续排列的,str 指向的是字符串的第 0 个字符;我们通常将第 0 个字符的地址称为字符串的首地址。字符串中每个字符的类型都是char,所以 str 的类型也必须是char *。

   char *str = "qimobuguake";
   int len = strlen(str), i;
  
   //直接输出字符串
   printf("%s\n", str);
   //使用*(str+i)
   for(i=0; i<len; i++){
       printf("%c", *(str+i));
   }
   printf("\n");
   //使用str[i]
   for(i=0; i<len; i++){
       printf("%c", str[i]);
   }

上述代码运行结果均为qimobuguake,但它们在内存中的存储区域不一样,字符数组存储在全局数据区或栈区,第二种形式的字符串存储在常量区。全局数据区和栈区的字符串有读取和写入的权限,而常量区的字符串只有读取权限,没有写入权限。(因此被命名为字符串常量)

1.3 指针做函数返回值:

C语言允许函数的返回值是一个指针,我们将这样的函数称为指针函数。用指针作为函数返回值时,函数运行结束后会销毁在它内部定义的所有局部数据,包括局部变量、局部数组和形式参数。

1.4 动态内存分配:

申请内存使用的是malloc()和free(),都是标准函数,在stdlib.h中定义。申请内存有可能失败,失败时返回NULL,因此,动态申请内存时,一定要判断结果是否为空。malloc()的返回值类型是“void *”。

1.5 指针数组及其应用:

如果一个数组中的所有元素保存的都是指针,那么我们就称它为指针数组。

dataType *(arrayName[length]);

上述代码忠arrayName是一个数组,包含了length个元素,括号外面说明每个元素的类型为dataType *。

1.6 二级指针:

指针可以指向一份普通类型的数据,例如 int、double、char 等,也可以指向一份指针类型的数据,例如 int *、double *、char * 等。如果一个指针指向的是另外一个指针,我们就称它为二级指针。
假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量,它们的关系如下图所示:

  • 可以使用&获取指针的地址。
  • 每增加一级指针,在定义指针变量时就得增加一个星号*。

1.7 行指针、列指针:

二维数组指针是一个指针,它指向一个二维数组。
指针数组和二维数组指针在定义时非常相似,只是括号的位置不同:

int *(p1[5]);  //指针数组,可以去掉括号直接写作 int *p1[5];
int (*p2)[5];  //二维数组指针,不能去掉括号

2.PTA实验作业

2.1 7-3 字符串的冒泡排序

2.1.1 伪代码

if (strcmp(a[i], a[i + 1]) > 0)\\运用strcmp比较a[i]和a[i+1]大小,当a[i]>a[i+1]时,进行排序
{
	strcpy(b, a[i]);       \\运用strcpy实现[i]和a[i+1]交换位置
	strcpy(a[i], a[i + 1]);
	strcpy(a[i + 1], b);
}

2.1.2 代码截图

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

由于本题思路比较简单,所以大家的代码都大同小异。

2.2 6-9 合并两个有序数组(2)

2.2.1 伪代码

        for (i = 0; i < m; i++)//新建一个数组c将a、b放进c中
	{
		*c = a[i];
		c++;
	}
	for (i = 0; i < n; i++)
	{
		*c = b[i];
		c++;
	}
	for (i = 1; i < m + n; i++)//通过冒泡法排序升序排序数组
	{
		for (j = i + 1; j < m + n; j++) {
			if (a[i] > a[j])
			{
				t = a[i];
				a[i] = a[j];
				a[j] = t;
			}

2.2.2 代码截图

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


我的代码用了循环嵌套,但是在运行时数据个数100000会超时,而同学的代码使用了逆向载入的方式避免了运行超时。

2.3 7-4 说反话-加强版

2.3.1 伪代码

	for (i = len - 1; i >= 0; i--)\\逆向输入数据
	{
		if (a[i] != ' ' && a[i] != '\n')
		{
			tail = i;
			for (j = i - 1; j >= 0; j--)
			{
				if (a[j] == ' ')
				{
					head = j + 1;
					break;
				}
				if (j == 0)
				{
					head = j;
					break;
				}
			}
			i = j;
			if (count > 0)\\输出一个空格
			{
				printf(" ");
			}
			for (j = head; j <= tail; j++)\\输出数据
			{
				printf("%c", a[j]);
			}

2.3.2 代码截图

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

老师的做法比较清晰易读,但是在第一次接触时会有点难懂,必须反复读代码才能理解。我的代码需要说明的特殊情况较多,代码看上去就显得杂乱,不过也能得到结果。

posted @ 2020-12-27 22:08  a丶落雨未  阅读(125)  评论(0编辑  收藏  举报