2016-05-21 9 views
2

Was ist der moderne Weg, dies zu tun? Header wie <cstring> sind veraltet und "C-like" -Funktionen sind durch einige Codierungsstile verboten. Ich habe drei Ansätze, das Gleiche zu tun. Welches wäre am meisten von modernem C++?Moderne C++ Möglichkeit zum Kopieren von Zeichenfolgen in Zeichen *

1. Verwenden Iteratoren und schließen die Nullabschluss

{ 
    std::string test{"hello, world!"}; 
    char* output = new char[test.size() + 1]; 
    std::copy(test.begin(), test.end(), 
     output); 
    output[test.size() + 1] = '\0'; 
    std::cout << output; 
    delete output; 
} 

2. Verwenden c_str() die dem Nullabschluss

{ 
    std::string test{"hello, world!"}; 
    char* output = new char[test.size() + 1]; 
    std::copy(test.c_str(), test.c_str() + std::strlen(test.c_str()), 
     output); 
    std::cout << output; 
    delete output; 
} 

3. Verwenden std::strcpy

enthält

Ich möchte nicht zu einem Interviewer wie ein noob aussehen, die sagen: "Oh, du benutzt strcpy, du musst ein C-Programmierer sein".

+0

Wenn ich Sie wäre, würde ich mich um die Ausnahmesicherheit kümmern, den ganzen Block mit einem "try" umwickeln und "std :: bad_alloc" fangen. Auch "Header wie sind veraltet" - seit wann ?! –

+1

Was * genau * ist die Ziel-Datenstruktur? Ist es malloc-allozierte 0-terminierte Zeichenfolge? Oder ist es "zugängliche 0-terminierte Zeichenfolge"? Oder eigentlich wirklich die Bastard neu zugewiesene 0-terminierte Zeichenfolge? – Deduplicator

+0

@DanielKamilKozar Seit C++ 98. Verrückt, ich weiß. – user6364501

Antwort

10

Der richtige Weg verwendet new[] in erster Linie nicht. Verwenden Sie std::vector statt:

std::string temp {"Some string"}; 
std::vector<char> data (begin(temp), end(temp)); 
// If '\0' termination is required: 
data.push_back('\0'); 

Sie können sie zugrunde liegenden Zugriff auf Puffer von data mit data.data(). Wenn Sie sind wirklich Angst vor einer Neuzuweisung aufgrund der , können Sie std::vector::reserve genug Platz vor der Zuweisung der Bereich.

Wenn Sie nicht ein tatsächlich modifizierbar char Array benötigen, können Sie die Kopie überspringen und benutzen Sie einfach den Zeiger zurück von std::string::data oder std::string::c_str direkt.

13

Die moderne sicher vor C++ 17 Weg, um einen zusammenhängenden Puffer zu erhalten, ist std::vector.

std::string test{"hello, world!"}; 
std::vector<char> output(test.c_str(), test.c_str()+test.size()+1); 
// use output.data() here... 

Da C++ 17 hat std::string eine nicht-const data() Überlastung.

std::string test{"hello, world!"}; 
char * p = test.data(); 
0

Während die anderen Antworten gut beraten, und der richtige Weg, Dinge zu tun, in fast allen Umständen, gibt es einige echte Fälle, in denen Sie eine char* anstelle eines Behälters zu verwenden, gezwungen werden könnten. Der häufigste Fall wird sein, wenn Sie direkt mit dem C-Code eine Schnittstelle herstellen müssen und die aufgerufene C-Methode einen Zeiger benötigt, der nicht const ist (d. H., Sie übernimmt den Besitz des Speichers).

Dies ist, wie ich die Umwandlung machen würde:

#include <string> 
#include <cstdlib> 

char* convert(const std::string& source) 
{ 
    const auto result = (char*) std::malloc(source.length() + 1); 
    source.copy(result, source.length()); 
    result[source.length()] = '\0'; 
    return result; 
} 

Dann haben Sie so etwas wie:

int main() 
{ 
    const std::string foo {"hello"}; 
    auto p = convert(foo); 
    some_nasty_c_method(p); // promises to free p 
    // other stuff 
} 

Als Faustregel gilt, wenn Sie sich delete benötigen, nicht tun Dies; Verwenden Sie stattdessen einen Container oder std::unique_ptr.

+0

Was ist falsch mit 'std :: vector v (foo.begin(), foo.end()); some_nasty_c_method (v.data()); '? –

+0

@ChristianHackl 'std :: vector :: data' gibt einen' const' Zeiger zurück. – Daniel

+0

@Daniel: [Eine Überladung tut aber auch eine nicht-const Überladung.] (Http://en.cppreference.com/w/cpp/container/vector/data) Es ist jedoch wahr, dass eine Funktion ist Um 'frei' für einen gegebenen Zeiger aufzurufen, ist es erforderlich, einen über 'malloc' erhaltenen Zeiger zu erhalten. Dies wird hoffentlich in der Schnittstellenbeschreibung spezifiziert und dann ist es keine Frage, welche Methode am besten verwendet werden sollte/ist, da Sie ohnehin 'malloc' verwenden müssen. – Pixelchemist

Verwandte Themen