2013-07-27 31 views
9

Tôi đang đọc ấn bản thứ 3 của Ngôn ngữ lập trình C++ bởi Bjarne Stroustrup và cố gắng hoàn thành tất cả các bài tập. Tôi không chắc chắn làm thế nào để tiếp cận tập thể dục 13 từ phần 6.6, vì vậy tôi nghĩ rằng tôi muốn chuyển sang Stack Overflow cho một số cái nhìn sâu sắc. Dưới đây là mô tả của vấn đề:C++: Cách sử dụng mới để tìm cửa hàng cho giá trị trả về hàm?

Viết một hàm mèo() mà phải mất hai đối số chuỗi C-phong cách và trả về một chuỗi duy nhất đó là nối của các đối số. Sử dụng mới để tìm cửa hàng cho kết quả.

Dưới đây là mã của tôi vậy, đến nay, với dấu hỏi nơi tôi không biết phải làm gì:

? cat(char first[], char second[]) 
{ 
    char current = ''; 
    int i = 0; 

    while (current != '\0') 
    { 
     current = first[i]; 
     // somehow append current to whatever will eventually be returned 
     i++; 
    } 

    current = ''; 
    i = 0; 

    while (current != '\0') 
    { 
     current = second[i]; 
     // somehow append current to whatever will eventually be returned 
     i++; 
    } 

    return ? 
} 

int main(int argc, char* argv[]) 
{ 
    char first[] = "Hello, "; 
    char second[] = "World!"; 

    ? = cat(first, second); 

    return 0; 
} 

Và đây là câu hỏi của tôi:

  1. Làm thế nào để sử dụng mới để tìm cửa hàng? Tôi có dự kiến ​​sẽ làm điều gì đó như std::string* result = new std::string; hoặc tôi có nên sử dụng mới để tạo một chuỗi kiểu C khác không?
  2. Liên quan đến câu hỏi trước, tôi nên trở về từ con mèo nào()? Tôi cho rằng nó sẽ cần phải là một con trỏ nếu tôi phải sử dụng mới. Nhưng một con trỏ đến những gì?
  3. Mặc dù sự cố không đề cập đến việc sử dụng xóa để giải phóng bộ nhớ, tôi biết tôi nên vì tôi đã sử dụng mới để cấp phát. Tôi có nên chỉ cần xóa vào cuối của chính, ngay trước khi trở về?
+1

+1 Câu hỏi được sáng tác độc đáo. – Sabuncu

Trả lời

4

Làm cách nào để sử dụng mới để tìm cửa hàng? Tôi có dự kiến ​​sẽ làm điều gì đó như std::string* result = new std::string; hoặc tôi có nên sử dụng mới để tạo một chuỗi kiểu C khác không?

Loại thứ hai; phương thức lấy các chuỗi kiểu C và không có gì trong văn bản gợi ý rằng nó sẽ trả về bất kỳ thứ gì khác. Nguyên mẫu của hàm do đó sẽ là char* cat(char const*, char const*). Tất nhiên đây là không phải cách bạn thường viết chức năng; quản lý bộ nhớ thủ công hoàn toàn cấm kỵ trong C++ hiện đại bởi vì nó rất dễ bị lỗi.

Mặc dù vấn đề không đề cập đến việc sử dụng xóa để giải phóng bộ nhớ, tôi biết tôi nên vì tôi sẽ sử dụng mới để phân bổ. Tôi có nên chỉ cần xóa vào cuối của chính, ngay trước khi trở về?

Trong bài tập này, có. Trong thế giới thực, không: như tôi đã nói ở trên, điều này hoàn toàn cấm kỵ. Trong thực tế, bạn sẽ trả lại một số std::stringkhông cấp phát bộ nhớ bằng cách sử dụng new. Nếu bạn thấy mình phân bổ bộ nhớ theo cách thủ công (và giả sử đó là vì lý do chính đáng), bạn sẽ đặt bộ nhớ đó không ở con trỏ thô mà là con trỏ thông minh - std::unique_ptr hoặc std::shared_ptr.

4

Trong chương trình "thực", có, bạn sẽ sử dụng std :: string. Có vẻ như ví dụ này muốn bạn sử dụng chuỗi C thay thế.

Vì vậy, có lẽ một cái gì đó như thế này:

