programing

C++ 문자열에서 상수가 아닌 C 문자열을 다시 받을 수 있습니까?

magicmemo 2023. 8. 29. 20:21
반응형

C++ 문자열에서 상수가 아닌 C 문자열을 다시 받을 수 있습니까?

C++의 항상 정확성은 여전히 저에게 두통을 줍니다.오래된 C 코드를 사용하는 동안, 저는 C++ 문자열 객체를 C 문자열로 변환하고 변수에 할당해야 하는 저 자신을 발견했습니다.그나변다같습니다과음는수러입니다.char *그리고.c_str()를 반환합니다.const char []제 기능을 사용하지 않고도 이 문제를 해결할 수 있는 좋은 방법이 있습니까?

편집: 저도 새로 전화하는 것을 피하려고 합니다.메모리 누수를 줄이기 위해 조금 더 복잡한 코드를 기꺼이 교환하겠습니다.

C++17 이상:

foo(s.data(), s.size());

C++11, C++14:

foo(&s[0], s.size());

그러나 주의해야 할 사항은 다음과 같습니다.의 결과&s[0]/s.data()/s.c_str()문자열을 변경할 수 있는 멤버 함수가 호출될 때까지만 유효합니다.따라서 이러한 작업의 결과를 다른 곳에 저장해서는 안 됩니다.가장 안전한 것은 제 예처럼 완전한 표현의 마지막에 그것들을 사용하는 것입니다.


C++-11 이전 답변:

제게 설명할 수 없는 이유로 아무도 지금처럼 대답하지 않았고, 다른 질문들이 이 질문을 가리키며 닫히고 있기 때문에, 여기에 추가하겠습니다. 비록 1년이 너무 늦게 오는 것은 그것이 산더미의 맨 아래에 걸려 있다는 것을 의미합니다.


C++03을 사용하면,std::string, 연적인메조저문장것는하않보이으며결그과지장, 에▁of▁result▁isn의 결과입니다.c_str()문자열의 내부 버퍼를 가리킬 필요가 없으므로 동작을 보장하는 유일한 방법은 다음과 같습니다.

std::vector<char> buffer(s.begin(), s.end());
foo(&buffer[0], buffer.size());
s.assign(buffer.begin(), buffer.end());

이것은 C++11에서는 더 이상 사실이 아닙니다.

할: 여서당해할야중구있별습다니: 그은다같습니다과음것신이기요한이▁the▁there다같습니▁is▁you.char*당신은 이 "평균 상수"를 어떤 것에 할당하고 싶습니까?즉, 버리는 것입니다.const-ness는 단지 기술적인 것이고, 당신은 여전히 문자열을 다룰 것입니다.constCC++ 할 수 .const_cast당신(그리고 이 코드를 유지하는 다른 사람)이 그것을 다룰 규율을 가지고 있는 한.char*const char*당신은 괜찮을 것입니다, 하지만 컴파일러는 더 이상 당신의 뒷모습을 감시하지 않을 것입니다, 그래서 만약 당신이 그것을 비-로 취급한다면.const코드의 다른 무언가가 의존하는 버퍼를 수정하고 있을 수 있습니다.

만약 당신이char*는 '비(非) 비문가취것로입다니될급전▁non것다'로 처리될 예정입니다.const그리고 당신은 그것이 가리키는 것을 수정하려고 합니다, 당신은 반환된 문자열을 복사해야 합니다, 그것을 버려서는 안됩니다.const -ness.

항상 있는 것 같아요.strcpy.

또는 사용char*C++ 코드의 일부에 있는 문자열들은 오래된 것들과 연결되어야 합니다.

한 후 C++ 컴파일러를 합니다.std:string.

항상 고정 출연진이 있어요

std::string s("hello world");
char *p = const_cast<char *>(s.c_str());

물론, 그것은 기본적으로 형식 시스템을 전복시키는 것이지만, 때로는 오래된 코드와 통합할 때 필요합니다.

권장 사항 대신 추가 할당을 할 수 있는 경우strcpy사용을 고려해 보겠습니다.std::vector<char>다음과 같이:

// suppose you have your string:
std::string some_string("hello world");
// you can make a vector from it like this:
std::vector<char> some_buffer(some_string.begin(), some_string.end());
// suppose your C function is declared like this:
// some_c_function(char *buffer);
// you can just pass this vector to it like this:
some_c_function(&some_buffer[0]);
// if that function wants a buffer size as well,
// just give it some_buffer.size()

은 나게이조더금것은다니 C++방입식보다 C.strcpy마이어스의 효과적인 STL 항목 16을 보면 제가 제공할 수 있는 것보다 훨씬 더 좋은 설명을 들을 수 있습니다.

복사 방법을 사용할 수 있습니다.

len = myStr.copy(cStr, myStr.length());
cStr[len] = '\0';

