CString - Capitalizing every first letter in a word

Hello,

I'm building an agenda in MFC.
I use some EditControl boxes that have CString variables attached to them.
I want to process the data that is inserted in a way that a string that looks like:
"bILL gATES" will become "Bill Gates" - capitalize every first letter and make lower the others.

At the first i tried to just capitalize the first letter.
The problem is that CString has functions just for making all the string in lowercase or uppercase,

If i'm trying for a variable CString name:

name[0]=towupper(name[0]);
i get: "Expression must be a modifiable lvalue";


so i've converted CString data to wchar_t ( i need it wchar_t to support UTF-8 characters)
The big issue is that i cannot declare the wchar_t variable like : wchar_t name2 [nr_of_characters],
because the CString length for name can be variable, so i've tried something like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void Agenda::Format (CString& name)
{
	bool first=true;//if its the first letter of every word
	int i;
	wchar_t name2=(wchar_t)LPCTSTR(name);// converts CString to wchar_t;
	for (i = 0; i < wcslen(&name2)+1; i++)
	{
		 if (iswspace(name2[i]))//if its a space goes to the next character
		 {
			 first=true;
			 continue;
		 }
		 if (first == true)
		 {
			 name2[i] = towupper(name2[i]);
			 first = false;
		 }
	}
}



it doesn't work, i get an error for "name2[i]" : "expression must have pointer to object type"


I have run out of ideas and i have to finish this for school.
This is the last thing that i have to implement for the agenda.
If anyone has some ideas it would be great.
Last edited on
This line

wchar_t name2=(wchar_t)LPCTSTR(name);

is getting the address of the string in the CString name, as a const pointer (hence the C in LPCTSTR)

and then telling the compiler to force 16 bits of the pointer value (which will be 32-bit or 64 bit, depending on how you compile it) into a single wchar_t (wide char) variable. So you end up with just one character.

If you want to modify the string in a CString's buffer, you need to obtain write access by call GetBuffer(), rather than using the LPCTSTR cast (which is intended for readonly access.)

1
2
3
4
5
6
7
8
void Agenda::Format (CString& name)
{
	bool first=true;//if its the first letter of every word
	int i;
	LPTSTR name2=name.GetBuffer();//get writable pointer to CString's buffer
	for (i = 0; i < wcslen(name2); i++) // lost the address-of operator (&) and the +1
	{
 		 // etc 


or slightly better

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void Agenda::Format (CString& name)
{
	bool isFirst = true;//if it's the first letter of every word
	LPTSTR buff = name.GetBuffer();
	int    len  = name.GetLength();
	for (int i = 0; i < len; ++i)
	{
		if (iswspace(buff[i]))//if it's a space goes to the next character
		{
			isFirst = true;
			continue;
		}
		if (isFirst)
		{
			buff[i] = towupper(buff[i]);
			isFirst = false;
		}
	}
}


BUT you can avoid the need to access the buffer by using SetAt to set the char (which avoids the "Expression must be a modifiable lvalue" error you hit before.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void Agenda::Format (CString& name)
{
	bool isFirst = true;//if it's the first letter of every word
	for (int i = 0; i < name.GetLength(); ++i)
	{
		if (iswspace(name[i]))//if it's a space goes to the next character
		{
			isFirst = true;
			continue;
		}
		if (isFirst)
		{
			name.SetAt(i, towupper(name[i])); // set using SetAt
			isFirst = false;
		}
	}
}

Andy
Last edited on
Its clear now what it went wrong.
I used the last version.
My agenda is finished.
Thanks for your support, means a lot.

Gabi.
Topic archived. No new replies allowed.