Reading INI with C++ Code help

Hi everyone, I was hoping that someone can help me with my code.

I have been reviewing GetPrivateProfileString and overall I believe that I have a basic understanding of it. I am trying to read this Ini file which ill list further down but the issue I have with the code is when I compile it, there is a error in regards to access violation that apprears during debuging.

As well what I would like to note too is where "LPSTR szResult = "\0",if I take out the null value and compile it, the code in turns says run time check failure #3. The Variable 'szResult' is being used without being initialized.

I am wondering what I have been doing wrong in the code and would appreciate any assistance to fixing the code as well as any advice you can share with me in regards to GetPrivateProfileString.

Thanks for taking the time to read this and the code. Hope to read some great advice and assistance to fixing this code.

The INI file I am trying to Read:
----------------------------------
[Core]
Status=P
Time=00:18:34
Location=66107
Score=20
[Obj_Status]
ID.0=02015090020
[Core_Point]
Completion=
Times= 212 332
Responses=12213
Jumps=12

My Code
---------------------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "stdafx.h"
#include <Windows.h>
#include <string>
#include <iostream>
#include <stdio.h>

long m_lRetVal;			// return value from the WIN32 API CALLS
const char* m_szFileName;
const char* szSection;		// points to section name 
const char* szKey;		// points to key name 
const char* szDefaultValue;	// points to default string

LPSTR ReadKeyString(LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR);

LPSTR ReadKeyString(LPCTSTR szSection, LPCTSTR szKey, LPCTSTR szDefaultValue,
LPCTSTR m_szFileName) //read the file
{
LPSTR szResult = "\0";

m_lRetVal = GetPrivateProfileString(szSection, szKey, szDefaultValue, szResult, 255, m_szFileName);

return szResult;
}


int _tmain(int argc, _TCHAR* argv[])
{
LPSTR test;
test = ReadKeyString((LPCTSTR) "Core", (LPCTSTR) "Lesson_Location",(LPCTSTR) "?",(LPCTSTR) "C:\\PARAM.INI");
std::cout << "test " << test << std::endl;
system("pause");
return 0;
}
Last edited on
Need to cast? You're doing it wrong.

It seems you're mixing ASCII and Unicode strings without proper conversion.

You can just specify the strings as Unicode, for example L"Core". If fact, what you're supposed to do is use the _T macro as in _T("Core").
Huh, didnt know about that. Learned something new, appreciate it kbw.
yes, i would need this to cast as well, but i think at the moment im just trying to get something back besides errors.

Ok, so i would need to rethink changing the ReadKeyString to be specified to unicode and in turn this will help it run? Or is the entire structure of the program wrong and i need to rethink how to code this again? Would that also mean that I would need to not use LPCTSTR too?

As well when i was looking for GetPrivateProfileString examples they really didnt show or explain conversions with this function, so i appreciate you letting me know about this.

Could you explain this to me in a bit more detail please? Just want to make sure I know exactly how things work just in case in the furture I need to use this function for another program. Thank you.
Last edited on
IF you take a look at that LPTSTR thing and its defivatives (LPCTSTR ...), you'll find that the definition changes with Unicode settings. If you're using the native Uncode interface, it's defined to be a wchar_t*; if _UNICODE is not defined, it's defined as a char*. As your code mostly uses these definitions, you don't need to change them.

However, you will need to revisit this code:
1
2
3
LPSTR szResult = "\0";  // szResult points to a constant 4 constant byte block (wchar_t[2]).

m_lRetVal = GetPrivateProfileString(szSection, szKey, szDefaultValue, szResult, 255, m_szFileName);

The call is expecting szResult to point to a writeable buffer of size 255 bytes.
I have done some changes to the code as per your suggestions but I am wondering about one section. Maybe im not seeing it or perhaps I may have just missed a simple character change but.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
long m_lRetVal;
const char* m_szFileName;
const char* szSection;
const char* szKey;
const char* szDefaultValue;

