指针与字符串、指针与函数

标题1、 指针与字符串的千丝万缕

由于在C语言中,是通过字符数组来存储字符串的,因而前面通过指针对一维数组和二维数组的操作方法,同样适用于字符串。其实,对字符串的操作最好采用字符串操作函数。

#include<stdio.h>
int main()
{
	char name[12],*p;
	p=name;
	gets(p);
	puts(p); 
	return 0;
}
再例如:char *p=”hello”;等价于char *p; p=”hello”。
        它的意思是把:hello串在内存中的首地址赋值给p。
我们已经讲过,如果要存储和处理我们班49个同学的姓名,可以定义一个二维数组,假设48个同学的姓名只占6个字节,因而第二维的大小为7即可,只有一个同学是少数民族,她的姓名需要占19个字节,因而需要给它分配至少20个字节的单元才能存放,为此,整个二维数组的第二维的大小必须为20个字节。char name[49][20];
    显然,这样会造成内存的浪费:48*13个字节的空间是无用的。如果随着问题规模的增大,这个浪费会更大,有没有一种办法,当需要多大空间的时候就分配多大的空间,字符指针数组就可以解决这个问题。
    char *name[3]={"hello","lcy","hahahahahahaha"};
这样定义之后,”hello”在内存中的首地址赋值给name[0],同理”lcy”在内存中的首地址赋值给name[1],"hahahahahahaha"在内存中的首地址赋值给name[2]。
    有同学会问:如果我们班同学的姓名都这样初始化的话,感觉也挺麻烦的:char* name[49]={“111”,”222”,,,,,,,,,,,,,,,,};
姓名能不能在程序中输入呢?

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
	char *name[49], s[20];
	int i;
	for(i=0;i<49;i++)
	{
		gets(s);
		name[i]=(char*)malloc(strlen(s)+1);
		if(name[i]!=NULL)
        strcpy(name[i],s);
    }
    for(i=0;i<49;i++)
        puts(name[i]);
	for(i=0;i<49;i++)
		    free(name[i]);
	return 0;
}

因为malloc函数分配的内存空间是在堆区上分配的,程序结束后,系统不会将其自动释放,需要程序员自己管理,C提供了free函数来释放内存。

标题2 :指针与函数

1. 指针作为函数参数

指针作为函数参数有两种形式:
(1)指针变量作为函数参数。前面我们讲过的swap函数,就是采用指针变量作为函数参数,才能通过swap函数交换实参的值。
(2)数组作为函数参数。前面我们讲解一维数组时,如果采用子函数形式来描述冒泡排序和选择排序时,就是采用了数组作为函数形参。这里不再赘述。
下面我们看一下字符串的连接函数来加深记忆吧。
(1)采用指针变量作为函数形参:

#include<stdio.h>
void connect_string(char *from,char *to)
{
	while(*from!='\0')
		from++;
	while(*to!='\0')
		*from++=*to++;
	*from='\0';
}
int main()
{
	char str1[50],str2[50];
	gets(str1);
	gets(str2);
	connect_string(str1,str2);
	puts(str1);
	return 0;
}

(2)采用数组作为函数形参

#include<stdio.h>
#include<string.h>
void connect_string(char from[],char to[])
{
	int i,j;
	for(i=strlen(from),j=0;j<strlen(to);i++,j++)
		from[i]=to[j];
	from[i]='\0';
}
int main()
{
	char str1[50],str2[50];
	gets(str1);
	gets(str2);
	connect_string(str1,str2);
	puts(str1);
	return 0; 
}

2. 返回指针的函数(也称为指针函数)

函数的返回值可以是int、double、char、int、void,C语言还允许函数的返回值是一个指针(地址)。

#include<stdio.h>
char *strchr(char *s,char ch)
{
	while(*s!='\0')
		if(*s==ch) return s;
		else s++;
}
int main()
{
	char *p=NULL,ch,s[]="hello,big data!";
	ch=getchar();
	p=strchr(s,ch);
	if(p)
		{
		    printf("%c's position is:%x\n",ch,p);
		    printf("%c's position is:%d\n",ch,p-s+1);
		}
	else
		printf("%c isn't exist!\n");
	return 0;
}

该程序的功能,输出某个字符(该字符可通过键盘输入)在字符串中的位置。
在这里插入图片描述

3. 指向函数的指针

如果在程序中定义了一个函数,在编译时,编译器为该函数代码分配了一段存储空间,这段存储空间的首地址可以用函数名来描述。因而,可以把这个首地址赋给一个指针变量,使得该指针变量指向该函数,把这种指向函数的指针变量称为:函数指针变量或者函数指针。

 #include<stdio.h>
    int func(int a,int b)
    {
        return a+b;
    }
    int main()
    {
    	int result;
    	int(*p)(int,int);
    	p=func;
    	result=(*p)(3,5);
    	printf("%d\n",result);
    	return 0;
    }

其中,p=func; //让指针变量指向了func函数的首地址
      result=(*p)(3,5);//通过指针变量p来调用函数

函数指针可作为函数参数。

用函数名来调用函数,只能调用指定的函数。而通过函数指针变量调用函数就比较灵活了,可以根据不同情况先后调用不同的函数。

#include<stdio.h>
int add(int a,int b)
{
    return a+b;
}
int minus(int a,int b)
{
    return a-b;
}
int xc(int a,int b)
{
    return a*b;
}
int func(int(*p)(int,int),int b,int n)
{
    int result=0,i;
    for(i=0;i<n;i++)
        result+=(*p)(i,b);
    return result;
}
int main()
{
	int result;
	result=func(add,1,10);
	printf("%d\n",result);
	result=func(minus,1,10);
	printf("%d\n",result);
	result=func(xc,1,10);
	printf("%d\n",result);
	return 0;
}

4. 带参数的main函数

前面使用的main都是无参的,实际上该函数也可以接收参数。main()函数是程序的入口,通常用来接收来自系统的参数。argc表示在命令行中输入的参数个数,argv为字符指针数组,其各个元素值为命令行中各字符串的首地址。

#include<stdio.h>
int main(int argc,char* argv[])
{
    int i;
    printf("%d\n",argc);
    for(i=0;i<argc;i++)
        puts(argv[i]);
    return 0;
}

在这里插入图片描述

5、 其它知识

周二实验课,黎龙洋同学问了一个memset函数的问题,问是不是进行初始化的。其实,还有很多对内存进行操作的函数:熟悉的malloc、free,还有memcpy、memmove和memcmp等等。用到的时候查阅下资料,不同的函数均有不同的用途。C++提供了new来进行内存空间的动态分配,我感觉也非常方便。

扫描二维码关注公众号,回复: 4562256 查看本文章
#include<iostream>
using namespace std;
int main()
{
    int *p,n,i;
    cin>>n;
    p=new int[n]{0}; //初始化
    for(i=0;i<n;i++)
        cout<<*(p+i)<<" ";
cout<<endl;
delete [] p; 
    return 0;
}

需要注意的是:p=new int[n]{0}; 动态开辟一个含n个int的无名数组空间,把该空间的首地址赋给P,数组中的元素均初始化为0。

delete [] p; //释放空间,因为p指向的是数组,因而需要加上[ ]。

猜你喜欢

转载自blog.csdn.net/lvcongying0601/article/details/84313914