下面是本人写的临时测试代码,有时单步运行看其他变量都没问题,唯独keyName有时能一个个正常写入,有时读到第二个section时(开始存放这行了)结果会影响到keyName[0][?]中的数据,这是怎么回事?程序大部分运行时都不能按要求存入keyName中啊,只有偶尔没问题成功的。
目的是读取任何ini配置文件中的全部节名和对应的键名,存放方式是,例:节名[section 3]下的第三个键名 为name,则keyName[2][3]中存放键值。
目的是读取任何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
在你每次调用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; }