一个好用的编码类
来源:互联网 发布:js高德地图轨迹清除 编辑:程序博客网 时间:2024/05/01 01:05
本文VC6.0工程源码下载地址:
http://code.google.com/p/serial-num/downloads/detail?name=SerialClass.rar&can=2&q=
大家好,我目前就职于一家工业制造公司,在工作中经常会碰到打印(激光标刻)序列号或流水号的问题,序列号就是某一数值对应的字符串编码,其具有计数功能。
举个例子,客户需要在一批工件上标刻序列号,每个序列号需要用5个字符标刻,即在第一个工件上标刻“00001”,在第二个工件上标刻“00002”,在第三个工件上标刻“00003”,后面的工件依次类推。
起初,碰到这样的问题时,我都会用一个整型变量和一个字符串变量来满足客户的需求,整型变量用来计数,加工的时候就将整型变量转换成字符串变量,然后标刻,每加工完成一个工件后,整型变量自增就可以了。以下是对应的代码片段:
const int WIDTH = 5;int nCount = 0;CString strCount;strCount.Format(_T("%0*d"), WIDTH, nCount++);
上面的设计思路视乎已能很好的满足客户需求了,但再想一下,要是客户的需求做了如下几种改动时,上面的设计思路是否还能满足客户的需求呢?!
1、客户要用30个字符标刻流水号,在这种情况下,流水号的最大数值已经超过了一个整型变量所能表达的范围。显然上面的代码已不能再满足客户的需求了。
2、客户要用大写英文字母标刻流水号,且除去易混淆的字符Q、I、O等,即23进制编码流水号,且每个流水号仍然用10个字符表示。显然在这种情况下,上面的代码也没法满足客户的需求了。
系统自带的数值型变量已经不能再满足个别客户的需求了,那么我们能不能自定义一个变量类型呢,若其具有以下这样一些基本属性,和一些好用的接口,那么我们是不是也能满足客户的个性流水号了呢?
1、能设置每个流水号的宽度。
2、能设置编码符号。
3、将当前编码转换成字符串变量。
4、能与整型变量进行加减运算。(为了获取下一工件的编码)
在日常生活中我们手工记流水号时,在脑海中始终是有一个数值的,即现在是第几个工件了,然后再经过思考心算,以10进制、0123456789作为编码符,最后用笔在纸上画下一串符号。但如果让我们在手工记流水号的时候,以23进制、A-Z除去Q、I、O作为编码符记录时,对我们来说,是不是就有困难了呢,特别是对记性不好的人来说(因为要知道n的编码符是个什么形状),但是我们仍然是可以完成的。只不过是,对记忆和运算能力的要求,比记普通流水号的要求要高些。
第一写博客啊,写作能力有限,不知道上面一段话大家能不能看明白,多包涵!
模拟我们的日常思维,我们就开始设计自定义变量类型吧!暂先命名为CSerialNum。
1、为了CSerialNum类的设计方便,我们先设计这样一个CRightIndexString类,其继承自CString类。
①CRightIndexString声明如下:
class CRightIndexString : public CString {public:CRightIndexString();virtual ~CRightIndexString();public://改写了CString的这个函数void SetAt(int nIndex, TCHAR ch);//改写了CString的这个函数TCHAR operator[](int nIndex) const;//ref-counted copy from another CStringconst CString& operator=(const CString& stringSrc);};
②CRightIndexString实现如下:
CRightIndexString::CRightIndexString(){}CRightIndexString::~CRightIndexString(){}TCHAR CRightIndexString::operator[](int nIndex) const{ASSERT(nIndex>=0 && nIndex<GetLength());return CString::operator[](GetLength()-nIndex-1);}void CRightIndexString::SetAt(int nIndex, TCHAR ch){ASSERT(nIndex>=0 && nIndex<GetLength());CString::SetAt(GetLength()-nIndex-1, ch);}const CString& CRightIndexString::operator=(const CString& stringSrc){return CString::operator=(stringSrc);}
设计CRightIndexString类的主要目的是为了重载CString的operator[](int nIndex) 和SetAt(int nIndex, TCHAR ch),重载后,我们能更方便的像日常思维那样计数,即低位在后面,高位在前面。
2、下面是CSerialNum类的声明与实现:
①CSerialNum类的声明:
CSerialNum::CSerialNum(int nSerialWidth, CString strCodeCharacter, CString strMinValue, CString strMaxValue){//判断有没有重复的编码符for (int n=0; n<strCodeCharacter.GetLength(); n++){if (strCodeCharacter.Find(strCodeCharacter[n]) != strCodeCharacter.ReverseFind(strCodeCharacter[n])){AfxMessageBox(_T("严重错误,编码符中存在重复的字符,请检查!"));return;}}//判断宽度和编码长度的有效性if (0>=nSerialWidth || 0>=strCodeCharacter.GetLength()){AfxMessageBox(_T("构造字符串时,宽度不能是0,且编码字符串不能为空!"));return;}//赋值给成员变量m_nSerialWidth = nSerialWidth;m_strCodeCharacter = strCodeCharacter;//设置序列号的编码范围SetRange(strMinValue, strMaxValue);//将当前序列号设为最小编码串CSerialNum::operator =(strMinValue);}CSerialNum::~CSerialNum(){}BOOL CSerialNum::PaddingStr(CString &str){#ifdef _DEBUGif (m_nSerialWidth < str.GetLength()){AfxMessageBox(_T("严重错误,序列号过长,无法前端补齐!"));return FALSE;}#endifwhile (m_nSerialWidth > str.GetLength()){str = m_strCodeCharacter[0] + str;}return TRUE;}int CSerialNum::CompSerialNum(CString str1, CString str2){PaddingStr(str1);PaddingStr(str2);int nIndex1, nIndex2;for (int n=0; n<str1.GetLength(); n++){nIndex1 = m_strCodeCharacter.Find(str1[n]);nIndex2 = m_strCodeCharacter.Find(str2[n]);if (nIndex1 > nIndex2){return 1;}else if (nIndex2 > nIndex1){return -1;}}return 0;}TCHAR CSerialNum::GetNextCode(TCHAR CrtCode, BOOL OUT &bCarry){int nCrtPosition = m_strCodeCharacter.Find(CrtCode);ASSERT(-1!=nCrtPosition);int nNextPosition = (nCrtPosition+1)%m_strCodeCharacter.GetLength();bCarry = (0==nNextPosition) ? TRUE : FALSE;return m_strCodeCharacter[nNextPosition];}BOOL CSerialNum::SetRange(CString strMinValue, CString strMaxValue){if (m_nSerialWidth < strMinValue.GetLength() || m_nSerialWidth < strMaxValue.GetLength()){AfxMessageBox(_T("设置序列号范围时,字符串过长,请检查!"));return FALSE;}if (0 >= strMinValue.GetLength() || 0 >= strMaxValue.GetLength()){AfxMessageBox(_T("设置序列号范围时,字符串过短,请检查!"));return FALSE;}if (strMinValue != strMinValue.SpanIncluding(m_strCodeCharacter) || strMaxValue != strMaxValue.SpanIncluding(m_strCodeCharacter)){AfxMessageBox(_T("设置序列号范围时,字符串含有未识别字符,请检查!"));return FALSE;}if (1 == CompSerialNum(strMinValue, strMaxValue)){AfxMessageBox(_T("设置序列号范围时,最小编码大于最大编码,请检查!"));return FALSE;}m_strMinValue = strMinValue;m_strMaxValue = strMaxValue;PaddingStr(m_strMinValue);PaddingStr(m_strMaxValue);return TRUE;}BOOL CSerialNum::operator=(const CString& stringSrc){if (m_nSerialWidth < stringSrc.GetLength() ||0>=stringSrc.GetLength()){AfxMessageBox(_T("设置当前序列号时,宽度过长或过短,请检查!"));return FALSE;}if (stringSrc != stringSrc.SpanIncluding(m_strCodeCharacter)){AfxMessageBox(_T("设置的序列号中含有未识别字符,请检查!"));return FALSE;}if (1 == CompSerialNum(stringSrc, m_strMaxValue) ||1 == CompSerialNum(m_strMinValue, stringSrc)){AfxMessageBox(_T("设置序列号时,超出了范围,请检查!"));return FALSE;}m_strCrtValue = stringSrc;PaddingStr(m_strCrtValue);return TRUE;}CSerialNum::operator CString() const{return m_strCrtValue;}CString CSerialNum::GetSerialNoPadd(void){CString strRet = m_strCrtValue;if (0 >= strRet.GetLength()){AfxMessageBox(_T("严重错误,序列号为空!"));}while (strRet[0] == m_strCodeCharacter[0]){strRet.Delete(0);}return strRet;}const CString& CSerialNum::operator++(void){BOOL bCarry = FALSE;for (int n=0; n<m_strCrtValue.GetLength(); n++){m_strCrtValue.SetAt(n, GetNextCode(m_strCrtValue[n], bCarry));//没有进位,即可结束循环if (!bCarry){break;}//最高位有进位,则已经到达最大编码,复位至最小编码if (n == (m_strCrtValue.GetLength()-1)){m_strCrtValue = m_strMinValue;break;}}if (1 == CompSerialNum(m_strCrtValue, m_strMaxValue)){m_strCrtValue = m_strMinValue;}return m_strCrtValue;}const CString& CSerialNum::operator+=(int nIncrease){ASSERT(nIncrease>=0);while (nIncrease--){operator ++();}return m_strCrtValue;}
当然,这个类肯定还有很多可以完善的地方,还请多指教!
本文VC6.0工程源码下载地址:
http://code.google.com/p/serial-num/downloads/detail?name=SerialClass.rar&can=2&q=
最后, 非常感谢你的耐心阅读!
- 一个好用的编码类
- 一个好用的中文编码过滤器的代码
- 共享一个在线base64解码编码的地址 好用
- 养成好的编码习惯----由一个bug想到的
- 一个好用的Curl的类
- 一个好用的日志工具类
- BCMenu一个好用的图形菜单类
- 一个好用的变换类TransformManager
- 一个好用的图片处理类
- 一个好用的sqlite3工具类
- 一个好用的 poi封装类
- 好用的视频编码转换工具
- 好的编码习惯
- 好的编码规范
- 好的编码习惯
- 一个好用的电子地图
- 一个好用的DBGRID
- 一个好用的DBGRID
- PCIe设备,功能,总线
- 使用图片创建不规则窗体 windows sdk
- 关于No Cortex-M Device found in JTAG chain...出现的问题
- 最佳Linux服务器发行版
- dll调用
- 一个好用的编码类
- 精通UIPasteboard 粘贴板
- NYOJ 10 Skiing 解题报告
- MPI_Gatherv函数的使用
- error while loading shared libraries 错误解决办法总结,
- c++出错问题解析
- 10幅图告诉你Pinterest的魅力所在
- Oracle数据库的十种重新启动步骤
- 用vim比较文件(Using vim to compare files)