Pointers problem

Started by gromit, June 05, 2012, 11:17:12 AM

Previous topic - Next topic

gromit

wchar_t  *ptrstrold=L"X";
wchar_t  *ptrstrnew=L"X";   
GetDlgItemText(hDlg, UNIT_STATIC,ptrstrold,len+1); // got text from static control

GetDlgItemText(hDlg, UNIT_QTY_COMBO,ptrstrnew,len+1);   // got text from qty combo

e.g
static control text = "1 No widget"
UNIT_QTY_COMBO text = "5"
I want ptrstrnew to read    "5 No widget"

if i + 1 on ptrstrold i am left with " No widget"

how do i add ptrstrold to ptrstrnew to give result ptrstrnew = "5 No widget"
i know i could do it with strings but i would like to understand pointers more.

Sorry if its obvious
but at the moment not to me...... :-[
BTIA Gromit

gromit

i now find some curiosity in this
concentrating on ptrstrold only
ptrstrold=ptrstrold+sizeof(wchar_t)*1 results in an empty string when i try to print ptrstrold
ptrstrold=ptrstrold+1 results in an empty string
ptrstrold=ptrstrold+4 and ptrstrold=ptrstrold+sizeof(wchar_t)*4
both result in the string minus the the first four characters
i only want to lose the first 1 or 2 ???
Doh

gromit

Just got to come back on this
ptrstrold=ptrstrold+3 or 2 or 1 results in an empty string
ptrstrold=ptrstrold+ 4 or more knocks off the front of the string 4 or more characters

so ptrstrold=ptrstrold+ 4 results in "Four/Characters" becoming "/characters"
But
ptrstrold=ptrstrold+ 3 or less results in "Four/Characters" becoming an empty string
I am printing string in windows Messagebox so i will check its not that misinterpreting the string??

CommonTater

#3
Quote from: gromit on June 05, 2012, 11:17:12 AM
wchar_t  *ptrstrold=L"X";
wchar_t  *ptrstrnew=L"X";   
GetDlgItemText(hDlg, UNIT_STATIC,ptrstrold,len+1); // got text from static control

GetDlgItemText(hDlg, UNIT_QTY_COMBO,ptrstrnew,len+1);   // got text from qty combo

That's not going to work.  If you are going to work with wchar_t* you need to allocate memory to hold the strings you get from your dialogs, and you will need to free() that memory when you're done with it...

// plan a - string buffer
#define MAX_BUF 128

wchar_t* buffer = malloc(MAX_BUF * sizeof(wchar_t));

GetDlgItemText(hDlg, Unit_Static, buffer, MAX_BUF);
...
free(buffer);


// plan b - exact size
int size = GetWindowTextLength(GetDlgItem(hDlg,Unit_Static));
wchar_t* exact = malloc((size * sizeof(wchar_t)) + sizeof(wchar_t));

GetDlgItemText(hDlg, Unit_Static, exact, size);
...
free(exact);

Writing over unallocated memory puts your system at risk... you may overwrite other variables, other variables may overwrite your stuff... or you might crash your program outright. It's the same as in the real world... If you don't own it, it's not yours to take.

Quote
how do i add ptrstrold to ptrstrnew to give result ptrstrnew = "5 No widget"
i know i could do it with strings but i would like to understand pointers more.

You're going to have to do this with string manipulations.  If you try to "trick it out" in a single buffer by putting in the 1 No widget" first then overwriting the first part of the string with the 5, you're going to run into troubles with the trailing null on the second string.  The only way you could get away with it is if you know for absolutely certain the data from the combobox will only ever be a single digit... then you could use  control_buffer[0] = static_text[0] to copy the first character.

Now if you didn't have the 1 at the beginning of the string from the static control, you could do something like this...

#define MAX_BUF 32  // bigger than you'll need!

// create your buffer
wchar_t* string1 = calloc(MAX_BUF, sizeof(wchar_t));
wchar_t* string2 = string1;
// get the first text bit
GetDlgItemText(hDlg,COMBO,string1,MAX_BUF);
// find the end of the first string
while(*string2++);
// get the second text bit
GetDlgItemText(hDlg,STATIC,string2,MAX_BUF - wcslen(string1));

...
free(string1);


CommonTater

#4
Quote from: gromit on June 05, 2012, 12:33:26 PM
i now find some curiosity in this
concentrating on ptrstrold only
ptrstrold=ptrstrold+sizeof(wchar_t)*1 results in an empty string when i try to print ptrstrold
ptrstrold=ptrstrold+1 results in an empty string
ptrstrold=ptrstrold+4 and ptrstrold=ptrstrold+sizeof(wchar_t)*4
both result in the string minus the the first four characters
i only want to lose the first 1 or 2 ???
Doh

This does not work because you have not allocated any memory to the string... all you're doing is adding a number to an uninitialized pointer... which could have any random value in it.

Moreover; if you did allocate memory with malloc() or calloc(), disturbing the "root pointer" (the address of the memory buffer) will cause free() to fail and your program would leak memory.

Give this a read... http://pw1.netcom.com/~tjensen/ptr/pointers.htm


migf1

#5
May be a bit off-topic, but you can also consider using the win32api-specific TCHAR data type instead of char/w_char, along with the _T() / TEXT() macro, and use the win32api generic string functions. This simplifies things and makes your programs "unicode ready" (just #define _UNICODE and UNICODE before anything else) .

For example...


#include <tchar.h>
...
#define my_strncpy    _tcsncpy   // generic win32api function for strncpy (I'm just defining a more familiar name for it)
#define MAX_BUF  (255+1)
...
TCHAR  *ptrstrold = NULL;
TCHAR  strnew[ MAX_BUF] = {TEXT('\0')};   // this makes sure strnew is padded with 0s
...
// read old text
if ( NULL == (ptrstrold = malloc(MAX_BUF * sizeof(TCHAR)) )
    // handle failure here
if ( 0 == GetDlgItemText(hDlg, Unit_Static, ptrstrold , MAX_BUF) )
    // handle failure here
free( ptrstrold );

// assign new text
my_strncpy( strnew, TEXT("I'm the new string"), MAX_BUF-1 );  // padded initialization comes handy here
if ( 0 == SetDlgItemText(hDlg, Unit_Static, strnew) )
    // handle failure here

...


EDIT:
Lots of typos!

migf1

Sorry about that, but I had a bunch of typos in the code above, which rendered it useless. I fixed them now.

CommonTater

#7
Quote from: migf1 on June 05, 2012, 04:01:47 PM
May be a bit off-topic, but you can also consider using the win32api-specific TCHAR data type instead of char/w_char, along with the _T() / TEXT() macro, and use the win32api generic string functions. This simplifies things and makes your programs "unicode ready" (just #define _UNICODE and UNICODE before anything else) .

TCHARs are good.  But, since practically nobody writes ANSI code anymore (it's all unicode) he can also use the windows WCHAR and PWCHAR types ... In general my habit to use Windows types when working GUI code and C types when in console mode.   

Just a couple of points, if I may...


#include <tchar.h>
...
#define my_strncpy    _tcsncpy   


Actually the winapi function is lstrcpy() which switches modes with the unicode define.

Windows API defines a whole set of them...  HERE  


TCHAR  strnew[ MAX_BUF] = TEXT("\0");   // this makes sure strnew is padded with 0s

Actually that just writes a NULL in the first character position. 
If you want an all 0 string...

TCHAR strnew[MAX_BUF] = {0};  // on the stack
or
PTCHAR strnew = calloc(MAX_BUF,sizeof(TCHAR));  // on the heap


EDIT: Found a better link for the string functions.

migf1

#8
Quote from: CommonTater on June 05, 2012, 04:21:15 PM
...
TCHARs are good.  But, since practically nobody writes ANSI code anymore (it's all unicode) he can also use the windows WCHAR and PWCHAR types ... In general my habit to use Windows types when working GUI code and C types when in console mode.

Personally I find it quite handy to use just one interface for both GUI and Console apps. It makes things much more simpler for me, especially in maintaining the code of several projects.

That being said, I don't consider myself an expert in the Win32 API, so your suggestion may very well be a better approach, having certain advantages I'm not aware of.

QuoteJust a couple of points, if I may...

Sure!

Quote

#include <tchar.h>
...
#define my_strncpy    _tcsncpy   


Actually the winapi function is lstrcpy() which switches modes with the unicode define.
Windows API defines a whole set of them...  HERE  

I think _tcsncpy does the same (perhaps in a different way): http://msdn.microsoft.com/en-us/library/xdsywd25%28v=vs.80%29.aspx

Quote

TCHAR  strnew[ MAX_BUF] = TEXT("\0");   // this makes sure strnew is padded with 0s

Actually that just writes a NULL in the first character position. 
If you want an all 0 string...

TCHAR strnew[MAX_BUF] = {0};  // on the stack
or
PTCHAR strnew = calloc(MAX_BUF,sizeof(TCHAR));  // on the heap


That was one of the typos I fixed a bit later. The fixed one was wrong too :lol: Ι just fixed it again, so now it does pad strnew with 0s during initialization.

Btw, I'm still missing (later on) a line before: free(), meaning it should read something like this ...

if ( 0 == GetDlgItemText(hDlg, Unit_Static, ptrstrold , MAX_BUF) )
    // handle failure here
// do whatever you need to do with ptstrold here, then free it
free( ptrstrold );
...


PS. Thanks for the link!

CommonTater

Quote from: migf1 on June 05, 2012, 05:10:55 PM
Personally I find it quite handy to use just one interface for both GUI and Console apps. It makes things much more simpler for me, especially in maintaining the code of several projects.

The reason I use windows types instead of crt types is that some of them are not exactly the crt "equivalents" and some accomodate x64.  It's more specific which, in my experience, usually means better...

Quote
That being said, I don't consider myself an expert in the Win32 API,

Nor do I...

Quote
PS. Thanks for the link!

No worries...

gromit

Thanks for your input everybody

I have learnt a fair bit there.
I am grateful

I have however for the second time in 2 years
Had A main.c file wiped clean .
It was 137 k of code and when i went back to it from this forum earlier
It is now 137 k of zeros  :o :o :o :o
Are there any limits to size of main.c ?

Anyone else experienced that???

Once again Big Thanks Gromit

CommonTater

Quote from: gromit on June 05, 2012, 08:38:05 PM
I have however for the second time in 2 years
Had A main.c file wiped clean .

I've had that a couple of times too... I believe, without knowing for certain, that it happens when you exit POIDE with unsaved files in memory.  If you can track down the cause, in a repeatable way, you should make a bug report for Pelle...




gromit

Hi Tater
Glad i am not the only one losing files
Fortunately i had a fairly recent backup.

Were the files you lost very large ?

CommonTater

Quote from: gromit on June 06, 2012, 12:59:43 AM
Hi Tater
Glad i am not the only one losing files
Fortunately i had a fairly recent backup.

Were the files you lost very large ?


Not really, I tend to break things up in some way that feels right for each project, so I end up with multiple smaller files and like you I keep frequent backups, sometimes hourly while working.


CommonTater

Quote from: migf1 on June 05, 2012, 05:10:55 PM
I think _tcsncpy does the same (perhaps in a different way): http://msdn.microsoft.com/en-us/library/xdsywd25%28v=vs.80%29.aspx

I just followed your link... Small problem... _tsncpy() does not even exist in Pelles C runtime library.  They are C++ runtime library functions...

You need to be careful with using Microsoft's C++ library references with Pelles C... they're not the same language and, in many cases, they're not compatible. 

The ultimate authority on Pelles C is it's own help file... you should always check CRT functions there before recommending them.

Also note that the Windows headers and libs supplied with Pelles C are not exactly Microsoft's versions.  They have been modified to use Pelles C's base variable types, etc.  So it's often best to check those against the supplied headers as well...