杨佳琴

指针

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

1.本章学习总结(3分)

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

  1. 指针是变量,但是指针的字节长度是固定的。因为指针保存的是地址,由操作系统的位数决定,32位机的字节是4,64位机的字节是8。
  2. 指针指向的内存空间和对应的内存空间

    在这里定义了一个整型指针p保存num的地址(0x1000),num的地址就是首字节的地址,而指针p本身的地址为0x2000。引入指针的定义:
    num对应的内存空间为5,指针p对应的内存空间为0x1000,指针指向的内存空间为5。
    num++:对num对应的内存空间加1。 5 --> 6
    p++:对p对应的内存空间加1。(步长) 0x1000 --> 0x1004
    (p)++:对p指向的内存空间加1。其中p是根据p对应的内存空间找到其对应的内存空间。 5 --> 6
    等式:
    p == &num
    *p == num == *(&num)
  3. 指针的运算
    a. 指针 +/- 整数 = 指针所对应的内存空间与它所指向的类型乘以整数相加减。eg. p++ --> p = p + 1
    b. 指针 - 指针 = 两个指针相差的数据个数。
    c. 指针的比较:如果两个指针变量指向同一个数组的元素,那么指向前面元素的指针变量小于指向后面元素的指针变量。
  4. 指针做函数参数
    函数指针可以作为一个参数传递给另一个函数。这时函数指针的使用就像普通的常量和变量一样。当函数指针作为参数传递的时候,这时接收参数传递的函数通常需要根据这个指针调用这个函数。
int calculate(int a, int b, fun_t operation)
{
 int result;
 result = operation(a, b); // 运算
 return result;
}

其中,fun_t是一个函数指针,其定义为:

typedef int (*fun_t)(int, int);
该函数指针fun_t指向一个带两个int类型的形参、int类型的返回值的函数。使用关键字typedef对int (*)(int, int)进行重命名(封装)为fun_t.

1.2 字符指针

  1. 除了字符数组,C语言还支持另外一种表示字符串的方法,就是直接使用一个指针指向字符串,例如:
    ``
    char *str = "http://c.biancheng.net";
或者:

char *str;
str = "http://c.biancheng.net";

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

函数名: stpcpy
功 能: 拷贝一个字符串到另一个
用 法: char *stpcpy(char *destin, char *source);

函数名: strcat
功 能: 字符串拼接函数
用 法: char *strcat(char *destin, char *source);

函数名: strchr
功 能: 在一个串中查找给定字符的第一个匹配之处
用 法: char *strchr(char *str, char c);

函数名: strcmp
功 能: 串比较
用 法: int strcmp(char *str1, char *str2);
看Asic码,str1>str2,返回值 > 0;两串相等,返回0

函数名: strncmpi
功 能: 将一个串中的一部分与另一个串比较, 不管大小写
用 法: int strncmpi(char *str1, char *str2, unsigned maxlen);

函数名: strcpy
功 能: 串拷贝
用 法: char *strcpy(char *str1, char *str2);

函数名: strcspn
功 能: 在串中查找第一个给定字符集内容的段
用 法: int strcspn(char *str1, char *str2);

函数名: strnset
功 能: 将一个串中的所有字符都设为指定字符
用 法: char *strnset(char *str, char ch, unsigned n);

函数名: strdup 
功  能: 将串拷贝到新建的位置处 
用  法: char *strdup(char *str); 
函数名: strerror 
功  能: 返回指向错误信息字符串的指针 
用  法: char *strerror(int errnum); 
函数名: strstr 
功  能: 在串中查找指定字符串的第一次出现 
用  法: char *strstr(char *str1, char *str2); 

1.3 指针做函数返回值

用指针作为函数返回值时需要注意的是,函数运行结束后会销毁在它内部定义的所有局部数据,包括局部变量、局部数组和形式参数,函数返回的指针请尽量不要指向这些数据,C语言没有任何机制来保证这些数据会一直有效,它们在后续使用过程中可能会引发运行时错误。

