求指导遍历ini文件时,二维指针数组保存的数据有时会出问题,偶尔正常

C++语言 码拜 8年前 (2016-05-25) 1058次浏览
下面是本人写的临时测试代码,有时单步运行看其他变量都没问题,唯独keyName有时能一个个正常写入,有时读到第二个section时(开始存放这行了)结果会影响到keyName[0][?]中的数据,这是怎么回事?程序大部分运行时都不能按要求存入keyName中啊,只有偶尔没问题成功的。
目的是读取任何ini配置文件中的全部节名和对应的键名,存放方式是,例:节名[section 3]下的第三个键名 为name,则keyName[2][3]中存放键值。

#include "iostream"
#include "string"
#include "atltime.h"
#include "regex"
using namespace std;
class FileReadIn
{
public:
	int sectionCount;//计数器
	char* pSectionName[300];//保存找到的节名字符串的首地址
	char* keyName[300][300];//保存全部路径(全部键值)
	void findSectionPath()
	{
		char chSectionNames[2048] = { 0 }; //全部节名组成的字符数组
		memset(pSectionName, 0, sizeof(pSectionName));
		sectionCount = 0;
		memset(keyName, 0, sizeof(keyName));
		int j = 0;//j用来保存下一个节名字符串的首地址相对于当前i的位置偏移量
		GetPrivateProfileSectionNames(chSectionNames, 2048, "E:\test.ini");
		for (int i = 0; i < 2048; i++, j++)
		{
			if (chSectionNames[0] == "\0")//假如第一个字符就是0,则说明ini中一个节也没有
			{
				cout << "配置文件中一个节也没有" << endl;
				break;
			}
			else if (chSectionNames[i] == "\0")
			{
				cout << "找到一个节名" << endl;//断点1
				char* temp = &chSectionNames[i - j];	//找到一个0,则说明从这个字符往前,减掉j个偏移量,就是一个节名的首地址
				cout << temp << endl;      //把找到的显示出来
				//找每个节名下的全部键
				{
					LPCSTR str1 = temp;
					char keyNamesAll[300] = { 0 };
					GetPrivateProfileString(str1, NULL, NULL, keyNamesAll, sizeof(keyNamesAll), "E:\test.ini");
					int k = 0;
					int keyCount = 0;
					for (int i = 0; i < 2048; i++, k++)
					{
						if (keyNamesAll[0] == "\0")//假如第一个字符就是0,则说明ini中一个节也没有
						{
							cout << "当前节中一个键也没有" << endl;
						}
						else if (keyNamesAll[i] == "\0")
						{
							cout << "找到一个键名" << endl;//断点2
							char* tempStr = &keyNamesAll[i - k];//找到一个0,则说明从这个字符往前,减掉j个偏移量,就是一个节名的首地址
							cout << tempStr << endl;      //把找到的显示出来
							keyName[sectionCount][keyCount] = tempStr;
							k = -1;
							keyCount++;
							if (keyNamesAll[i + 1] == 0)//当两个相邻的字符都是0时,则全部的节名都已找到,循环终止
							{
								break;
							}
						}
					}
				}//已找完该节名下的键名
				pSectionName[sectionCount] = temp;
				j = -1;
				sectionCount++;
				if (chSectionNames[i + 1] == 0)//当两个相邻的字符都是0时,则全部的节名都已找到,循环终止
				{
					break;
				}
			}
		}
		cout << "as" << endl;//断点3
	}
};
int main()
{
	FileReadIn A;
	A.findSectionPath();
	cout << "ffffgg"<< endl;//断点
	system("PAUSE");
	return 0;
}
解决方案

20

首先回答你的问题,为什么keyName值会被覆盖?你的keyName数组里存的是字符串地址,而这个地址来源于你定义的一个局部数组char keyNamesAll[300] = { 0 },
在你每次调用GetPrivateProfileString(str1, NULL, NULL, keyNamesAll, sizeof(keyNamesAll), “C:\test.ini”)函数时,这个
数组中存放的字符都会发生变化,当ini文件解析结束后,这个数组中存放的就是最后一个section中的全部keyName,这就是为什么当解析第2个section时,keyName[0][*]
变化的原因。原因是keyNamesAll中存放的字符已经变化了,而keyName中存放的只是keyNamesAll某个offset的地址,keyName内存放的值当然随着keyNamesAll的
变化而变化了。
其次,你这样的写法也是不对的,局部变量超出其作用域,就不应该被引用了,而在你的程序中使用类的成员变量存储了局部变量的地址,这无疑超出了局部变量的作用域。
建议你可以使用vector, map

#include "iostream"
#include "string"
#include "atltime.h"
#include "regex"
#include <vector>
#include <map>
using namespace std;
class FileReadIn
{
public:
	int sectionCount;//计数器
	vector<string> sectionNames;//保存找到的节名字符串的首地址
	map<string, vector<string> > sectionNameToKeys;//保存全部路径(全部键值)
	void findSectionPath()
	{
		char chSectionNames[2048] = { 0 }; //全部节名组成的字符数组
		char keyNamesAll[300] = { 0 };
		int j = 0;//j用来保存下一个节名字符串的首地址相对于当前i的位置偏移量
		GetPrivateProfileSectionNames(chSectionNames, 2048, "C:\TestSetup_XSIM7.ini");
		for (int i = 0; i < 2048; i++, j++)
		{
			if (chSectionNames[0] == "\0")//假如第一个字符就是0,则说明ini中一个节也没有
			{
				cout << "配置文件中一个节也没有" << endl;
				break;
			}
			else if (chSectionNames[i] == "\0")
			{
				cout << "找到一个节名" << endl;//断点1
				char* temp = &chSectionNames[i - j];	//找到一个0,则说明从这个字符往前,减掉j个偏移量,就是一个节名的首地址
				cout << temp << endl;      //把找到的显示出来
				vector<string> keys;
				//找每个节名下的全部键
				{
					LPCSTR str1 = temp;

					GetPrivateProfileString(str1, NULL, NULL, keyNamesAll, sizeof(keyNamesAll), "C:\TestSetup_XSIM7.ini");
					int k = 0;
					int keyCount = 0;

					for (int i = 0; i < 2048; i++, k++)
					{
						if (keyNamesAll[0] == "\0")//假如第一个字符就是0,则说明ini中一个节也没有
						{
							cout << "当前节中一个键也没有" << endl;
						}
						else if (keyNamesAll[i] == "\0")
						{
							cout << "找到一个键名" << endl;//断点2
							char* tempStr = &keyNamesAll[i - k];//找到一个0,则说明从这个字符往前,减掉j个偏移量,就是一个节名的首地址
							cout << tempStr << endl;      //把找到的显示出来
							keys.push_back(string(tempStr));
							k = -1;
							keyCount++;
							if (keyNamesAll[i + 1] == 0)//当两个相邻的字符都是0时,则全部的节名都已找到,循环终止
							{
								break;
							}
						}
					}
				}//已找完该节名下的键名
				sectionNames.push_back(string(temp));
				sectionNameToKeys[string(temp)] = keys;
				j = -1;
				sectionCount++;
				if (chSectionNames[i + 1] == 0)//当两个相邻的字符都是0时,则全部的节名都已找到,循环终止
				{
					break;
				}
			}
		}
		cout << "as" << endl;//断点3
	}
};
int main()
{
	FileReadIn A;
	A.findSectionPath();
	cout << "ffffgg"<< endl;//断点
	system("PAUSE");
	return 0;
}

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明求指导遍历ini文件时,二维指针数组保存的数据有时会出问题,偶尔正常
喜欢 (0)
[1034331897@qq.com]
分享 (0)