wchar_t* szResult= L"\0";  //changed this to be more unicode friendly
//Changed LPSTR to LPWSTR so it can return the szResult
LPWSTR ReadKeyString(LPCTSTR szSection, LPCTSTR szKey, LPCTSTR szDefaultValue, LPCTSTR m_szFileName) 
{
	m_lRetVal = GetPrivateProfileString(szSection, szKey, szDefaultValue, szResult //when i look szResult shows that the argument of type "wchar_T*" is incompatible with parameter type LPSTR
                                            , 255, m_szFileName);
	return szResult;
}

int _tmain(int argc, _TCHAR* argv[])
{
	LPWSTR ReadKeyString(LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR);
	LPWSTR test;
	test = ReadKeyString(_T("Core"), _T("Location"), _T("?"), _T("C:\\PARAM.INI"));
	std::cout << "test " << test << std::endl;
	system("pause");
	return 0;
}


Guess what im trying to understand is how to get past the error in which it cannot convert that parameter from 'wchar_t *' to 'LPSTR'. Feel like im on the right track but hope im not still doing this wrong.
You still haven't created a large enough writeable buffer to receive the value from the file.
ah, ok so just by changing 255 to something like 1024.
 
m_lRetVal = GetPrivateProfileString(szSection, szKey, szDefaultValue, szResult, 1024, m_szFileName);


or more so in the regards of:
1
2
char buffer[4096]
m_lRetVal = GetPrivateProfileString(szSection, szKey, szDefaultValue, szResult, sizeof(buffer), m_szFileName);
Last edited on
The second example is more like it. Do you now understand why what you had before was incorrect?
yes, it makes a lot more sense now when it comes down to how i had it previously.
Its helped me with understanding the actual function overall and how there are 2 differnet getprofilestrings that the system can call threw the regards of ASCII and Unicode as well as conversion and knowing the size is important.

Now All i gotta do is find a way to fix the szResult incompatability param on line 11 and ill be all set! Would greatly appreciate this final help kbw.
Last edited on
Its all good, kbw. I found the issue after rethinking about what you had told me about the LPCSTR as well as the code being ASCII/Unicode friendly. It now runs.

Though I did get 2 warnings in regards to
(the returning address being local/temp and the buffer being a unreferenced local variable)
it looks like it found what i was looking for but would those be any trouble in your opinion if left unchecked?

Really Glad to have had your help and once again appreciate it!

Looks like I can go to the next steps of what i want to do with it. Also was thinking about printing the entire INI file to the console but that shouldnt be that hard (hopefully haha)

// This is the code I was able to get, though with 2 warnings C4172 and C4101
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include "stdafx.h"
#include <Windows.h>
#include <string>
#include <iostream>
#include <stdio.h>
#include <tchar.h>

long m_lRetVal;			    // return value from the WIN32 API CALLS
const char* m_szFileName;         
const char* szSection;
const char* szKey;
const char* szDefaultValue;
LPCSTR ReadKeyString(LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR);

LPCSTR ReadKeyString(LPCTSTR szSection, LPCTSTR szKey, LPCTSTR szDefaultValue, LPCTSTR m_szFileName)
{
	char szResult[4096];
	char buffer[4096];
	m_lRetVal = GetPrivateProfileString(szSection, szKey, szDefaultValue, szResult,	sizeof(buffer), m_szFileName);

	return szResult;
}

int _tmain(int argc, _TCHAR* argv[])
{
	LPCSTR test;
	test = ReadKeyString(_T("Core"), _T("Location"), _T("?"), _T("C:\\PARAM.INI"));
	std::cout << "test " << test << std::endl;
	system("pause");
	return 0;
}
Last edited on
Please note that there's a std::wcout that can be used to write out Unicode strings. on MS compilers.
will keep that in mind and thanks!
Topic archived. No new replies allowed.