에▁where디myStr당신의 C++ 이고 당의 C++입니다.cStr a char * 어도는 .myStr.length()+1 사이즈.또한.len이 형의입니다.size_t가 null-refix를 null-refix는 null-refix를하지 않기 합니다.cStr.

그냥 사용하기const_cast<char*>(str.data())

그것에 대해 기분 나쁘거나 이상하게 생각하지 마세요, 이것을 하는 것은 완벽하게 좋은 스타일입니다.

그것은 C++11에서 작동하는 것이 보장됩니다.은 그것; C에서는 그이일게그이원틀다표의실니에; C++▁c▁the▁before▁to▁possible▁c▁implement▁in▁was▁a▁it+다▁standard▁fact'+그▁by▁arguably▁it▁originals▁at▁mistake것▁qualified▁all니▁that0303▁it▁the▁is▁const에습가+구했;.string불연속적인 기억 목록으로, 하지만 아무도 하지 않았습니다.에는 지상에다구컴없현다습니파를 .string연속적인 기억 블록 이외의 다른 것으로서, 그러니 그것을 완전한 확신을 가지고 자유롭게 다루세요.

만약 당신이 그것을 안다면.std::stringC 스타일의 깁스는 바뀌지 않을 것입니다.

std::string s("hello");
char *p = (char *)s.c_str();

물이야론.p는 에서관일버가있에서 있습니다.std::string에 약에만.std::string된 경우( 쓰기 대상), 범를벗즉버변경우경된가퍼나(거, 쓰기위치),p아마 무효가 될 것입니다.

코드 리팩터링이 불가능하다면 문자열을 복사하는 것이 가장 안전합니다.

std::string vString;
vString.resize(256); // allocate some space, up to you
char* vStringPtr(&vString.front());
// assign the value to the string (by using a function that copies the value).
// don't exceed vString.size() here!
// now make sure you erase the extra capacity after the first encountered \0.
vString.erase(std::find(vString.begin(), vString.end(), 0), vString.end());
// and here you have the C++ string with the proper value and bounds.

이렇게 하면 C++ 문자열을 C 문자열로 변환할 수 있습니다.그러나 원시 문자열 함수를 사용하여 경계를 벗어나는 것은 매우 쉬우므로, 당신이 무엇을 하고 있는지 확실히 알아야 합니다.이것이 필요한 순간들이 있습니다.

한다면c_str()버퍼의 합니다. "" " " " " " 를 . 그냥 사용할 수 있습니다.const_cast<>.

만약 만지면, 에약.c_str()문자열 개체 내부 버퍼에 직접 액세스할 수 있도록 하는 것입니다. const를 제거하는 대신 명시적으로 복사하십시오.

c_str()는 데이터 구조에 대한 직접적인 고정 액세스를 제공하므로 캐스트하지 않아야 합니다.버퍼를 미리 할당하지 않고 이를 수행하는 가장 간단한 방법은 strdup을 사용하는 것입니다.

char* tmpptr;
tmpptr = strdup(myStringVar.c_str();
oldfunction(tmpptr);
free tmpptr;

빠르고, 쉽고, 정확합니다.

에는 만당이원한면다신입니다.char *에서.string.c_str()(예를 들어, 오직 하나의 함수만 취하는 함수에 그것을 주는 것.char *)에 캐스팅할 수 있습니다.char *직접적으로 패배하기 위해const.c_str()

예:

launchGame((char *) string.c_str());

C++17은 a를 추가합니다.char* string::data() noexcept가 const가, 는 "cont"됩니다.data()둘 다 아니고 당신은 그것을 사용할 수 있습니다.

스스로 하는 것이 정말 그렇게 어렵습니까?

#include <string>
#include <cstring>

char *convert(std::string str)
{
    size_t len = str.length();
    char *buf = new char[len + 1];
    memcpy(buf, str.data(), len);
    buf[len] = '\0';
    return buf;
}

char *convert(std::string str, char *buf, size_t len)
{
    memcpy(buf, str.data(), len - 1);
    buf[len - 1] = '\0';
    return buf;
}

// A crazy template solution to avoid passing in the array length
// but loses the ability to pass in a dynamically allocated buffer
template <size_t len>
char *convert(std::string str, char (&buf)[len])
{
    memcpy(buf, str.data(), len - 1);
    buf[len - 1] = '\0';
    return buf;
}

용도:

std::string str = "Hello";
// Use buffer we've allocated
char buf[10];
convert(str, buf);
// Use buffer allocated for us
char *buf = convert(str);
delete [] buf;
// Use dynamic buffer of known length
buf = new char[10];
convert(str, buf, 10);
delete [] buf;

언급URL : https://stackoverflow.com/questions/1919626/can-i-get-a-non-const-c-string-back-from-a-c-string

반응형