MFC中CList使用方法以及项目踩坑

最近项目里一个问题要用到容器存储数据,因为C++的stl容器在MFC中不能用,因为会引起运算符重载,所以只能用MFC中的CList容器,但是csdn上的CList博客都是抄来抄去,也没有具体的用法实例,太恶心了,自己折腾了半天才找到遍历CList容器的方法;
1.CList容器基本操作:

标题/末尾访问
GetHead 返回列表的标题元素(不能为空)
GetTail 返回列表的末尾元素(不能为空)

操作
RemoveHead 从列表标题中移走元素
RemoveTail 从列表末尾移走元素
AddHead 添加一个元素(或另一个列表的所有元素)到列表标题(生成新的标题)
AddTail 添加一个元素(或另一个列表的所有元素)到列表尾部(生成新的尾部)
RemoveAll 从列表中移走所有元素

循环
GetHeadPosition 返回列表标题元素的位置
GetTailPosition 返回列表尾部元素的位置
GetNext 先返回本位置的元素,然后位置指针指向后一个元素
GetPrev 先返回本位置的元素,然后位置指针指向前一个元素

获取/修改
GetAt 在指定位置上获得元素
SetAt 在指定位置上设置元素
RemoveAt 从列表中删除一个由位置确定的元素

插入
InsertBefore 在指定位置前插入一个新的元素
InsertAfter 在指定位置后插入一个新的元素

查找
Find 获得由指针值确定的元素位置
FindIndex 获得由基于零的索引指定的元素位置

状态
GetCount 返回此列表中的元素数
IsEmpty 检测空列表的情况(没有元素)

2.遍历CList容器实例
(1)for循环遍历元素(第一种方法)

    CList<int> mList;
	POSITION posi; /*不能像数组一样用下标遍历CList容器,必须用POSITION变量表示位置*/
	CString str;

	for (int i = 0; i < 5; i ++)
	{
		mList.AddTail(i);/*从尾部插入数据*/
	}

	/*CList容器获取尾部指针的函数是获取最后一个元素的位置,
	而不是跟STL容器一样得到最后一个元素后面的位置,
	所以在循环中不能用posi != mList.GetTailPosition()作为判断条件,会导致最后一个数据无法读取
	*/
	for (posi = mList.GetHeadPosition(); posi != NULL; mList.GetNext(posi))
	{
		/*GetAt()中的参数必须是POSITION变量,用0, 1之类的整数下标是不行的*/
		str.AppendFormat(_T("%d "), mList.GetAt(posi));
	}

(2)while循环遍历元素(第二种方法)

    CList<int> mList;
	POSITION posi; /*不能像数组一样用下标遍历CList容器,必须用POSITION变量表示位置*/
	CString str;

	for (int i = 0; i < 5; i ++)
	{
		mList.AddTail(i);
	}

	/*CList容器获取尾部指针的函数是获取最后一个元素的位置,
	而不是跟STL容器一样得到最后一个元素后面的位置,
	所以在循环中不能用posi != mList.GetTailPosition()作为判断条件,会导致最后一个数据无法读取
	*/
	posi = mList.GetHeadPosition();

	while(posi != NULL)
	{
		/*GetNext函数先返回当前位置的值,位置指针再指向后一个元素*/
		str.AppendFormat(_T("%d "), mList.GetNext(posi));
	}

(3)while循环遍历元素(第三种方法)

    CList<int> mList;
	POSITION posi; /*不能像数组一样用下标遍历CList容器,必须用POSITION变量表示位置*/
	CString str;

	for (int i = 0; i < 5; i ++)
	{
		mList.AddTail(i);
	}

	/*CList容器获取尾部指针的函数是获取最后一个元素的位置,
	而不是跟STL容器一样得到最后一个元素后面的位置,
	所以在循环中不能用posi != mList.GetTailPosition()作为判断条件,会导致最后一个数据无法读取
	*/
	posi = mList.GetHeadPosition();

	while(posi != NULL)
	{
	    /*跟第二种方法差不多*/
		str.AppendFormat(_T("%d "), mList.GetAt(posi));
		mList.GetNext(posi);
	}
	
	AfxMessageBox(str);

最后的运行结果都一样,如下图:
MFC中CList使用方法以及项目踩坑_第1张图片

