2010-04-01 33 views
22

Nếu tôi chuyển một char * vào một hàm. Tôi muốn sau đó đi mà char * chuyển đổi nó thành một chuỗi std :: và một khi tôi nhận được kết quả của tôi chuyển đổi nó trở lại char * từ một std :: string để hiển thị kết quả.cách sao chép char * thành chuỗi và ngược lại

  1. Tôi không biết làm thế nào để làm điều này cho chuyển đổi (Tôi không nói const char * nhưng chỉ char *)
  2. Tôi không chắc chắn làm thế nào để thao tác các giá trị của con trỏ tôi gửi trong.

nên bước tôi cần phải làm

  1. mất trong một char *
  2. chuyển đổi nó thành một chuỗi.
  3. lấy kết quả của chuỗi đó và đặt nó trở lại dưới dạng char *
  4. trả về kết quả sao cho giá trị phải có sẵn bên ngoài hàm và không bị hủy.

Nếu có thể, tôi có thể xem cách nó có thể được thực hiện thông qua tham chiếu so với con trỏ (có địa chỉ mà tôi chuyển vào theo giá trị. Tuy nhiên, tôi vẫn có thể sửa đổi giá trị mà con trỏ trỏ tới. địa chỉ trong hàm bị phá hủy tôi vẫn nhìn thấy giá trị thay đổi bên ngoài

nhờ

+1

"chuyển đổi lại thành char * từ chuỗi std :: để hiển thị kết quả". - tại sao bạn không thể hiển thị kết quả khi nó là một chuỗi? Nên có thể làm std :: cout << my_string; –

+0

đây là giao diện tôi phải làm việc. vì vậy mặc dù tôi sử dụng chuỗi bất cứ khi nào tôi có thể nếu một giao diện yêu cầu char * thì đó là những gì tôi phải sử dụng. tham số đầu ra chức năng là một char * ... và đó là những gì tôi phải làm việc với – user295030

+3

Trong trường hợp đó, giao diện nên nói điều gì đó về quản lý bộ nhớ. Tôi nói "nên" bởi vì nó * có thể * không - một số giao diện được xác định kém, thực tế của cuộc sống. Bất cứ khi nào bạn trả về một con trỏ từ một hàm, bạn cần phải nói ai chịu trách nhiệm phân bổ dữ liệu được trỏ đến, thời gian nó vẫn hợp lệ và ai chịu trách nhiệm giải phóng nó (nếu có). Nếu bạn có thể làm việc đó, bạn có thể tìm ra cách trả về một giá trị con trỏ thích hợp. –

Trả lời

36

Chuyển đổi một char* đến một std::string:.!

char* c = "Hello, world"; 
std::string s(c); 

Chuyển đổi một std::string đến một char*:

std::string s = "Hello, world"; 
char* c = new char[s.length() + 1]; 
strcpy(c, s.c_str()); 

// and then later on, when you are done with the `char*`: 
delete[] c; 

Tôi thích sử dụng một std::vector<char> thay vì một thực tế char*; sau đó bạn không cần phải quản lý bộ nhớ của riêng bạn:

std::string s = "Hello, world"; 
std::vector<char> v(s.begin(), s.end()); 
v.push_back('\0'); // Make sure we are null-terminated 
char* c = &v[0]; 
+1

yea nhưng trong trường hợp thứ hai khi bạn sử dụng c_str() nó trả về một const char * không phải là char * – user295030

+0

@ user295030: 'c_str()' thực sự trả về 'const char *'; tham số thứ hai là 'strcpy' (chuỗi nguồn) là kiểu' const char * '. Nếu bạn chỉ cần một 'const char *', thì không cần phải làm điều này, và bạn chỉ có thể sử dụng kết quả của 'c_str()'. –

+0

s.c_str() trả về một const char *, đó là lý do tại sao anh ta sao chép nó vào char * gọi là c. Trong hàm của bạn, bạn sẽ quay trở lại c. –

1

Bạn cần phải xem cách bạn xử lý bộ nhớ từ con trỏ bạn quay trở lại, ví dụ đoạn code dưới đây sẽ không làm việc vì nhớ bố trí trong std: : chuỗi sẽ được giải phóng khi fn() thoát.

const char* fn(const char*psz) { 
    std::string s(psz); 
    // do something with s 
    return s.c_str(); //BAD 
} 

Một giải pháp là phải phân bổ bộ nhớ trong hàm và chắc chắn rằng người gọi của hàm giải phóng nó:

const char* fn(const char*psz) { 
    std::string s(psz); 
    // do something with s 
    char *ret = new char[s.size()]; //memory allocated 
    strcpy(ret, s.c_str()); 
    return ret; 
} 
.... 
const char* p = fn("some text"); 
//do something with p 
delete[] p;// release the array of chars 

Ngoài ra, nếu bạn biết một trên ràng buộc về kích thước của chuỗi bạn có thể tự tạo nó trên ngăn xếp và chuyển vào một con trỏ, ví dụ

void fn(const char*in size_t bufsize, char* out) { 
    std::string s(psz); 
    // do something with s 
    strcpy_s(out, bufsize, s.c_str()); //strcpy_s is a microsoft specific safe str copy 
} 
.... 
const int BUFSIZE = 100; 
char str[BUFSIZE]; 

fn("some text", BUFSIZE, str); 
//ok to use str (memory gets deleted when it goes out of scope) 
0

Bạn có thể duy trì một bộ thu rác cho thư viện của bạn thực hiện như std::vector<char*> g_gc; có thể truy cập vào thư viện của bạn 'lib'.Sau đó, bạn có thể giải phóng tất cả các con trỏ trong g_gc một cách thuận tiện bằng cách gọi lib::release_garbage();

char* lib::func(char*pStr) 
{ 
    std::string str(pStr); 
    char *outStr = new char[str.size()+1]; 
    strcpy(outStr, str.c_str()); 
    g_gc.push_back(outStr); // collect garbage 
    return outStr; 
} 

chức năng release_garbage sẽ trông giống như:

void lib::release_garbage() 
{ 
    for(int i=0;i<g_gc.size();i++) 
    { 
     delete g_gc[i]; 
    } 
    g_gc.clear(); 
} 

Trong một mô hình luồng duy nhất, bạn có thể giữ này g_gc tĩnh. Mô hình đa luồng sẽ liên quan đến việc khóa/mở khóa nó.

+0

Đây là _very_ nguy hiểm; lưu trữ con trỏ trần trong một container hầu như luôn luôn là một ý tưởng tồi, bởi vì nó là rất khó khăn để đảm bảo an toàn ngoại lệ. (Xem tại đây để biết các lựa chọn thay thế: http://stackoverflow.com/questions/2558134/2558152#2558152). Ngoài ra, mã trong câu trả lời của bạn có lỗi nghiêm trọng: nó sử dụng 'không khớp' mới 'và' xóa' không khớp. –

+0

đó là một chủ đề tuyệt vời. Cảm ơn bạn đã chỉ ra về xóa []. – Pankaj

+0

Và với điều này bạn thậm chí không thể "thu thập rác" theo yêu cầu vì một số con trỏ có thể được sử dụng. Bạn chỉ có thể làm điều đó một cách an toàn khi ứng dụng của bạn thoát, điều này làm cho nó vô dụng vì bộ nhớ được cấp phát sẽ được giải phóng khi ứng dụng của bạn thoát. – Blindy

Các vấn đề liên quan