1.4 动态内存分配

  1. 为什么要动态内存分配
    a. 因为内存太宝贵。
    b. 如果全部是静止内存不能释放,对于小的程序可以运行完毕。但是对于大的程序,还没运行完,内存就要被占用完,此时就要发生内存泄露。
    c. 给定一个占用内存可变大小的变量(假设是数组的长度len),给该变量通过函数动态分配内存后,分配内存的大小是根据数组的长度len决定的,假定用户输入len的大小是5,系统就会动态的给该数组分配长度为5的内存,该段代码运行结束后,系统调用free()函数释放分配的内存,然后接着运行剩下的程序。换句话说,动态分配内存可以根据需要去申请内存,用完后就还回去,让需要的程序用。
  2. 堆区和栈区区别
    a. 在数据结构中,栈是一种可以实现“先进后出”(或者称为“后进先出”)的存储结构。假设给定栈 S=(a0,a1,…,an-1),则称 a0 为栈底,an-1 为栈顶。进栈则按照 a0,a1,…,an-1 的顺序进行进栈;而出栈的顺序则需要反过来,按照“后存放的先取,先存放的后取”的原则进行,则 an-1 先退出栈,然后 an-2 才能够退出,最后再退出 a0。
    在实际编程中,可以通过两种方式来实现:使用数组的形式来实现栈,这种栈也称为静态栈;使用链表的形式来实现栈,这种栈也称为动态栈。
    相对于栈的“先进后出”特性,堆则是一种经过排序的树形数据结构,常用来实现优先队列等。
    b. 内存分配中的栈与堆主要存在如下区别。
    分配与释放方式
    栈内存是由编译器自动分配与释放的,它有两种分配方式:静态分配和动态分配。
    1>. 静态分配是由编译器自动完成的,如局部变量的分配(即在一个函数中声明一个 int 类型的变量i时,编译器就会自动开辟一块内存以存放变量 i)。与此同时,其生存周期也只在函数的运行过程中,在运行后就释放,并不可以再次访问。
    2>. 动态分配由 alloca 函数进行分配,但是栈的动态分配与堆是不同的,它的动态分配是由编译器进行释放,无需任何手工实现。值得注意的是,虽然用 alloca 函数可以实现栈内存的动态分配,但 alloca 函数的可移植性很差,而且在没有传统堆栈的机器上很难实现。因此,不宜使用于广泛移植的程序中。当然,完全可以使用 C99 中的变长数组来替代 alloca 函数。
    而堆内存则不相同,它完全是由程序员手动申请与释放的,程序在运行的时候由程序员使用内存分配函数(如 malloc 函数)来申请任意多少的内存,使用完再由程序员自己负责使用内存释放函数(如 free 函数)释放内存,如代码所示:
/*分配堆内存*/
char  *p1 = (char *)malloc(4);
… …
/*释放堆内存*/
free(p1);
p1=NULL;

