is there non const variant of c_str()?

is there non const variant of c_str()?

I used this to convert from string to char
const char * cpath = path.c_str();
now I found I need to trim the string but const denies to change it. So is there a variant which allows to change the variable?
Yes. See http://www.cplusplus.com/reference/string/string/copy/

If you need to trim the string, why not do it while it was still a string. In fact, why do you need to turn it into a C-string anyway? Why don't you just pass the actual string object around?
Last edited on
Are you trying to modify the original string or modify a copy of the string?

If you don't mind modifying a copy then you'll need to copy it:
1
2
3
4
char * cpath = new char[ path.size() ];
strcpy(cpath, path.c_str() );
//...
delete[] cpath;


Otherwise, getting a char* from a std::string would be returning a pointer to the internal data. That's too dangerous for std::string because it would let someone modify the internal data without considering any other internal methods such as updating the size, re-allocating memory, etc.

http://www.cplusplus.com/reference/cstring/strcpy/

Edit: I stand corrected NT3... still the same thing, A copy is needed.
1
2
char* cpath = new char[ path.size() ];
strcpy(cpath, path.c_str() );
char* cpath = new char[ path.size() ];
path.copy(cpath, path.size() );
Last edited on
NT3:
To answer your question, I am testing the string path:
if( stat(cpath,&s) == 0 )
stat needs char. Maybe I did not choosed correct way how to do it. My idea was to trim dot from left for the case directory name is like ./myDir , but then I realized that there can be file name like .myfile so not good idea. I should test first two characters and if they are ./ so remove 2 and add current_path to begin of the variable.
stat needs char
if( stat(path.c_str(), &s) == 0 )

You should do all operation on your actual path string and convert it to c-string right before passing into function.
Good idea. But I have one more problem with testing the begin of the path.

path: .\88469142758.jpeg
Type: std::basic_string<char,std::char_traits<char>,std::allocator<char> >

using:
1
2
std::string prefix(".\"");
n = path.compare(0, prefix.size(), prefix);


path.compare(0, prefix.size(), prefix);
returns CXX0047: Error: argument list does not match a function
n is 1
any idea why?
Last edited on
compare() returns zero on match. As your string does not starts with .", it returns nonzero value. Maybe you want to compare it with .\?
> I should test first two characters and if they are ./ so remove 2 and add current_path to begin of the variable.

You do not need to do that. stat() accepts relative paths.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int main() 
{
    struct stat buf ;
    
    for( const std::string path : { "./test_dir", "./main.cpp", "./../../usr/local/include", "bad_path" } )
    {
        std::cout << '\'' << path << "' : " ;
        if( stat( path.c_str(), &buf ) == 0 )
        {
            const mode_t mode = buf.st_mode ;
            
            if( S_ISREG(mode) ) std::cout << "regular file\n" ;
            else if( S_ISDIR(mode) ) std::cout << "directory\n" ;
            // etc.
        }
        else std::cout << "*** stat error ***\n" ;
    }
}

http://coliru.stacked-crooked.com/a/84653bbed9e75cbd

As an academic exercise, to get a c-style string without leading ./ if any:
1
2
3
4
    const std::string path = "./my_dir" ;
    const char* cstr = path.c_str() ;
    if( path.find( "./" ) == 0 ) // begins with ./
         cstr += 2 ; // skip the first two chars 
MiiNiPaa, yes I want to compare .\ , I see my error now, should be
std::string prefix(".\\"); thanks
JLBorges: But in your 2nd example if I want to join this:
1
2
3
4
5
const char* cpath = path.c_str() ;
	if( path.find( ".\\" ) == 0 ){ // begins with .\ 
         cpath += 2 ; // skip the first two chars       
	cpath = *workingPath + cpath; // join the value of workigPath with cPath
	}

Result is failture
Last edited on
What workingPath is? Why do you need to dereference it? If working path a c-string too, you need to make use of strncat function.
both are c string.

Edit: workingPath is c string.
Path is stiring as original.
cpath would be const c string if I use it as destination of conversation.
Last edited on
cpath = *workingPath + cpath Here you are adding integral value of first character of working path to cpath pointer.
You need either:
1) Work with strings and take c-string as last step:
1
2
3
4
5
if( path.find( "./" ) == 0 ) {
    path.erase(0, 2);
    path.insert(0, workingPath);
}
const char* cpath =  path.c_str();

2) contacenate your strings:
1
2
3
4
5
6
char buffer[256];
if (path.find( "./" ) == 0) {
    strncpy(buffer, workingPath, 256);
    strncat(buffer, path.c_str() + 2, 256 - strlen(buffer));
} else
    strncpy(buffer, path.c_str(), 256);
MiiNiPaa
thanks, your solution works. But I am too tired to think about is father more. Just question to the second solution. Is it possible to use similar solution but for char * buffer? But the first solution is clear and simple. Simple to remember.
Is it possible to use similar solution but for char * buffer
It uses char* buffer already. You can use dynamic memory allocation and pointers to guarantee that any path would fit.
Topic archived. No new replies allowed.