01/10/2018, 08:13

Return hai giá trị trong một hàm C/C++

Chào mọi người mình đang làm một chương trình C++
Trong đó mình viết cho nó một cái hàm sẽ trả về hai giá trị
Nhưng mà trong C++ nó lại không dễ trả về hai giá trị bạn nào biết làm không chỉ mình với
Mình có tìm trên mạng thấy nó có ghi là dùng thư viện tuple nhưng mà mình lại ko biết dùng

Phạm Vinh viết 10:19 ngày 01/10/2018

Chào bạn, về vấn đề của bạn thì mình nghĩ kiểu dữ liệu struct là phù hợp nhất
Về cơ bản Struct là một kiểu dữ liệu bao gồm nhiều thành phần có thể thuộc nhiều kiểu dữ liệu khác nhau. Các thành phần được truy nhập thông qua một tên.
Lúc return bạn chỉ cần return tên của struct
Để tìm hiểu rõ hơn bạn có thể đọc qua ở đây:
https://www.stdio.vn/articles/read/166/struct-va-union

Hoàng Khoa viết 10:25 ngày 01/10/2018

Mình nghĩ nên truyền gửi vào 2 parameters, xong rồi gán giá trị cho 2 parameters đó là được. Gọi là truyền tham chiếu ấy hope it help :3

viết 10:29 ngày 01/10/2018

dùng đơn giản thôi, #include <tuple> rồi xài, nhớ bật std=c++14

#include <iostream>
#include <tuple>
#include <string>

auto func()
{
    std::string s = "hi";
    int n = 10;
    float f = 10.9;
    return std::make_tuple(s, n, f);
}

int main()
{
    std::string s;
    int n;
    float f;
    
    std::tie(s, n, f) = func();
    
    std::cout << s << " " << n << " " << f << "\n";
}
  • trong hàm func() để kiểu trả về là auto (C++14) hoặc std::tuple<std::string, int, float> (C++11). Để auto cho khỏe.
  • xài std::make_tuple(...) để “đóng gói” các giá trị lại thành 1 tuple.
  • xài std::tie(...) để lấy từng giá trị trong tuple ra.

C++17 hứa hẹn cho viết dễ hơn nữa: xài auto[...] để lấy giá trị, và chẳng cần nhớ nó trả về kiểu giá trị gì. (vd ở đây chẳng cần nhớ s, n, f kiểu giá trị là gì)

#include <iostream>
#include <tuple>

auto func()
{
    std::string s = "hi";
    int n = 10;
    float f = 10.9;
    return std::make_tuple(s, n, f);
}

int main()
{
    auto[s, n, f] = func();
    std::cout << s << " " << n << " " << f << "\n";
}

trước C++11 thì phải tạo định nghĩa 1 kiểu struct rồi trả về struct này. Hoặc có thể truyền tham chiếu vào hàm cần trả về nhiều giá trị.

Nguyễn Hiến viết 10:23 ngày 01/10/2018

Yeah mình cũng thử dùng đến struct và cuối cùng nó cũng hoạt động được cám ơn bạn

Nguyễn Hoàng Trung viết 10:30 ngày 01/10/2018

cho em hỏi bật std=c++14 ở đâu ạ

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

Option đó của g++. Bạn dùng VS?

Thực ra hai trị thì dùng std::pair được rồi, std::tuple đến C++11 mới có và nó là trường hợp tổng quát. Không nên dùng makeshift struct mà chỉ nên viết thẳng vào prototype.

viết 10:14 ngày 01/10/2018

tùy vào bạn đang dùng compiler gì, gu gồ tìm cách bật C++14 cho compiler đó là lẹ nhất

Nguyễn Hoàng Trung viết 10:30 ngày 01/10/2018

À tại em tưởng đâu dùng dòng lệnh luôn ạ :v nếu em xài bên g++ thì làm sao ạ?

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

Bạn thêm tham số -std=c++14 vào sau cách gọi g++ bt của bạn.

  • Từ 4.8 mới hỗ trợ đầy đủ chuẩn C++11.
  • Từ 5.x trở đi hỗ trợ “sơ sơ” một phần chuẩn C++14. (tham số -std=c++1x)
  • Từ 5.2 trở đi hỗ trợ C++14 qua tham số -std=c++14.
The Wind viết 10:30 ngày 01/10/2018

Mình ngày trc code C++ thỉnh thoảng cũng muốn trả về hơn 2 giá trị mà k biết làm thế nào …
Thế là nghĩ ra việc dùng mảng với con trỏ …
Bằng cách gán các giá trị cần trả vào 1 mảng nào đó .Sau khi kết thúc hàm thì trả về cái mảng ấy(Dùng con trỏ ) ! Rồi sau đó sử dụng ở main !
Giờ mình mới biết đến tuple .Căn bản sách dạy C++ của mềnh k có nên cũng k biết

Đỗ Trung Quân viết 10:14 ngày 01/10/2018

Sao mọi người nghĩ phức tạp vậy nhỉ. Trả về 1 array, object hoặc 1 string cũng được mà.

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

@Kulteam viết như vậy không bảo trì được.
@^: như trên.

Đỗ Trung Quân viết 10:18 ngày 01/10/2018

Bạn có thể chỉ ra cái khó ở đây không

viết 10:18 ngày 01/10/2018

vd trả về 3 kiểu khác nhau thì sao? Trả về {string, int, float} thì đâu có xài mảng được. Trả về string rồi phải parse string này thành {string,int,float} thì bó tay.com Trả về object chứa string, int, float thì ok, nhưng mất công viết 1 cái class/struct mà có thể chỉ xài 1 lần để trả về {string,int,float} ở cái hàm này.

trong Python có cho trả về nhiều kiểu rất là khỏe:

def func():
    return "hi", 20, 90.8 # trả về tuple

msg, n, avg = func() # khỏe re

C++ cũng bắt chước với std::tuple, nhưng phải viết dài dòng hơn: std::make_tuple(...) và khi lấy ra phải viết std::tie(...) và khai báo từng kiểu trả về trước đó. C++17 cho viết theo kiểu auto[...] mà ko cần khai báo kiểu trước đó nữa thì quá sướng

#include <tuple>

auto func()
{
  return std::make_tuple(std::string("hi"), 20, 90.8f);
}

int main()
{
  auto [msg, n, avg] = func();
}

compile thử với C++17: https://godbolt.org/g/PFYYZl

ko khác Python là bao

edit: nếu viết kiểu trả về ra rõ ràng thì có thể viết gọn hơn, xài initializer_list thay cho std::make_tuple:

std::tuple<std::string, int, float> func()
{
  return {"hi", 20, 90.8f};
}
kiencon viết 10:16 ngày 01/10/2018

Cho mình hỏi sao không dùng tham chiếu mà lại cố gắng trả về nhiều giá trị? Liệu trả về nhiều giá trị sẽ có thể dễ phát triển, bảo trì hơn?

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

Theo nguyên tắc self-documenting code (self-descriptive thì đúng hơn) thì nên dùng tham chiếu hay struct do ko thể đặt tên cho thành phần trong std::tuple.

Nhưng dùng struct sẽ dẫn đến những tên struct “bá đạo” (phải đặt là outputFunc + tên hàm hay đại loại vậy).

Điều này cho thấy trả về một std::tuple chỉ nên xài ở C++1z mode (chưa có 17).

Nguyen Quang Hien viết 10:14 ngày 01/10/2018

return về một arraylà cách hay nhất.

Bài liên quan
0