Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Tuesday, May 22, 2018 10:14 AM
I am trying to add a text string, or a character, to a TCHAR variable. I have found many web-sites seemingly having a solution to this, but whatever I try, my program crashes. This is what I have come up with so far:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <wchar.h>
#include <tchar.h>
#include <string.h>
#include <mbstring.h>
struct roots
{
TCHAR *root;
int letters;
int cls;
int sys;
};
struct roots rt[150] = {
{TEXT("aJj"), 3, 1, 1},
};
int main(int argc, char *argv[])
{
TCHAR *stem[10];
*stem = rt[0].root;
_tcscat(*stem, L"a");
_tprintf( TEXT("%s\n"), *stem );
_getch();}
When I run this in the debugger, I get the message "Unhandled exception at ... Access violation writing location ..."
Thanks in advance.
All replies (4)
Tuesday, May 22, 2018 11:53 AM | 1 vote
There are a few things wrong with this.
struct roots rt[150] = { //this is an array of 150 roots structures
{TEXT("aJj"), 3, 1, 1},
};
This creates an array of 150 roots structures, it doesn't create a roots structure with 150 characters for the TCHAR * variable. Because this is a pointer, there is no memory backing it automatically, so you either need to define this with an array for the string:
struct roots
{
TCHAR root[150];
//other elems
};
or allocate the memory for the string using malloc/new at some point.
TCHAR *stem[10];
This creates an array of pointers to TCHAR, this is not a string. If you want to create a string then you create an array of TCHARS:
TCHAR stem[10];
This is a proper string.
This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.
Tuesday, May 22, 2018 1:52 PM
Thank you very much for your answer. Because of it I was able to find the solution. I did like this:
truct roots
{
TCHAR root[10];
int letters;
int cls;
int sys;
};
struct roots rt[150] = {
{TEXT("aJj"), 3, 1, 1},
};
TCHAR stem[10];
wcscpy(stem, rt[0].root);
_tcscat(stem, L"a"); // or wcscat(stem, L"a");
I guess it here doesn't matter whether I use "_tcscat" or "wscat".
However, I am still confused about when I should use pointers or not. If I instead of TCHAR root[10] and TCHAR stem[10] had used TCHAR *root and TCHAR *stem, I would, as I understand it, have two pointers to addresses containing strings. Would it then not possible to do string manipulations using these pointers?
Wednesday, May 23, 2018 10:24 AM | 1 vote
The thing with pointers is that the memory that they point to isn't allocated for them automatically. So:
TCHAR *str;
would be a pointer, containing an address, but it would more than likely point to an invalid memory location and will crash the program if you try to write to it. If you try to use it, say in:
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstring>
int main()
{
wchar_t *str; //not initialised to anything
wcscpy(str, L"Hello World!"); //line 9
wprintf(L"%s\n", str);
return 0;
}
Then you will get a compiler error:
1> Build started: Project: meh, Configuration: Debug x64
1>main.cpp
1>c:\users\darran\source\repos\meh\meh\main.cpp(9): error C4700: uninitialized local variable 'str' used
1>Done building project "meh.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
But this isn't something guaranteed by the C++ standard, VC just does it.
This is an error because a pointer is a variable, and all variables contain an indeterminate value when it is created, and you need to initialise it to have it point to something useful. Also, the only memory allocated for a pointer is for the pointer itself, so either 32 bits/4 bytes for 32 bit applications, or 64 bits/8 bytes for 64 bit applications.
The difference between an array and a pointer is that arrays will allocate all of the memory for the array when you define it. Pointers will not do this.
You need to allocate the memory for the pointer separately.
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstring>
#include <malloc.h>
int main()
{
wchar_t *str;
str = static_cast<wchar_t *>(malloc(sizeof(wchar_t) * 20)); //allocates memory for 20 wchar_ts
//or you can do
//str = new wchar_t[20];
wcscpy(str, L"Hello World!");
wprintf(L"%s\n", str);
free(str);
//or
//delete[] str;
return 0;
}
This will not only allocate the memory for the string but then set the pointer to point at the new block of memory.
But the one way to think about a pointer is to only see it as a link to something. This link doesn't automatically create the object that it links to, and you have to do the linking up of this pointer to the memory it points to manually.
This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.
Wednesday, May 23, 2018 12:48 PM
Thanks for your explanation. Very good to have this overview of pointers versus arrays.
Sincerely