|
I copied this off the internet without fully understanding how it works, and now it's not working when I compile as Release version. In Debug it works fine.
Not sure if I should dump it and reinvent the wheel, or if there is just a slight mistake in the code. The part I don't understand is in bold.
WCHAR extension [32];
WCHAR* peek = szFileName + szFileName [ wcslen( szFileName ) - 1 ];
while ( peek >= szFileName )
{
if (*peek == L'.') {
wcsncpy_s ( extension, peek, wcslen( peek ) );
break;
}
peek--;
}
swprintf_s( szFileExtension, L"%s", extension );
Edit:
The peek gets stuck with a 2 dot extension, and won't progress forward like
project.config.user
And then all file extensions are .user after that.
But just in Release
modified 25-Apr-12 22:58pm.
|
|
|
|
|
If you are using MFC, why don't you use CString::ReverseFind('.') ?
|
|
|
|
|
I should of said it was just a stock win32 project in c++
|
|
|
|
|
Further to Flaviu2 said,
if you're not using MFC, this will work:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
wchar_t *wszFilename = L"project.config.user";
wchar_t *extension;
wchar_t *dotPosition;
size_t extensionLength;
dotPosition = wcsrchr(wszFilename, '.');
extensionLength = wcslen(dotPosition);
extension = (wchar_t*) malloc(extensionLength * sizeof(wchar_t));
wcscpy(extension, dotPosition + 1); wprintf(extension);
}
Output:
user
|
|
|
|
|
Ooo, have a 5 'cause it's nice to see people using standard language features and types rather than sucking up to a particular OS/compiler and getting their code stuck on them for evermore.
The only comment I'd make is in the line:
dotPosition = wcsrchr(wszFilename, '.');
Should the character constant be a wide character? I haven't tried compiling it or looking at the standard so I could be very wrong!
Cheers,
Ash
|
|
|
|
|
Thanks mate!
Not so sure, I guess it would have been better to explicitly cast the '.' to a wchar_t. I figured since the function takes a wchar_t that this would be implicitly cast for me.
Compiling with gcc 4.something, the only warning I get was for line 7 (the wszFilename declaration) -
"warning: deprecated conversion from string constant to 'wchar_t*' "
It compiles & runs just fine with the -Wall and -Wextra compiler flags.
If the line in question is changed to:
wchar_t *wszFilename = (wchar_t*)"project.config.user";
Then it compiles with 0 warnings. [EDIT: but crashes like a bus!]
The line should read:
wchar_t *wszFilename = (wchar_t*)L"project.config.user";
Nice catch!
Simon.
modified 26-Apr-12 6:26am.
|
|
|
|
|
If you change wszFilename to a const char * you can avoid the cast. I can't see anywhere wszFilename is modified so you should be alright.
Another thing you might not be aware of: In C you don't need to cast the return value of malloc or calloc - void * is type compatible with any sort of pointer so (at least in C90, not sure about C99) you can convert them to anything implicitly.
Cheers,
Ash
|
|
|
|
|
Well,
I realize that it is just a code sample... but there are alot of novice programmers learning by reading these forums. You might want to free() the memory you allocated for the extension and you forgot to return an integer for the main() function.
Best Wishes,
-David Delaune
|
|
|
|
|
Thanks David,
I certainly had overlooked both of these points. Time I exercised a little more diligence..
Simon
|
|
|
|
|
What if the path is \\server\share\path.path\file?
|
|
|
|
|
|
You kidding me, there's an app for that!
So PathFinderExtension trumps the sample function posted earlier?
Thanks Dave, spent way too much time on it last night.
|
|
|
|
|
There's also a CRT function for this - _splitpath_s /_wsplitpath_s
|
|
|
|
|
That works great. Thanks
But I don't get it. I'm not sure if the wcsncpy_s bombed, or if I have some kind of buffer error, that never got flagged.
I have a registry function that's doing the same thing, but just the 1, so far, all others work fine.
I'm going to post it in a new post.
|
|
|
|
|
jkirkerx wrote: I have a registry function that's doing the same thing, but just the 1, so far, all others work fine.
Not sure but if you post the contents of the function and the calling function I might be able to pinpoint your problem.
Because I am somewhat familiar with the project you are working on... last comment about path handling:
In the future I would recommend that you use the Shell Path Handling Functions[^] when working on the windows platform rather than attempting to implement your own path parser. Over the past 20 years or so there have been hundreds of vulnerabilities associated with path handling/parsing... because many software engineers attempted to implement an algorithm of their own.
Best Wishes,
-David Delaune
|
|
|
|
|
Dear Mr. David Delaune,
I have received your feedback.
Thank you so much. please give me your email!
Best Regards,
L.Q.LONG
|
|
|
|
|
Le Quang Long wrote: Dear Mr. David Delaune,
I have received your feedback.
What feedback?
|
|
|
|
|
THe code snippet assumes UNICODE is being used.
I would suggest to use generic mapping that will work for both: ANSII and UNICODE:
As for retrieving parts of the path why not to let CRT do it for you using generic (_tsplitpath_s)?
For example:
LPTSTR lpszPath = _T("project.config.user");
TCHAR szFilename[MAX_PATH] = {0};
TCHAR szExt[MAX_PATH] = {0};
_tsplitpath_s(lpszPath, NULL, NULL, NULL, NULL, szFilename, _MAX_FNAME, szExt, _MAX_EXT);
JohnCz
|
|
|
|
|
I implemented the PathFinderExtension from Dave's Suggestion, but your suggestion looks quite interesting. hmm.
I didn't know about that function and how to implement it.
The PathFinderExtension is working quite well now, but let me fix my errors first before making any more changes.
|
|
|
|
|
Dear all everyone,
Please help me calling a dialog in project, I am using visual studio 2005(MFC, detail as below:
- My project have 2 dialogs(1 dialog to show data, 1 dialog login( user name and password) to protect data dialog)
- I created 1 dialog to show data is ok, but when I add a new dialog into this project and can not call dialog). So please help me!
Thanks and Best regards,
|
|
|
|
|
How are you trying to call the dialog? ...you have to show some applicable code.
|
|
|
|
|
I am not sure why check for valid password in OnInitDlg, while it seems that it should be checked before main dialog is invoked. No need for posting any messages to the thread.
Besides, log in dialog should not be checked for cancel only but validate password and/or username.
This code snippet shows how this can be done:
CLoginDlg loginDlg;
loginDlg.DoModal();
INT_PTR nResponse = loginDlg.DoModal();
if(nResponse == IDCANCEL)
{
return FALSE; }
if(loginDlg.m_csUser.CompareNoCase(lpszUser))
{
return FALSE; }
if(loginDlg.m_csPassword.Compare(lpszPassword))
{
return FALSE; }
CMainDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
.
.
.
JohnCz
|
|
|
|
|
I would do something like :
pre-requisite.
CLoginDialog: your login dialog.
CDataDialog; your main application dialog
The CDataDialog is the main application dialog (for example created via the wizard).
When the CDataDialog is created, you can call/create the login dialog in the OnInitDialog; if the login is valid, just continue, if it is invalid, you can either close the main application, or better continue but disable some stuff or not load the data.
For example ...
BOOL Ctest_dialogDlg::OnInitDialog()
{
CDialog::OnInitDialog();
LoginDialog dlg;
if ( dlg.DoModal() == IDCANCEL)
{
PostQuitMessage(42);
return FALSE;
}
return TRUE; }
Watched code never compiles.
|
|
|
|
|
|
Thank you so much!
Please give me your email!
|
|
|
|