C++笔记day7-指针和字符串

145 阅读5分钟

指针和函数:

栈 帧:

	当函数调用时,系统会在 stack 空间上申请一块内存区域,用来供函数调用,主要存放 形参 和 局部变量(定义在函数内部)。

	当函数调用结束,这块内存区域自动被释放(消失)。

传值和传址:

传值:

函数调用期间,实参将自己的值,拷贝一份给形参。

01-传值操作.png

示例

//函数声明
int swap(int a, int b);

int main(void)
{
	int m = 37;
	int n = 35;

	printf("before m =%d n =%d\n", m, n);

	//函数调用;
	swap(m, n); //实参;

	printf("after m = %d n = %d\n", m, n);



	system("pause");
	return EXIT_SUCCESS;
}
//函数定义
int swap(int a, int b) // a,b 形参
{
	int temp = 0;

	temp = a;
	a = b;
	b = temp;

	return 0;
}

传址:

函数调用期间,实参将地址值,拷贝一份给形参。 【重点】

(地址值 --》 在swap函数栈帧内部,修改了main函数栈帧内部的局部变量值)

指针做函数参数:

	int swap2(int *a, int *b);

	int swap2(char *a, char *b);

	调用时,传有效的地址值。

02-传址操作.png

示例

//函数声明
int  swap(int a, int b);
int swap2(int* a, int* b);


int main(void)
{
	int m = 37;
	int n = 35;

	printf("before m =%d n =%d\n", m, n);

	//函数调用;
	swap(m, n); //实参;
	printf("after swap m = %d n = %d\n", m, n);
	swap2(&m, &n);//实参:取地址
	printf("after swap2 m = %d n = %d\n", m, n);


	system("pause");
	return EXIT_SUCCESS;
}
//函数定义:传值
int swap(int a, int b) // a,b 形参
{
	int temp = 0;

	temp = a;
	a = b;
	b = temp;

	return 0;
}
//函数定义:传址
int swap2(int* a, int* b) 
{
	int temp = 0;

	temp = *a;
	*a = *b;
	*b = temp;

	return 0;
}

数组做函数参数:

	void BubbleSort(int arr[10]) == void BubbleSort(int arr[])  == void BubbleSort(int *arr) 

	传递不再是整个数组,而是数组的首地址(一个指针)。

	所以,当整型数组做函数参数时,我们通常在函数定义中,封装2个参数。一个表数组首地址,一个表元素个数。

指针做函数返回值:

	int *test_func(int a, int b);

	指针做函数返回值,不能返回【局部变量的地址值】。


数组做函数返回值:

	C语言,不允许!!!!  只能写成指针形式。

示例1:数组做函数参数

