这个作业属于哪个班级 | C语言--网络2011/2012 |
---|---|
这个作业的地址 | C博客作业05--指针 |
这个作业的目标 | 学习指针相关内容 |
姓名 | 吴慧敏 |
0.展示PTA总分(0----2)
1.本章学习总结(3分)
1.1 指针定义、指针相关运算、指针做函数参数。
- 指针定义:专门用来存放另一个变量的地址,那么就称它为“指针变量”。
- 指针相关运算:
指针变量加(减)一个整数:c语言中规定,一个指针变量加(减)一个整数并不是简单的将指针变量的值加(减)一个整数,而是将该指针变量的原值(是一个地址)和它指向的变量锁占用的内存单元字节数相加减。如:p+i代表地址计算:p+c*i。其中,c为字节数。
两个指针变量相加减:如果两个指针变量都指向同一个数组中的元素,则两个指针变量值之差是两个指针之间的元素个数。
两个指针变量比较:若两个指针指向同一个数组元素,则可以进行比较。指向前面的元素指针变量小于指向后面元素的指针变量,其值为0或1(真或假)
指针变量的赋值:
p= &a; 表示将变量a的地址赋给p;
p= arry, 表示将数组arry首元素地址赋给P;
p= &arry[i]; 表示将数组arry第个元素的地址赋给p;
p= max, 表示将max的入口地址赋给p,其中max为已定义的函数;
p1= p2, 表示将p2的值赋给p1,其中p1和p2都是指针变量;
p= NULL,不指向任何变量的指针变量为空指针。
注意:p=p+1,++p,和(p)++都是将指针p所指向的变量的值加1。而表达式p++等价于(p++)。
- 指针做函数参数:可以实现返回多个值的功能。
1.2 字符指针
指针如何指向字符串:将指针指向该字符串的首地址。
eg.char *p = str;//定义一个指针变量,里面存放字符数组的首地址
字符串相关函数及函数代码原型的理解:
1.char *strcpy(char* dest, const char *src);
把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间,src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
eg.
char a[10],b[]={"COPY"};
//定义字符数组a,b
strcpy(a,b);
//将b中的COPY复制到a中
2.char *strcat(char *dest, const char *src);
把src所指向的字符串(包括“ ”)复制到dest所指向的字符串后面(删除dest原来末尾的“ ”)。要保证dest足够长,以容纳被复制进来的src。src中原有的字符不变。返回指向dest的指针,src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
3.strcmp(str1,str2)
用于比较两个字符串并根据比较结果返回整数,若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数。
4.strlen(s1)
:计算给定字符串的(unsigned int型)长度,不包括' '在内,返回s的长度,不包括结束符NULL。
1.3 指针做函数返回值
int a(int *p)
注意:
指针的类型要和函数返回值一样
指针在函数内无返回值时应return 0(return NULL)
1.4 动态内存分配
- 为什么要动态内存分配:
传统数组长度必须事先指定,而且只能是常量,不能是变量。
因为数组长度只能是常量,所以它的长度不能在函数运行的过程当中动态地扩充和缩小
因为数组长度只能是常量,所以它的长度不能在函数运行的过程当中动态地扩充和缩小
动态数组能很好地解决传统数组的这几个缺陷。 - 堆区和栈区区别:
堆区(heap) 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS(操作系统)回收。分配方式类似于链表
栈区(stack) 函数运行时分配,函数结束时释放。由编译器自动分配释放 ,存放为运行函数而分配的局部变量、函数参数、返回数据、返回地址等。其操作方式类似于数据结构中的栈。
void *malloc(unsigned int size);
其作用是在内存的动态存储区中分配一个长度为size的连续空间。此函数的返回值是分配区域的起始地址,或者说,此函数是一个指针型函数,返回的指针指向该分配域的开头位置。一般它需和free函数配对使用。free函数能释放某个动态分配的地址,表明不再使用这块动态分配的内存了,实现把之前动态申请的内存返还给系统。
void* calloc(unsigned int num,unsigned int size)
在内存的动态存储区中分配num个长度为size的连续空间。num:对象个数,size:对象占据的内存字节数,相较于malloc函数,calloc函数会自动将内存初始化为0;
1.5 指针数组及其应用
如果使用指针,可以这么初始化:char *s[] = "I", "love", "you"};
字符串二维数组:char s[3][5] = {"I", "love", "you"};
在字符串数组的初始化上显然更建议用指针数组来进行初始化,这样能更好地利用内存空间。
但在访问字符串数组(或者其他二维数组)上,用数组形式更加简洁、清晰。
1.6 二级指针
如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针。
int a =100;
int *p1 = &a;
int **p2 = &p1;
1.7 行指针、列指针
行指针:指向某一行,不指向具体的元素。int (*a)();
列指针:指向行中具体的元素。a[i]
2.PTA实验作业(7分)
2.1 题目名1(2分)
2.1.1 伪代码
定义最大值max=0,length=0,i;
for()
{
计算字符串s[i]的长度
if(字符串长度大于max)
{
让最大值为此时字符串长度
}
}
2.1.2 代码截图
2.1.3 找一份同学代码(尽量找思路和自己差距较大同学代码)比较,说明各自代码特点。
姚庆荣同学的代码:
int max_len( char *s[], int n )
{
int i, min=0, max=0;
for(i=0;i<n;i++)
{
min=strlen(s[i]);
if(min>max)
max=min;
}
return max;
}
他的代码特点:简洁明了。运用for循环找到最大值。
2.2 题目名2(2分)
2.2.1 伪代码
2.2.2 代码截图
2.2.3 找一份同学代码(尽量找思路和自己差距较大同学代码)比较,说明各自代码特点。
姚庆荣同学的代码:
void merge(int* a, int m, int* b, int n)
{
int i=0, j=0, k=0;
int* c;
c = (int*)malloc((m + n) * sizeof(int));
for (; i<m&&j<n; k++)
{
if (a[i] < b[j])
{
c[k] = a[i++];
}
else
{
c[k] = b[j++];
}
}
if (m > n)
{
while (i < m)
{
c[k++] = a[i++];
}
}
else
{
while (j < n)
{
c[k++] = b[j++];
}
}
for (i = 0; i < k; i++)
{
a[i] = c[i];
}
}
2.3 题目名3(3分)
2.3.1 伪代码
void ReverseStr(char *beginPtr)
{
定义尾部指针endPtr=beginPtr
while(*endPtr)endPtr++//指针定位到字符串尾部
遍历指针p=--endPtr
while(!=beginPtr)
{
若*p不是空格,则统计单词长度len
若*p不是空格但是前一个字符是空格:
则找到单词,输出从p开始的len长度字符串,len=0
p--
}
输出第一个单词
}
2.3.2 代码截图
2.3.3 请说明和超星视频做法区别,各自优缺点。
(参照超星视频做的,所以没差别)
优点:
1:字符串指针能灵活表示某个子串:printf("%.*s",len,p);
输出长为len,起始位置为p的字符串。 (%.ms可以输出指定长为m的字符串长度)
2:找单词:指针定位在字符串最后一个字符,往前扫描到第一个空格,即找到一个单词,则输出指定长度字符串。
3:fgets会吸收换行符,所以还要考虑'endPtr!='
''的情况