Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Get File Extension

Get File Extension

Scheduled Pinned Locked Moved C / C++ / MFC
announcementdebugginghelp
19 Posts 9 Posters 3 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    jkirkerx
    wrote on last edited by
    #1

    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 ) ); // stuck here
    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

    _ enhzflepE L J 4 Replies Last reply
    0
    • J jkirkerx

      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 ) ); // stuck here
      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

      _ Offline
      _ Offline
      _Flaviu
      wrote on last edited by
      #2

      If you are using MFC, why don't you use CString::ReverseFind('.') ?

      J 1 Reply Last reply
      0
      • J jkirkerx

        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 ) ); // stuck here
        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

        enhzflepE Offline
        enhzflepE Offline
        enhzflep
        wrote on last edited by
        #3

        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); // add 1 to point to char following the .
        wprintf(extension);
        

        }

        Output:

        user

        A L J 3 Replies Last reply
        0
        • enhzflepE enhzflep

          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); // add 1 to point to char following the .
          wprintf(extension);
          

          }

          Output:

          user

          A Offline
          A Offline
          Aescleal
          wrote on last edited by
          #4

          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

          enhzflepE 1 Reply Last reply
          0
          • A Aescleal

            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

            enhzflepE Offline
            enhzflepE Offline
            enhzflep
            wrote on last edited by
            #5

            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! :thumbsup: Simon.

            A 1 Reply Last reply
            0
            • J jkirkerx

              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 ) ); // stuck here
              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

              L Offline
              L Offline
              Lost User
              wrote on last edited by
              #6

              Jim, When you are working with paths on the windows platform I would recommend using the Shell Path Handling Functions[^]. You are probably looking for the PathFindExtension function[^]. Best Wishes, -David Delaune

              J 2 Replies Last reply
              0
              • enhzflepE enhzflep

                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); // add 1 to point to char following the .
                wprintf(extension);
                

                }

                Output:

                user

                L Offline
                L Offline
                Lost User
                wrote on last edited by
                #7

                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

                enhzflepE 1 Reply Last reply
                0
                • L Lost User

                  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

                  enhzflepE Offline
                  enhzflepE Offline
                  enhzflep
                  wrote on last edited by
                  #8

                  Thanks David, I certainly had overlooked both of these points. Time I exercised a little more diligence..:thumbsup: Simon

                  1 Reply Last reply
                  0
                  • enhzflepE enhzflep

                    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! :thumbsup: Simon.

                    A Offline
                    A Offline
                    Aescleal
                    wrote on last edited by
                    #9

                    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

                    1 Reply Last reply
                    0
                    • _ _Flaviu

                      If you are using MFC, why don't you use CString::ReverseFind('.') ?

                      J Offline
                      J Offline
                      jkirkerx
                      wrote on last edited by
                      #10

                      I should of said it was just a stock win32 project in c++

                      1 Reply Last reply
                      0
                      • L Lost User

                        Jim, When you are working with paths on the windows platform I would recommend using the Shell Path Handling Functions[^]. You are probably looking for the PathFindExtension function[^]. Best Wishes, -David Delaune

                        J Offline
                        J Offline
                        jkirkerx
                        wrote on last edited by
                        #11

                        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.

                        _ 1 Reply Last reply
                        0
                        • L Lost User

                          Jim, When you are working with paths on the windows platform I would recommend using the Shell Path Handling Functions[^]. You are probably looking for the PathFindExtension function[^]. Best Wishes, -David Delaune

                          J Offline
                          J Offline
                          jkirkerx
                          wrote on last edited by
                          #12

                          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.

                          L 1 Reply Last reply
                          0
                          • J jkirkerx

                            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.

                            L Offline
                            L Offline
                            Lost User
                            wrote on last edited by
                            #13

                            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

                            L 1 Reply Last reply
                            0
                            • J jkirkerx

                              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.

                              _ Offline
                              _ Offline
                              _Superman_
                              wrote on last edited by
                              #14

                              There's also a CRT function for this - _splitpath_s/_wsplitpath_s

                              «_Superman_»  _I love work. It gives me something to do between weekends.

                              _Microsoft MVP (Visual C++)

                              Polymorphism in C

                              1 Reply Last reply
                              0
                              • L Lost User

                                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

                                L Offline
                                L Offline
                                Le Quang Long
                                wrote on last edited by
                                #15

                                Dear Mr. David Delaune, I have received your feedback. Thank you so much. please give me your email! Best Regards, L.Q.LONG

                                L 1 Reply Last reply
                                0
                                • L Le Quang Long

                                  Dear Mr. David Delaune, I have received your feedback. Thank you so much. please give me your email! Best Regards, L.Q.LONG

                                  L Offline
                                  L Offline
                                  Lost User
                                  wrote on last edited by
                                  #16

                                  Le Quang Long wrote:

                                  Dear Mr. David Delaune,
                                  I have received your feedback.

                                  :confused: What feedback?

                                  1 Reply Last reply
                                  0
                                  • J jkirkerx

                                    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 ) ); // stuck here
                                    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

                                    J Offline
                                    J Offline
                                    JohnCz
                                    wrote on last edited by
                                    #17

                                    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

                                    J 1 Reply Last reply
                                    0
                                    • enhzflepE enhzflep

                                      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); // add 1 to point to char following the .
                                      wprintf(extension);
                                      

                                      }

                                      Output:

                                      user

                                      J Offline
                                      J Offline
                                      Joe Woodbury
                                      wrote on last edited by
                                      #18

                                      What if the path is \\server\share\path.path\file?

                                      1 Reply Last reply
                                      0
                                      • J JohnCz

                                        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

                                        J Offline
                                        J Offline
                                        jkirkerx
                                        wrote on last edited by
                                        #19

                                        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.

                                        1 Reply Last reply
                                        0
                                        Reply
                                        • Reply as topic
                                        Log in to reply
                                        • Oldest to Newest
                                        • Newest to Oldest
                                        • Most Votes


                                        • Login

                                        • Don't have an account? Register

                                        • Login or register to search.
                                        • First post
                                          Last post
                                        0
                                        • Categories
                                        • Recent
                                        • Tags
                                        • Popular
                                        • World
                                        • Users
                                        • Groups