先看题目,写一个fun函数,统计一个字符串中某个字符出现的次数,以及这个字符第一次出现的位置。
看起来很简单,似乎几行就可以搞定,但是写出来之后,才发现代码怎么这么长!程序里多处使用了指针,涵盖了下面三种用途:
(1)动态申请内存,返回指针
(2)用指针访问数组中的元素
(3)指针作为函数形参,达到返回多个值的效果
题目面临的两个问题:
(1)输入的字符串长度未知
(2)fun函数需要返回2个值
#include <stdio.h>
#include <stdlib.h>
void fun(const char* s, char c, int* count, int* first_pos);
int main()
{
int size = 10;
char* s = (char*)malloc(size); //①动态申请内存
if (s == NULL)
{
printf("memory alloc error\n");
return -1;
}
int length = 0;
char ch;
while ((ch = getchar()) != '\n')
{
if (length >= size)
{
size *= 2;
s = (char*)realloc(s, size);
if (s == NULL)
{
printf("memory alloc error\n");
return -1;
}
}
*(s + length) = ch; //②访问数组中的元素
length++;
}
*(s + length) = '\0';
printf("输入的字符串为:%s\n", s);
int count = 0;
int pos = -1;
char c = 'a';
fun(s, c, &count, &pos);
printf("字符%c出现了%d次,第一次出现的位置是%d\n", c, count, pos);
free(s);
return 0;
}
void fun(const char* s, char c, int* count, int* first_pos) //③作为函数形参,达到返回多个值的效果
{
int cnt = 0;
int pos = -1;
int i = 0;
int found_flag = 0;
while (*s != '\0')
{
if (*s == c)
{
if (found_flag == 0)
{
pos = i;
found_flag = 1;
}
cnt++;
}
s++;
i++;
}
*count = cnt;
*first_pos = pos;
}
以上程序,多处用到了指针,指针的所有操作和内存息息相关。
(1)动态申请内存,返回指针
通过指针p获得对内存的控制权。
(2)用指针访问数组中的元素
数组本身是一个变量,而变量呢,它是内存中的一块区域,所以,通过指针访问数组中的元素,实际上就是通过指针获得了变量所在内存的控制权。由于数组元素在内存中是连续分布的,所以这个指针可以通过++或者--操作访问数组里的元素,这个指针它还描述了“位置信息”。
(3)指针作为函数形参,达到返回多个值的效果
count是一个指针,它指向了原来的实参,通过指针可以直接修改原来的实参,实际上,通过指针获得了实参所在内存的控制权。
c语言的指针,灵活,但是容易出错。
程序追求三个目标“简洁、高效、安全”,c程序的错误,除了逻辑错误之外,最多的就是内存错误,“高效”是c语言的优点,但是安全性……程序员一不小心就是崩溃。
下面用c++改写程序,看不到指针了,程序更加“简洁、安全”。
(1)string是不定长字符串类型,不用动态申请内存了。
(2)有了容器和迭代器,可以不再使用c的指针了。
(3)使用引用代替指针。
#include <iostream>
using namespace std;
void fun(const string& s, char c, int& count, int& first_pos);
int main()
{
string s;
cin >> s;
cout << "输入的字符串为" << s << endl;
int count = 0;
int pos = -1;
char c = 'a';
fun(s, c, count, pos);
cout << "字符" << c << "出现了" << count << "次,第一次出现的位置是" << pos << endl;
return 0;
}
void fun(const string& s, char c, int& count, int& first_pos)
{
int cnt = 0;
int pos = -1;
int i = 0;
int found_flag = 0;
for (auto elem : s)
{
if (elem == c)
{
if (found_flag == 0)
{
pos = i;
found_flag = 1;
}
cnt++;
}
i++;
}
count = cnt;
first_pos = pos;
}