01/10/2018, 09:53

Hàm có kiểu trả về char * thì có return được char[] không?

Xin chào ae. Tình hình là mình đang làm 1 bài tập tìm từ có độ dài lớn nhất trong 1 chuỗi cho trước và in từ đó ra màn hình.
Đây là code:

#include <stdio.h>
#include <string.h>

char * findLongestWord(char *);

int main()
{
    char str[] = "Lorem ipsum dolor sit amet.";
    printf("The longest word: %s
", findLongestWord(str));
    return 0;
}

char * findLongestWord(char *str)
{
    char *s = strdup(str);
    //const size_t size = strlen(s);
    //char result[size];
    char *result = NULL;
    int length;
    char *arr = strtok(s, " ,./?:;!");
    //strcpy(result, arr);
    result = strdup(arr);
    length = strlen(arr);
    while ((arr = strtok(NULL, " ,./?:;!")) != NULL) {
        int _size = strlen(arr);
        if (_size >= length) {
            length = _size;
            //strcpy(result, arr);
            result = strdup(arr);
        }
    }
    return result;
}

Trong quá trình code, mình thấy nếu ko dùng char * result mà dùng char result[] thì khi return kq về, hàm printf() ko in ra đc ! Vì thế mình post lên đây để hỏi kỹ là hàm có kiểu trả về char * thì có return char[] được không?
Xin cảm ơn ae trước

rogp10 viết 11:57 ngày 01/10/2018

Không. Bạn phải malloc ra vì khi thoát khỏi hàm là mất luôn mảng char[].

Nguyễn Thanh Việt viết 12:02 ngày 01/10/2018

Bạn phải malloc ra vì quay về caller là mất luôn mảng char[]

Mình chưa hiểu ý này lắm bạn @@

rogp10 viết 11:58 ngày 01/10/2018

Vì char[] này là local và non-static nên nó chỉ tồn tại khi hàm đó đang chạy thôi, thoát ra khỏi hàm rồi là mất luôn.

Nguyễn Thanh Việt viết 11:54 ngày 01/10/2018

Ừm, vẫn chưa hiểu ^^
Lúc này char[] phải nằm trong Stack ko bạn?

rogp10 viết 12:00 ngày 01/10/2018

Đúng vậy, nên trước khi trả về, runtime sẽ rút lại stack.

Trần Hoàn viết 11:58 ngày 01/10/2018

con trỏ và mảng là 2 kiểu dữ liệu khác nhau, bạn này tư duy không giống cách nghĩ thông thường, dự tương lai phát minh ra ngôn ngữ mới :))

HK boy viết 11:59 ngày 01/10/2018

Mình cùng suy nghĩ với bạn =))) có khi lại phát minh thêm cả thuật toán khủng nhất nhì thế giới đây :v
Mà không hiểu thớt học C++ C kiểu gì nhỉ :v
Hỏi thớt luôn: sao #include <string.h> mà sao không dùng luôn std::string? Mình đọc code của bạn mà đau hết cả não :’(

rogp10 viết 12:09 ngày 01/10/2018

Nãy giờ thớt có viết câu nào của C++ đâu nhỉ?

Mà mảng với con trỏ vẫn khác nhau chớ mảng là nguyên một vùng nhớ, con trỏ chỉ là một ô nhớ thôi.

HK boy viết 11:57 ngày 01/10/2018

Mình hơi thắc mắc tí, sao thớt không sang C++ luôn nhỉ :v Thấy #include <string.h> mà không dùng C++ STL thì hơi phí :v Mình không thích code string bằng mảng lắm…
Căn bản tại thớt code hơi đau mắt (nhiều hàm khủng quá, mình phát khiếp) nên mình nghĩ thớt dùng STL cho lẹ :v

p/s: mà bài dễ thế này thì cần gì phải nghĩ phức tạp hoá vấn đề lên làm gì nhỉ, cứ for bình thường rồi cộng chuỗi, so độ dài là xong mà :v

Nguyễn Thanh Việt viết 12:06 ngày 01/10/2018

Đúng vậy, nên trước khi trả về, runtime sẽ rút lại stack.

À, mình có nghe nói là vùng nhớ Stack do CPU quản lý, nên nó sẽ tự hủy ô nhớ bất kỳ hoặc dãy ô nhớ bất kỳ khi ko sử dụng. Vậy trong trường hợp trên, khi thoát ra khỏi hàm là char[] đó bị CPU hủy đi rồi đúng ko bạn?
Mà runtime là j ấy nhỉ? ^^

con trỏ và mảng là 2 kiểu dữ liệu khác nhau

Uhm, tại mình thấy char * với char[] “hơi” giống nhau nên thắc mắc hỏi thử
mà nó khác nhau ở những chỗ nào bạn nhỉ?

sao #include <string.h> mà sao không dùng luôn std::string?

Chắc std::string thuộc thư viện string của C++ ^^ (mình chưa học C++ nên chưa biết)
Nếu bạn đọc code mình kỹ thì thấy bt thôi mà, mình chỉ dùng 2 hàm thông dụng là strdup()strtok() với thuật toán là cứ gặp những ký tự như khoảng trắng, dấu chấm, dấu phẩy, chấm hỏi, chấm than … thì cắt ra lấy từ đằng trước và so với chuỗi kết quả rồi cuối cùng return v ề thôi !

Thấy #include <string.h> mà không dùng C++ STL thì hơi phí :v Mình không thích code string bằng mảng lắm…