void BubbleSort(int arr[]) //把数组封装为函数形参相当于 void BubbleSort(int *arr)
{
    int n = sizeof(arr) / sizeof(arr[0]);

    printf("n = %d\n", n); //封装后值变了
    printf("sizeof(arr) = %d\n", sizeof(arr)); // 数组首地址,即一个指针的大小,64位系统8字节
    printf("sizeof(arr[0]) = %d\n", sizeof(arr[0])); //4字节

    for (int i = 0; i < 10- 1; i++)
    {
        for (int j = 0; j < 10 - 1 - i; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}
//可以改为void BubbleSort(int arr[],int n)
//整形数组做函数参数时,通常在函数定义中封装2个参数,一个表数组首地址,一个表示元素个数。

int main(void)
{

    int arr[] = {1,2,15,51,3,78,99,21,8,6};

    int n = sizeof(arr) / sizeof(arr[0]);
    printf("n = %d\n", n);
    printf("sizeof(arr) = %d\n", sizeof(arr));//整个数组的大小
    printf("sizeof(arr[0]) = %d\n", sizeof(arr[0]));

    BubbleSort(arr);

    for (size_t i = 0; i < n; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
	system("pause");
	return EXIT_SUCCESS;
}

示例2:指针做函数返回值

int m = 100; //全局变量;对应空间消失  ===>程序结束

int* test_func(int a, int b) 
{
	return &m;
}

int main(void)
{
	int *ret = NULL; //NULL = 0;
	ret = test_func(10, 20);
	printf("ret = %d\n", *ret);
	system("pause");
	return EXIT_SUCCESS;
}

指针和字符串:

1char str1[] = {'h', 'i', '\0'};			变量,可读可写

	char str2[] = "hi";				变量,可读可写

	char *str3 = "hi";				常量,只读

		str3变量中,存储的是字符串常量“hi”中首个字符‘h’的地址值。


		str3[1] = 'H';	// 错误!!

	char *str4 = {'h', 'i', '\0'};  // 错误!!!

2)
	当字符串(字符数组), 做函数参数时, 不需要提供2个参数。 因为每个字符串都有 '\0'

示例

int main(void)
{
	char str1[] = "hello"; //{'h','e','l','l','o','\0'}
	char m[] = "hello";//不跟str1一个地址,是变量
	char* str2 = "hello"; //“hello"是一个字符串常量
	char *n = "hello"; //是字符串常量,只能读,所以跟str2一个地址

	str1[0] = 'R';
	//不能写成:str2[0] = 'R'; 
 
	printf("str1 = %s\n", str1);
	printf("str2 = %s\n", str2);

	printf("str1 = %p\n", str1);
	printf("m = %p\n", m);	
	printf("str2 = %p\n", str2);
	printf("n = %p\n", n);

	system("pause");
	return EXIT_SUCCESS;
}

练习:比较两个字符串: strcmp();实现

比较 str1 和 str2, 如果相同返回0, 不同则依次比较ASCII码,str1 > str2 返回1,否则返回-1

数组方式:

int mystrcmp(char *str1, char *str2)
{
	int i = 0;

	while (str1[i] == str2[i])   // *(str1+i) == *(str2+i)
	{
		if (str1[i] == '\0')
		{
			return 0;			// 2字符串一样。
		}
		i++;
	}
	return str1[i] > str2[i] ? 1 : -1;
}

指针方式:

int mystrcmp2(char *str1, char *str2)
{
	while (*str1 == *str2)   // *(str1+i) == *(str2+i)
	{
		if (*str1 == '\0')
		{
			return 0;			// 2字符串一样。
		}
		str1++;
		str2++;
	}
	return *str1 > *str2 ? 1 : -1;
}

示例

//str1和str2比较,如果相等,返回0;如果str1>str2返回1;否则返回-1

int mystrcmp(char* str1, char* str2) //数组方式 
{
	int  i = 0;
	while (str1[i] == str2[i])  // *(str1+i) == *(str2+i)
	{
		if (str1[i]=='\0')
		{
			return 0; //两字符串一样
		}
		i++;
	}
	return *str1 > *str2 ? 1 : -1;//三目运算,不然str1<str2只能返回0;
}

int mystrcmp2(char* str1, char* str2) //指针方式
{
	while (*str1 == *str2)  // *(str1+i) == *(str2+i)
	{
		if (*str1 == '\0')
		{
			return 0; //两字符串一样
		}
		str1++;
		str2++;
	}
	return *str1 > *str2 ? 1 : -1;
}

int main(void)
{
	char* str1 = "hello ";
	char* str2 = "helloz";

	int ret = mystrcmp2(str1,str2);
	if (ret ==0)
	{
		printf("str1 = str2");
	}
	else if (ret == 1)
	{
		printf("str1 > str2");
	}
	else
	{
		printf("str1 < str2");
	}

	system("pause");
	return EXIT_SUCCESS;
}


练习:字符串拷贝:

//数组版本
void mystrcpy(char *src, char *dst)
{
	int i = 0;
	while (src[i] != 0)  // src[i] == *(src+i)
	{
		dst[i] = src[i];
		i++;
	}
	dst[i] = '\0';
}
//指针版
void mystrcpy2(char *src, char *dst)
{
	while (*src != '\0')  // src[i] == *(src+i)
	{
		*dst = *src;
		src++;
		dst++;
	}
	*dst = '\0';
}

练习:在字符串中查找字符出现的位置:

char *myStrch(char *str, char ch) //指针方式
{
	while (*str)
	{
		if (*str == ch)
		{
			return str;
		}
		str++;
	}
	return NULL;
}
// hellowrld --- 'o'
char *myStrch2(char *str, char ch) //数组方式
{
	int i = 0;
	while (str[i])
	{
		if (str[i] == ch)
		{
			return &str[i];  
		}
		i++;
	}
	return NULL;
}

示例

char *strch(char *src, char ch) //查找字符串中字符出现的位置,数组方式 
{
	int i = 0;
	while (src[i])
	{
		if (src[i] == ch) 
		{
			return &src[i];
		}
		i++;
	}
	return NULL;
}

char* strch2(char* src, char* ch) //指针方式
{
	while (*src)
	{
		if (*src == ch)
		{
			return src;

		}
		src++;
	}
	return NULL;
}

int main(void)
{
	char* src = "hello world";
	char ch = 'e';

	char* ret = NULL;

	ret = strch(src, ch);
	printf("ret = %s\n", ret);

	system("pause");
	return EXIT_SUCCESS;
}

练 习:字符串去空格。

void str_no_space(char *src, char *dst)
{
	int i = 0;   // 遍历字符串src
	int j = 0;	 // 记录dst存储位置
	while (src[i] != 0)
	{
		if (src[i] != ' ')
		{
			dst[j] = src[i];
			j++;
		}
		i++;
	}
	dst[j] = '\0';
}
// 指针版
void str_no_space2(char *src, char *dst)
{
	while (*src != 0)
	{
		if (*src != ' ')
		{
			*dst = *src;
			dst++;
		}
		src++;
	}
	*dst = '\0';
}

示例

void strnospace(char* src, char* dst)  //数组模式
{
	int i = 0;//遍历字符串src;
	int j = 0;//记录dst存储位置

	while (src[i] != 0) 
	{
		if (src[i] != ' ') 
		{
			dst[j] = src[i];
			j++;
		}
		i++;
	}
	dst[j] = '\0';
}

void strnospace2(char* src, char* dst)  //指针模式
{

	while (*src)
	{
		if (*src != ' ')
		{
			*dst = *src;
			dst++;
		}
		src++;
	}
	*dst = '\0';
}




int main(void)
{
	char str[] = "ni chou sha chou ni za di ";
	char dst[100] = { 0 };
	strnospace2(str, dst);
	printf("dst = %s\n", dst);


	system("pause");
	return EXIT_SUCCESS;
}

带参数的main函数:

无参main函数: 	int main(void) == int main()

带参数的main函数: int main(int argc, char *argv[]) == int main(int argc, char **argv)

	参1:表示给main函数传递的参数的总个数。

	参2:是一个数组!数组的每一个元素都是字符串 char * 

测试1: 
	命令行中的中,使用gcc编译生成 可执行文件,如: test.exe

	test.exe abc xyz zhangsan nichousha 

	-->

	argc --- 5
	test.exe -- argv[0]
	abc -- argv[1]
	xyz -- argv[2]
	zhangsan -- argv[3]
	nichousha -- argv[4]

测试2:

	在VS中。项目名称上 --》右键--》属性--》调试--》命令行参数 --》将 test.exe abc xyz zhangsan nichousha 写入。

	-->

	argc --- 5
	test.exe -- argv[0]
	abc -- argv[1]
	xyz -- argv[2]
	zhangsan -- argv[3]
	nichousha -- argv[4]
		

str 中 substr 出现次数:

strstr函数: 在 str中,找substr出现的位置。

char *strstr(char *str, char *substr)   -- #include <string.h>

	参1: 原串

	参2: 子串

	返回值: 子串在原串中的位置。(地址值);

		 如果没有: NULL

实 现:统计字符串中子串出现的次数

int str_times(char *str, char *substr)
{
	int count = 0;
	char *p = strstr(str, substr);  // "llollollo"

	while (p != NULL)
	{
		count++;
		p += strlen(substr);	// p = p+strlen(substr) --> "llollo"
		p = strstr(p, substr);	// 返回: "llo"
	}
	return count;
}

字符串中找子串.png

示例

int strtimes(char* str, char* substr) 
{
	char* p = strstr(str, substr);
	int count = 0;
	while (p != NULL)
	{
		count++;
		p += strlen(substr);//p跳过子串的距离;
		p = strstr(p, substr);
	}
	return count;
}

int main(void)
{	
	char str[] = "hellollollo";
	char substr[] = "llo";


	char* ret = strstr("hellollollo", "lloh"); //需要引入string.h
	int renum = strtimes(str, substr);

	printf("ret = %s\n", ret);
	printf("出现%d次\n", renum);
	system("pause");
	return EXIT_SUCCESS;
}