3.项目里用到CList的地方
有个地方会收到如下报文内容:

  • SV: 1 ELEV: 0 AZI: 0 SNR: 41
    现在要获取SV的信号值和SNR的信号值,也就是1和41,但是有一个问题,报文内容可能有多条指令,而且数量不限,如下:
  • SV: 5 ELEV: 4 AZI: 116 SNR: 32
  • SV: 12 ELEV: 14 AZI: 95 SNR: 30
  • SV: 13 ELEV: 34 AZI: 42 SNR: 31
  • SV: 15 ELEV: 47 AZI: 40 SNR: 33
    也有可能如下:
  • SV: 20 ELEV: 45 AZI: 319 SNR: 34
  • SV: 24 ELEV: 75 AZI: 154 SNR: 39
  • SV:193 ELEV: 0 AZI: 0 SNR: 39
  • SV:194 ELEV: 0 AZI: 0 SNR: 35
  • SV:195 ELEV: 0 AZI: 0 SNR: 32
  • SV: 41 ELEV: 0 AZI: 0 SNR: 41
  • SV:206 ELEV: 64 AZI: 319 SNR: 37
  • SV:218 ELEV: 0 AZI: 0 SNR: 29
  • SV:219 ELEV: 61 AZI: 21 SNR: 39
    那么面对这些不定量条数的数据,想把每一个SV和SNR的值读出来,用容器去存储自然是比较容易的办法,接下来是我的处理思路以及代码:
/*(1) 先定义一个结构体,同时包含SV和SNR两个数据*/
	typedef struct _Signal
	{
		int svSignal;
		int snrSignal;
	}mSignal;

	/*(2) 信号读取函数代码*/
	BOOL GetAllSignal(CList<mSignal>& sig, char* recvMsg)
	{
		if(recvMsg == NULL || !(strstr(recvMsg, "SV")) || !(strstr(recvMsg, "SNR")) || !(strstr(recvMsg, ":")))
		{
			return FALSE;
		}
	
		BOOL bRet = TRUE;
		char getSig[50] = {0};
		int i = 0;
		mSignal tempSig;
	
		while (*(recvMsg++) != '\0')
		{
		    /*每一条报文都是先找到SV字符的位置,并读取值*/
			if((recvMsg = strstr(recvMsg, "SV")) == NULL) 
			{
				break;
			}
			//cout << recvMsg << endl;
	
			while (*recvMsg != '\0' && !(*recvMsg >= '0' && *recvMsg <= '9')) recvMsg++;
			while((*recvMsg != '\0') && (*recvMsg >= '0' && *recvMsg <= '9')) 
			{
				getSig[i++] = *recvMsg;
				recvMsg++;
			}
	
			i = 0;
			tempSig.svSignal = atoi(getSig);
			memset(getSig, '\0', sizeof(getSig));
	
	        /*找到SNR字符的位置,并读取值*/
			if((recvMsg = strstr(recvMsg, "SNR")) == NULL) 
			{
				break;
			}
			//cout << recvMsg << endl;
	
			while (*recvMsg != '\0' && !(*recvMsg >= '0' && *recvMsg <= '9')) recvMsg++;
			while((*recvMsg != '\0') && (*recvMsg >= '0' && *recvMsg <= '9')) 
			{
				getSig[i++] = *recvMsg;
				recvMsg++;
			}
	
			i = 0;
			tempSig.snrSignal = atoi(getSig);
			memset(getSig, '\0', sizeof(getSig));
			sig.AddTail(tempSig);
			recvMsg--;
		}
	
		return bRet;
	}

    /*(3)手动模拟一些信号进行测试*/
    CList<mSignal> allSignal;
	//char signals[200] = {"* SV:  1  ELEV:  0  AZI:    0  SNR: 41"};
	char signals[200] = {"* SV:  5  ELEV:  0  AZI:    0  SNR: 33\n* SV:  7 ELEV:  0  AZI:    0  SNR: 55\n* SV:  16 ELEV:  0  AZI:    0  SNR: 65"};
	CString str;

	GetAllSignal(allSignal, signals);

	for (POSITION posi = allSignal.GetHeadPosition(); posi != NULL; allSignal.GetNext(posi))
	{
		str.AppendFormat(_T("SV:%d SNR:%d\n"),	allSignal.GetAt(posi).svSignal, allSignal.GetAt(posi).snrSignal);
	}

	AfxMessageBox(str);

代码运行结果如下:
MFC中CList使用方法以及项目踩坑_第2张图片

你可能感兴趣的:(MFC中CList使用方法以及项目踩坑)