string.h là của C mà bạn, nó đâu bao hàm những object, container như trong C++ STL đâu. Còn std::string là object của C++ trong thư viện string nên mình đâu thể sử dụng đc.

nhiều hàm khủng quá, mình phát khiếp

hàm nào khủng bạn?
Dùng STL thì đâu còn tư duy nữa !

mà bài dễ thế này thì cần gì phải nghĩ phức tạp hoá vấn đề lên làm gì nhỉ, cứ for bình thường rồi cộng chuỗi, so độ dài là xong mà :v

Mình luôn muốn code hoạt động đúng hết nhiều trường hợp có thể. Mà cách hoạt động của code trên cũng giống như cách bạn nói roi` mà?

Nguyễn Thanh Việt viết 11:58 ngày 01/10/2018
#include <stdio.h>
#include <string.h>

char * findLongestWord(char *);

int main()
{
    char str[] = "Lorem ipsum dolor sit amet.";
    printf("The longest word: %s\n", findLongestWord(str));
    return 0;
}

char * findLongestWord(char *str)
{
    char *s = strdup(str);
    char *result = NULL;
    int length;
    char *arr = strtok(s, " ,./?:;!");
    result = strdup(arr);
    length = strlen(arr);
    while ((arr = strtok(NULL, " ,./?:;!")) != NULL) {
        int _size = strlen(arr);
        if (_size >= length) {
            length = _size;
            result = strdup(arr);
        }
    }
    return result;
}

HK boy viết 11:54 ngày 01/10/2018

Uhm, tại mình thấy char * với char[] “hơi” giống nhau nên thắc mắc hỏi thử
mà nó khác nhau ở những chỗ nào bạn nhỉ?

Link so sánh: https://www.programiz.com/c-programming/c-pointers-arrays

Cách hoạt động của code trên như thế, nhưng mình chưa thấy thế :v
Bài này đâu cần bất cứ hàm gì của C đâu :v dùng hàm substr cũng là hơi quá tay rồi :v
Để loại các trường hợp thì bạn dùng if thôi, cần gì các hàm.

Mình nói thật lòng là hãy code dễ nhìn, dễ hiểu, dễ nhớ nhất có thể. Không phải cứ dùng nhiều hàm là mạnh. Nhiều hàm bạn dùng nhưng sau này sẽ không bao giờ nhìn nữa.

Think like a kid. Please, like a kid. - SPOJ

Code là lâu dài. Tư duy cũng là lâu dài. Nhiều người càng học càng nghĩ phức tạp hoá vấn đề, kể cả những vấn đề đơn giản nhất.

Dùng STL thì đâu còn tư duy nữa !

Dùng STL không phải là không còn tư duy nữa. Phải có ý niệm về nó trước, phải hiểu rồi mới sử dụng được thành thục được. Dùng được là cả 1 quá trình code và hiểu. Các hàm của C/C++ cũng vậy. Không phải cứ thích là dùng. Các hàm sẽ có 1 độ phức tạp khác nhau, cách sử dụng cũng tuỳ các trường hợp khác nhau và mình gặp cực kì nhiều trường hợp dùng hàm của C/C++ thì bị sai đến mức không nhìn nổi lỗi sai nữa (bản thân mình cũng gần chết vì các hàm về string trong C/C++); nhiều trường hợp khác dùng hàm của C/C++ thì chạy quá thời gian còn bỏ hàm ra thì ăn ngay. Mình vẫn mong muốn những người học sau này nhớ, cần thiết thì dùng hàm, hàm phức tạp quá thì bỏ ngay. Hàm cho sẵn có sức mạnh của nó, không nắm vững mà đã sử dụng là không ổn.
Mình vẫn muốn các bạn nghĩ gì code nấy. Nghĩ là nếu thì viết if. Nghĩ là khác thì viết !=,… Đừng phức tạp hoá code.

Trần Hoàn viết 12:05 ngày 01/10/2018

Uhm, tại mình thấy char * với char[] “hơi” giống nhau nên thắc mắc hỏi thử
mà nó khác nhau ở những chỗ nào bạn nhỉ?

Mình cũng chẳng biết chúng nó khác nhau thế nào nữa. Chỉ biết mảng và con trỏ chúng nó khác nhau và không cast được từ mảng sang con trỏ thôi.

rogp10 viết 11:53 ngày 01/10/2018

À, mình có nghe nói là vùng nhớ Stack do CPU quản lý, nên nó sẽ tự hủy ô nhớ bất kỳ hoặc dãy ô nhớ bất kỳ khi ko sử dụng. Vậy trong trường hợp trên, khi thoát ra khỏi hàm là char[] đó bị CPU hủy đi rồi đúng ko bạn?
Mà runtime là j ấy nhỉ? ^^

Không, OS không thực hiện mấy thao tác ntn khi chương trình vẫn còn chạy.

Bổ sung #13: strtok viết lên chuỗi ban đầu nên không thể chạy nửa chừng. http://en.cppreference.com/w/cpp/string/byte/strtok (để ý chuỗi nào không bị ghi lên thì đều đánh const hết)

Ngoài ra bạn có thể lưu lại con trỏ chứa từ dài nhất để malloc và strdup ra ngoài một lần duy nhất.

Nguyễn Thanh Việt viết 12:08 ngày 01/10/2018

Mình đã nói là mình code theo những gì mình nghĩ nhé lúc đầu mình có nghĩ ra cách dài hơn nữa kìa, nhưng sau khi suy nghĩ lại thì thấy dùng hàm strtok() ngắn hơn nên dùng thôi

Bài liên quan
0