对栈内存的自动释放而言,虽然堆上的数据只要程序员不释放空间就可以一直访问,但是,如果一旦忘记了释放堆内存,那么将会造成内存泄漏,导致程序出现致命的潜在错误。
3. 动态分配相关函数及其用法
1>. malloc:
原型:void *malloc(int byte_size);
作用:动态开辟byte_size个字节的内存空间,不进行初始化,返回指向此内存的指针
举例:int p=(int )malloc(5sizeof(int));
例解:动态开辟5
4=20个字节大小的空间,返回空间首地址指针并强转为int *型后赋予指针变量p。
注意:malloc只开辟空间,不初始化,即只将此空间由未占用状态变为已占用状态,空间内存储的具体数据未指定改变。函数返回值是空间首地址,上例中赋给了p变量。
2>. calloc:
原型:void calloc(int n,int type_byte_size);
作用:动态开辟n
type_byte_size个字节,将每个字节均初始化为ascii码0,返回指向此内存的指针,
举例:int *p=(int )calloc(5,sizeof(int));
例解:动态开辟5
4=20个字节大小的空间,其中每个字节均赋初值0,返回空间首地址指针并强转为int *型后赋予指针变量p。
注意:calloc在malloc的基础上将空间按字节初始化为ascii码0,且其参数有两个,两参数之积为空间总字节数。
3>. realloc
void * realloc(void * ptr,size_t size)
realloc()函数让动态内存管理更加灵活 .在程序运行过程中动态分配内存大小, 如果分配的太大 ,则浪费空间, 如果太小, 可能还是会出现不够用的情况 .为了合理的利用内存,我们一定会对内存的大小做灵活的调整。那realloc() 函数就可以做到对动态开辟内存大小的调整(既可以往大调整, 也可以往小了调整) .
1). ptr为需要调整的内存地址
2). size为调整后需要的大小(字节数)
3). 若调整成功, 返回值为调整大小后内存的起始位置(也就是指向调整后内存的指针), 若失败(当没有内存可以分配时, 一般不会出现), 则返回NULL, 所以还是要对返回值判空
4). 如果ptr是空指针, 则和calloc()函数一样作用一样

1.5 指针数组及其应用

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

二维字符数组:
char str[5][5]={"abc","abcd","aaaa","ad","k"};
str[0]到str[4]五个字符串的最大长度被限制为(5-1)=4。

由于每个字符串的地址已经确定,所以以下赋值是不允许的:

str[0]="news";
字符指针数组:
char* str[5];

以下赋值是允许的:

str[0]="Welcome!";//字符串长度无限定

1.6 二级指针

1.7 行指针、列指针

(1). 行指针:指向某一行,不指向具体的元素。
(2). 列指针: 指向行中具体的元素。
从根本类型bai上讲:行指针是du int()[]类型,zhi列指针是int * 类型的。
int a[2][3];定义它zhuan的行指针shu就是int(
pr)[3]=a;而定义列指针int *pc=pr[0];
pr,pr+1,pr+2分别表示第一二三行(其实就是&a[0],&a[1],&a[2])。
至于列指针就是指向具体某行某列的指针。
所谓行指针,就是一个指向一维数组的指针(它指向地址的值也是指针,每次自增跨度是一个数组的长度)。
而列指针,就是指向具体某行某列的一个指针,指向地址的值是一个数组的元素。

2.PTA实验作业(7分)

2.1 题目名1(2分)


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

char *search( char *s, char *t )
{
	int i=0,k=0;
	int slen=0,tlen=0;
	while(s[slen]!='\0') slen++; //计算s的长度
	while(t[tlen]!='\0') tlen++; //计算t的长度
	 
	while(i<slen&&k<tlen) //任意字符串越界则结束循环
	{
		if(s[i]==t[k]) //相同则一起++
		{
			i++;
			k++;
		}
		else            //不同则只有i++,但当前面相投后面不相同时,k=0,i退格+1.
		{
				k=0;
                                i=i-k+1;	
		}
	}
	if(k>=tlen)
		return s+i-k; //返回地址
	else
		return NULL;	
}

他的代码思路清楚,文字注释较多,值得我去学习。
2.2 题目名2(2分)

这道题我没有做出来。
2.3 题目名3(3分)

#include<stdio.h>
#include<string.h>
int main()
{
	char c[600000];
	gets(c);

	int i,j,flag,l;	
	l=strlen(c);
	for(i=0;i<l;i++)
		if(c[i]==' ')
			c[i]='\0';
	
	for(;l>=0;l--)
		if(c[l-1]=='\0'&&c[l]!='\0')
		{
			flag=0;		
			
			for(i=l;c[i]!='\0';i++)
				putchar(c[i]);
            for(j=0;j<l-1;j++)
				if(c[j]!='\0')
                {
					flag=1;
				break;
				}
			if(flag)
			printf(" ")	;
		}		
}

posted on 2020-12-27 22:22  长安&  阅读(391)  评论(0编辑  收藏  举报

导航