char * cat(char first[], char second[]) 
{ 
    char *result = new char[strlen(first) + strlen(second) + 1]; 

...

Q: Làm thế nào để bạn "gắn"?

A: Chỉ cần viết mọi thứ trong "đầu tiên" đến "kết quả".

Ngay sau khi bạn hoàn tất, sau đó tiếp tục bằng cách viết mọi thứ trong "giây" để có kết quả (bắt đầu từ nơi bạn đã dừng lại). Khi bạn hoàn tất, hãy đảm bảo nối thêm '\ 0' ở cuối.

+0

Có sử dụng 'strlen' bất cứ điều gì liên quan đến lập trình trong C++ không? – Antonio

+0

@Antonio: Có, khi xử lý các chuỗi kiểu C như đã nêu trong câu hỏi. – Blastfurnace

+0

@Blastfurnace Sau đó, không phải lý do tại sao strcpy và strcat? Tôi nghĩ rằng nếu bạn thực sự muốn tập thể dục về quản lý chuỗi và bộ nhớ, bạn nên nhận thức được sự tồn tại của các chức năng này, nhưng tập thể dục trong thực hiện của riêng bạn. – Antonio

3
  1. Bạn có nghĩa vụ trả lại chuỗi kiểu C, vì vậy bạn không thể sử dụng std::string (hoặc ít nhất, đó không phải là "theo tinh thần của câu hỏi"). Có, bạn nên sử dụng new để tạo chuỗi kiểu C.
  2. Bạn nên trả lại chuỗi kiểu C bạn đã tạo ... Vì vậy, con trỏ đến ký tự đầu tiên của chuỗi mới tạo.
  3. Đúng, bạn nên xóa kết quả ở cuối. Tôi hy vọng nó có thể bị bỏ qua, như trong trường hợp đặc biệt này, nó có thể không quan trọng nhiều - nhưng đối với tính đầy đủ/đúng đắn, bạn nên làm như vậy.
2

Ý nghĩa của việc tập thể dục là sử dụng new để cấp phát bộ nhớ. "Tìm cửa hàng" được nói một cách kỳ lạ, nhưng trên thực tế đó là những gì nó làm. Bạn nói với nó bao nhiêu cửa hàng bạn cần, nó tìm thấy một khối có sẵn của bộ nhớ mà bạn có thể sử dụng, và trả về địa chỉ của nó.

Nó không giống như bài tập muốn bạn sử dụng std :: string. Có vẻ như bạn cần trả lại char*. Vì vậy, nguyên mẫu chức năng phải là:

char * cat (const char first [], const char second []);

Lưu ý thông số const. Điều quan trọng là bạn sẽ có thể vượt qua chuỗi ký tự dưới dạng đối số. Vì vậy, nếu không đưa mã ra ngay lập tức, những gì bạn cần làm là xác định chuỗi số char* kết quả lớn như thế nào, phân bổ số tiền yêu cầu bằng cách sử dụng new, sao chép hai chuỗi nguồn vào không gian mới được phân bổ và trả lại . Lưu ý rằng bạn thường không thực hiện việc quản lý bộ nhớ kiểu này theo cách thủ công trong C++ (thay vào đó bạn sử dụng std::string), nhưng điều quan trọng là phải biết về nó, đó là lý do tại sao lý do cho bài tập này.

3

Dưới đây là một số mã cũ tôi đào lên từ một dự án của tôi một thời gian trở lại:

char* mergeChar(char* text1, char* text2){ 
    //Find the length of the first text 
    int alen = 0; 
    while(text1[alen] != '\0') 
     alen++; 

    //Find the length of the second text 
    int blen = 0; 
    while(text2[blen] != '\0') 
     blen++; 

    //Copy the first text 
    char* newchar = new char[alen + blen + 1]; 
    for(int a = 0; a < alen; a++){ 
      newchar[a] = text1[a]; 
    } 

    //Copy the second text 
    for(int b = 0; b < blen; b++) 
     newchar[alen + b] = text2[b]; 

    //Null terminate! 
    newchar[alen + blen] = '\0'; 
    return newchar; 
} 

Nói chung, trong một chương trình 'thực tế', bạn sẽ được dự kiến ​​sẽ sử dụng std::string, mặc dù. Đảm bảo bạn delete[] newchar sau!

+1

Bất kỳ lý do cụ thể nào để viết thủ công các phần này thay vì sử dụng các hàm thích hợp ('std :: strlen',' std :: strcpy')? Điều này dài hơn, ít dễ đọc hơn và dễ bị lỗi hơn. Đừng làm thế. –

+1

Ai đó cố gắng học không nên được cung cấp bộ mã hoàn chỉnh để giải quyết cùng một vấn đề - đó không phải là dạy cho người học bất cứ điều gì ngoài CTRL-C + CTRL-V, mà ai đó sử dụng SO có thể (dù đôi khi chỉ vừa đủ) biết . –

+2

Anh ấy hỏi về thao tác các chuỗi kiểu C. Tôi đang cho anh ta xem chuyện gì đang xảy ra. Nếu anh không muốn học, anh sẽ không đọc cuốn sách ngay từ đầu. Anh ấy nói anh ấy không sử dụng mã cho một ứng dụng trong thế giới thực, anh ấy sẽ xem xét tài liệu trong cuốn sách. – BrainSteel

0

Dường như bạn cần sử dụng new để cấp phát bộ nhớ cho một chuỗi và sau đó trả về con trỏ. Do đó, loại return của cat sẽ là `char*.

Bạn có thể làm làm một cái gì đó như thế này:

int n = 0; 
int k = 0; 

//also can use strlen 
while(first[n] != '\0') 
    n ++ ; 
while(second[k] != '\0') 
    k ++ ; 

//now, the allocation 

char* joint = new char[n+k+1]; //+1 for a '\0' 

//and for example memcpy for joining 

memcpy(joint, first, n); 
memcpy(joint+n, second, k+1); //also copying the null 


return joint; 
0

Đó là nói cho bạn để làm điều này C cách khá nhiều:

#include <cstring> 

char *cat (const char *s1, const char *s2) 
{ 
    // Learn to explore your library a bit, and 
    // you'll see that there is no need for a loop 
    // to determine the lengths. Anything C string 
    // related is in <cstring>. 
    // 
    size_t len_s1 = std::strlen(s1); 
    size_t len_s2 = std::strlen(s2); 
    char *dst; 

    // You have the lengths. 
    // Now use `new` to allocate storage for dst. 


    /* 
    * There's a faster way to copy C strings 
    * than looping, especially when you 
    * know the lengths... 
    * 
    * Use a reference to determine what functions 
    * in <cstring> COPY values. 
    * Add code before the return statement to 
    * do this, and you will have your answer. 
    * 
    * Note: remember that C strings are zero 
    * terminated! 
    */ 

    return dst; 
} 

Đừng quên sử dụng các nhà điều hành chính xác khi bạn đi để giải phóng bộ nhớ được phân bổ. Nếu không, bạn sẽ bị rò rỉ bộ nhớ.

Mã hóa vui vẻ! :-)

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