4

the following code (main.cpp):

#include <string>
#include <vector>

std::vector< std::string > split( std::string haystack, const char limiter ) {
    std::vector< std::string > return_value;

    while( haystack.find( limiter ) != std::string::npos ) {
        return_value.push_back( haystack.substr( 0, haystack.find( limiter ) ) );
        haystack = haystack.substr( haystack.find( limiter ) + 1 );
    }

    return_value.push_back( haystack );

    return return_value;
}

const char* str = split( std::string( __FILE__ ), '/' ).back().c_str();

int main() {
    printf( "%s\n", str );
    return 0;
}

Always returns "iso_a3" and I don't know why... Basically, what I want to do is defining a LOG-macro that outputs the filename and in the beginning calculates the length of the project's base directory to substract it like this: __FILE__[ _base_directory_length ] so that the output is more readable, to be precise:

Debug.h

#pragma once

static int _base_directory_length = strlen( __FILE__ ) - split( __FILE__, '/' ).back().length();

#define LOG( message ) { \
    printf( "%s(%i): %s ", __FILE__ + _base_directory_length, __LINE__, __func__ ); \
    printf( message ); \
    printf( "\n" ); \
}

Does that make sense :-) ? BTW _base_directory_length = strlen( __FILE__ ) - strlen( "Debug.h" ) does not suffice.

user3116736
  • 111
  • 1
  • 5
  • What is the value of `__FILE__` ? – John3136 Dec 19 '13 at 00:43
  • And damn it, stackoverflow, two underscores are __NOT__ meant to be printed in bold letters. – user3116736 Dec 19 '13 at 00:44
  • See also: http://stackoverflow.com/questions/8487986/file-macro-shows-full-path – Anthony Dec 19 '13 at 00:45
  • __FILE__ is a macro defined by the compiler that... is replaced by the respective name of the file where the macro is getting replaced. I.e. /home/john/devel/project1/main.cpp – user3116736 Dec 19 '13 at 00:46
  • 1
    @user3116736 Surround stuff you don't want to be Markdown-formatted with backticks (\`) to make it look like this: `__FILE__` – Eric Finn Dec 19 '13 at 00:46
  • The point is this: There is an error somewhere, as my function returns iso_a3 which has nothing to do with my filename. – user3116736 Dec 19 '13 at 00:47
  • @anthony-arnold: You didn't get me there. I do not want to completely strip the path, just the project base path. Debug.h is placed in the "top level" directory. And all other files including Debug.h will only strip the path of Debug.h away leaving their sub directories in tact. – user3116736 Dec 19 '13 at 00:50

3 Answers3

0

__FILE__[ _base_directory_length ] is going to return a single character.

Maybe you want &__FILE__[ _base_directory_length ]'.

StilesCrisis
  • 15,972
  • 4
  • 39
  • 62
0

Ok, I'm sorry I bothered, should have been more attentive myself. This is what I actually wanted to do:

Debug.cpp in the project's root directory:

#include <cstring>

/* calculate the length of the root directory string */
int _path_length = strlen( __FILE__ ) - strlen( strrchr( __FILE__, '/' ) ) + 1;

Debug.h

extern int _path_length;

#define LOG( message ) {
    printf( "%s(%i): %s:\t", __FILE__ + _path_length, __LINE__, __func__ );
    printf( message ); /* message may be a variadic list of arguments */
    printf( "\n" );
}

All other files in sub directories now seem to output the correct path, with the location of Debug.cpp being the project root directory.

Once again, apologies for my stupid question and thanks for your replies.

user3116736
  • 111
  • 1
  • 5
  • Though the question remains, why my function returned iso_a3. Life's a mystery. – user3116736 Dec 19 '13 at 01:15
  • `printf( "%f(%i): %f"` - you had (correctly) `"%s"` in your question. Separately, who not just use `const char* filename = strchr(__FILE__, '/') + 1` and skip all the `strlen()` and `__FILE__ +` business? – Tony Delroy Dec 19 '13 at 02:05
  • You're absolutely right regarding the formatting strings, but your suggestion does not work at all. I want /home/john/devel/testproject/Gui/widget.cpp to output Gui/widget.cpp, however as strchr seems to find the first occurence of a character, all I could get from this one is home/john/devel/testproject/Gui/widget.cpp without the slash at the beginning. – user3116736 Dec 19 '13 at 19:38
  • `strlen` is unneccesary, I'd use `sizeof() -1` instead, also for the performance – Zaffy Dec 19 '13 at 19:45
  • Ah sorry - I was thinking of and meant to type `strrchr`, which searches from the right end of the string, but if you want Gui/widget.cpp not widget.cpp (you should really have said that clearly in your question ;-P), you'd need to use it twice... `const char* p = __FILE__; const char* q = strrchr(p, '/'); if (q) { while (q > p && *(q-1) != '/') --q; p = q; }` - answer in `q`. – Tony Delroy Dec 20 '13 at 01:50
  • You get "iso_a3" because you have undefined behavior. Your function returns a temporary vector. You fetch the last element of the vector and call `c_str` on it, and then the vector and its strings are destroyed, leaving `str` holding an invalid pointer. Something in your program (probably in the vendor-provided runtime library, not any code you wrote) evidently writes "iso_a3" into the memory previously occupied by the `std::string` at the end of that vector – Rob Kennedy Jun 03 '15 at 07:32
  • Depending on platform, check both '/' and '\'. – Technophile Apr 26 '18 at 18:15
0

Seems so strange. I copy the first snippet of code and run on my host, I got "main.cpp".

Why not do some debugging? If you do want to use gdb, you can just simply print str and every element you put into return_value.

WKPlus
  • 6,955
  • 2
  • 35
  • 53