首先,指针存的是内存地址。有指针类型的区分就是限制在这个内存地址能进行什么操作。比如int *的指针就用int限定了这个内存开始存的一个int数据。操作范围也是int数据的大小。函数指针再结合函数的申明就可以指定在该函数的内存地址上可以怎么执行方法喽。C#的委托也是这个意思,封装层面高一些。
通过对指针的理解,以前一直费解的C#里的IntPtr是个什么东西也能深刻理解了。
指针=带有说名约定的内存地址
IntPtr=没有约定的通用内存地址
把指针赋值给IntPtr来传递,直到使用时候按照约定还原指针后按约定操作对象。
指针能干什么
1.用变量传递函数
2.模块互操作
3.通过内存地址和方法约定驱动方法?
指针练习部分
#include "MainUtil.h"
//得到两个字符串的总长度
string StrTotalLen(string ruleStr, string curNo);
//定义一个通过两个字符串返回一个字符串的指针,具体两个字符串返回一个什么功效不知道
string(*TowRetOne) (string,string);
//通过GetNextNo获得函数类型定义函数指针,和上一行效果一样,上面的可读性好
decltype(GetNextNo)* TowRetOne1;
//申明一个空的函数头
string TowRetOneDec (string, string);
//得到函数指针
decltype(TowRetOneDec) * GetFunPoint(const string &);
int main()
{
string nextNo = "";
string ruleStr = "[[\"$y1\"],[\"$y2\"],[\"$y3\"],[\"$y4\"],[\"$M1\"],[\"$M2\"],[\"$d1\"],[\"$d2\"],[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"],[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"],[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"]]";
cout << "函数指针方面" << endl;
//把通过规则和当前号得到下一号的函数赋值给指针
TowRetOne = GetNextNo;
//函数指针1
if (TowRetOne != NULL)
{
string curNo = "";
nextNo=TowRetOne(ruleStr, curNo);
cout << "通过函数指针TowRetOne调用获得下一号:" << nextNo<<endl;
}
TowRetOne1 = GetNextNo;
//函数指针2
if (TowRetOne1 != NULL)
{
nextNo = TowRetOne1(ruleStr, nextNo);
cout << "通过函数指针TowRetOne1调用获得下一号:" << nextNo << endl;
}
cout << "通过名称驱动方法" << endl;
//通过变量传递指针
decltype(TowRetOneDec)* funPtr=GetFunPoint("GetNextNo");
if (funPtr != NULL)
{
nextNo=funPtr(ruleStr, nextNo);
cout << "通过名称驱动方法GetNextNo:" << nextNo << endl;
}
//通过变量传递指针
decltype(TowRetOneDec)* funPtr1 = GetFunPoint("StrTotalLen");
if (funPtr1 != NULL)
{
nextNo = funPtr1(ruleStr, nextNo);
cout << "通过名称驱动方法StrTotalLen:" << nextNo << endl;
}
cout << "理解句柄" << endl;
//给句柄地址赋值的什么类型的指针,在使用时候一样申明类型。然后把句柄转换成正确类型指针就能通过指针操作对象
//把指针转换为地址的句柄,把指针的内存地址存在intptr里和系统地址一样长度的数据类型
intptr_t intptrTest = (intptr_t)funPtr1;
//通过句柄得到指针
decltype(TowRetOneDec)* funPtr2 = (decltype(TowRetOneDec)*)intptrTest;
if (funPtr2 != NULL)
{
nextNo = funPtr2(ruleStr, nextNo);
cout << "通过句柄驱动方法StrTotalLen:" << nextNo << endl;
}
//使用放得到地址后转换实际的指针类型调用方法.如果是对象的话就是操作对象
return 0;
}
//得到两个字符串的总长度
string StrTotalLen(string str1, string str2)
{
string retStr= "传入两个字符串的总长度是:" + IntToStr(str1.length() + str2.length());
return retStr;
}
//多态化第一步
//通过名称得到方法指针
decltype(TowRetOneDec)* GetFunPoint(const string& Code)
{
if (Code == "GetNextNo")
{
return GetNextNo;
}
else if (Code == "StrTotalLen")
{
return StrTotalLen;
}
else
{
return NULL;
}
}
基础头文件
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <sstream>
using std::string;
using std::vector;
using std::stringstream;
using std::cin;
using std::cout;
using std::endl;
//通过规则串和当前号得到下一号
//ruleStr:规则串 例如:[[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"],[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"],[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"]]
//curNo:当前号 例如:259
string GetNextNo(string ruleStr, string curNo);
//分隔字符串得到向量数组
//str:字符串
//spChar:分隔字符
vector<string> Split(string str, char spChar);
//替换字符串里的指定字符串为新字符串
//str:原字符串
//oldValue:要替换的字符串
//newValue:新字符串
string ReplaceAll(string str, const string oldValue, string newValue);
//把int处理成字符串
string IntToStr(int num);
//处理规则编号的特殊串
string DealSpecialStr(string ruleNo);
基础实现代码
#include "MainUtil.h"
//通过规则串和当前编号得到下一号
//ruleStr:规则串 例如:[[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"],[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"],[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"]]
//curNo:当前号 例如:259
string GetNextNo(string ruleStr, string curNo)
{
if (ruleStr.length() == 0)
{
return "-1^没有传入规则串!";
}
ruleStr = ReplaceAll(ruleStr, "],[", "^");
ruleStr = ReplaceAll(ruleStr, "\"", "");
ruleStr = ReplaceAll(ruleStr, "[", "");
ruleStr = ReplaceAll(ruleStr, "]", "");
//分隔第一层二维数组
vector<string> vecArrRule = Split(ruleStr, '^');
if (curNo.length() > 0 && curNo.length() != vecArrRule.size())
{
return "-1^规则定义的串长度和当前号长度不一致!";
}
//完全解析的规则串
vector<vector<string>> vecArrRuleTow;
//记录当前号在没位的位置
vector<size_t> indexArr;
//存每位的数量
vector<size_t> countArr;
int curOneIndex = -1;
//迭代遍历每位规则
for (auto one = vecArrRule.begin(); one < vecArrRule.end(); one++)
{
curOneIndex++;
string oneRule = *one;
//每一位的可走范围
vector<string> oneRuleArr = Split(oneRule, ',');
vecArrRuleTow.push_back(oneRuleArr);
size_t curTowIndex = -1;
bool hasIn = false;
for (auto tow = oneRuleArr.begin(); tow < oneRuleArr.end(); tow++)
{
curTowIndex++;
//记录当前位所在的位置
if (curNo.length() == 0 || curNo[curOneIndex] == (*tow)[0] || ((*tow)[0] == '$'))
{
indexArr.push_back(curTowIndex);
countArr.push_back(oneRuleArr.size());
hasIn = true;
break;
}
}
if (hasIn == false)
{
return "-1^编号与规则不匹配!";
}
}
//得到下一号位置
if (curNo.length() > 0 && indexArr.size() > 0)
{
for (int i = indexArr.size() - 1; i >= 0; i--)
{
if (indexArr[i] + 1 < countArr[i])
{
indexArr[i]++;
break;
}
else if (i > 0)
{
indexArr[i] = 0;
}
else
{
return "-1^已经到最大号了!";
}
}
}
string retNo = "";
int curIndex = -1;
//按位置得到下一号
for (auto a = indexArr.begin(); a < indexArr.end(); a++)
{
curIndex++;
retNo += vecArrRuleTow[curIndex][(*a)];
}
return DealSpecialStr(retNo);
}
//分隔字符串为向量数组
//str:字符串
//spChar:分隔字符
vector<string> Split(string str, char spChar)
{
vector<string> retArr;
if (str.length() == 0)
{
retArr.push_back("");
return retArr;
}
string tmp;
for (int i = 0; i < str.length(); i++)
{
if (str[i] == spChar)
{
retArr.push_back(tmp);
tmp = "";
continue;
}
tmp += str[i];
}
if (tmp.length() > 0)
{
retArr.push_back(tmp);
}
return retArr;
}
//替换所有字符串
//str:原字符串
//oldValue:要替换的字符串
//newValue:新字符串
string ReplaceAll(string str, const string oldValue, string newValue)
{
for (auto pos(0); pos != string::npos; pos += newValue.length())
{
if ((pos = str.find(oldValue, pos)) != string::npos)
{
str.replace(pos, oldValue.length(), newValue);
}
else
{
break;
}
}
return str;
}
//处理特殊串
string DealSpecialStr(string ruleNo)
{
// 基于当前系统的当前日期/时间
time_t now = time(0);
tm ltm;
localtime_s(<m,&now);
int year = ltm.tm_year + 1900;
int month = ltm.tm_mon + 1;
int day = ltm.tm_mday;
int hour = ltm.tm_hour;
int min = ltm.tm_min;
int sec = ltm.tm_sec;
string yearStr = "";
ruleNo = ReplaceAll(ruleNo, "$y1", IntToStr(year).substr(0, 1));
ruleNo = ReplaceAll(ruleNo, "$y2", IntToStr(year).substr(1, 1));
ruleNo = ReplaceAll(ruleNo, "$y3", IntToStr(year).substr(2, 1));
ruleNo = ReplaceAll(ruleNo, "$y4", IntToStr(year).substr(3, 1));
string monthStr = IntToStr(month);
if (monthStr.size() == 1)
{
monthStr = "0" + monthStr;
}
string dayStr = IntToStr(day);
if (dayStr.size() == 1)
{
dayStr = "0" + dayStr;
}
string hourStr = IntToStr(hour);
if (hourStr.size() == 1)
{
hourStr = "0" + hourStr;
}
string minStr = IntToStr(min);
if (minStr.size() == 1)
{
minStr = "0" + minStr;
}
string secStr = IntToStr(sec);
if (secStr.size() == 1)
{
secStr = "0" + secStr;
}
ruleNo = ReplaceAll(ruleNo, "$M1", monthStr.substr(0, 1));
ruleNo = ReplaceAll(ruleNo, "$M2", monthStr.substr(1, 1));
ruleNo = ReplaceAll(ruleNo, "$d1", dayStr.substr(0, 1));
ruleNo = ReplaceAll(ruleNo, "$d2", dayStr.substr(1, 1));
ruleNo = ReplaceAll(ruleNo, "$h1", hourStr.substr(0, 1));
ruleNo = ReplaceAll(ruleNo, "$h2", hourStr.substr(1, 1));
ruleNo = ReplaceAll(ruleNo, "$m1", minStr.substr(0, 1));
ruleNo = ReplaceAll(ruleNo, "$m2", minStr.substr(1, 1));
ruleNo = ReplaceAll(ruleNo, "$s1", secStr.substr(0, 1));
ruleNo = ReplaceAll(ruleNo, "$s2", secStr.substr(1, 1));
return ruleNo;
}
//整数转换字符串
string IntToStr(int num)
{
string res;
stringstream ss;
ss << num;
ss >> res;
return res;
}