2010-02-04 44 views
24

Tôi thấy mã getcwd của C qua: man 3 cwdCó tương đương C++ với getcwd không?

Tôi nghi ngờ C++ có dạng tương tự, có thể trả về chuỗi std ::.

Nếu có, nó được gọi là gì và tôi có thể tìm tài liệu ở đâu?

Cảm ơn!

+4

Tại sao không chỉ sử dụng 'std :: string cwd = getcwd();' và để hàm tạo thực hiện công việc? – LiraNuna

+0

sẽ không phải là bộ nhớ bị rò rỉ? – anon

+4

Có getcwd() bộ nhớ bị rò rỉ nếu bạn không giải phóng nó? Nếu vậy, sau đó bạn nên giải phóng nó sau khi tạo chuỗi, trái ngược với giải phóng nó khi bạn không còn cần nó nữa, và điều đó thuận tiện hơn. Nếu không, sau đó khởi tạo chuỗi sẽ không bị rò rỉ bộ nhớ. –

Trả lời

20

Ok, tôi trả lời ngay cả khi bạn đã chấp nhận câu trả lời.

Một cách tốt hơn để quấn cuộc gọi getcwd sẽ là sử dụng boost::filesystem, trong đó bạn nhận được đối tượng path từ chức năng current_path(). Thư viện hệ thống tập tin Boost cho phép bạn thực hiện rất nhiều công cụ hữu ích khác mà bạn cần làm nhiều phân tích chuỗi để thực hiện, như kiểm tra xem tệp/thư mục có tồn tại hay không, lấy đường dẫn gốc, tạo đường dẫn hoàn chỉnh etcetera. Kiểm tra nó ra, nó là xách tay là tốt - mà rất nhiều chuỗi phân tích cú pháp một chuỗi nếu không sẽ sử dụng có khả năng sẽ không được.

Cập nhật (2016): Hệ thống tệp đã được xuất bản dưới dạng technical specification vào năm 2015, dựa trên Boost Filesystem v3. Điều này có nghĩa là nó có thể có sẵn với trình biên dịch của bạn (ví dụ như Visual Studio 2015). Với tôi nó cũng dường như có khả năng là nó sẽ trở thành một phần của một tiêu chuẩn C++ trong tương lai (tôi sẽ giả sử C++ 17, nhưng tôi không nhận thức được tình trạng hiện tại).

Update (2017): Các filesystem library đã được sáp nhập với ISO C++ trong C++ 17, cho

std::filesystem::current_path(); 
+1

Tất nhiên, trong một số trường hợp, nó có thể không đáng giá bao gồm thư viện boost :: filesystem chỉ để lấy thư mục làm việc hiện tại. Mặc dù, nếu anh ta đang làm rất nhiều công cụ hệ thống tập tin, sau đó họ cũng có thể sử dụng tăng cho tất cả của nó. –

+7

Tại sao mọi câu trả lời đều tăng :: tăng này :: đó? – TheRealChx101

+0

@ chx101: Tôi không nghĩ rằng Boost luôn là câu trả lời. Nhưng trong một số trường hợp nó là, và sử dụng một cái gì đó đã tồn tại và làm cho cuộc sống của bạn dễ dàng hơn thường là một điều tốt. Lưu ý rằng một số điều mà bây giờ trong tiêu chuẩn C++ đến từ Boost và hệ thống tập tin Boost được dự kiến ​​đưa vào như là một đặc tả kỹ thuật iirc. – villintehaspam

17

std::string hàm tạo của an toàn có thể lấy tham số char* một cách an toàn. Đáng ngạc nhiên là có một số windows version.

Edit: thực sự đó là một chút phức tạp hơn:

std::string get_working_path() 
{ 
    char temp[MAXPATHLEN]; 
    return (getcwd(temp, MAXPATHLEN) ? std::string(temp) : std::string("")); 
} 

Memory là không có vấn đề - temp là một chồng dựa đệm, và các nhà xây dựng std :: string làm một bản sao. Có lẽ bạn có thể làm điều đó trong một lần, nhưng tôi không nghĩ rằng tiêu chuẩn sẽ đảm bảo điều đó.

Về phân bổ bộ nhớ, thông qua POSIX:

Các getcwd() chức năng có trách nhiệm đặt tên đường dẫn tuyệt đối của thư mục làm việc hiện tại trong mảng trỏ đến bởi buf, và trở về buf. Đường dẫn được sao chép vào mảng không chứa thành phần nào là liên kết tượng trưng. Đối số kích thước là kích thước tính bằng byte của mảng ký tự được chỉ ra bởi đối số buf. Nếu buf là một con trỏ rỗng, hành vi của getcwd() là không xác định.

+2

Cả hai câu trả lời này và bình luận của Liranuna sử dụng 'getcwd' như là một hàm không có đối số, nhưng tài liệu tôi thấy cho thấy hai tham số. Tôi có đọc tài liệu sai không? –

+2

là char * tự động giải phóng? hoặc điều này cho tôi một rò rỉ bộ nhớ? – anon

+0

@anon no, char kết quả * là 'malloc' ed và phải là' free' d sau khi tạo chuỗi std :: từ nó. – Bill

3

Tất cả các hàm C cũng là hàm C++. Nếu bạn cần số std::string, chỉ cần tạo một tài khoản từ số char* mà getcwd nhận được cho bạn.

4

Bạn sẽ chỉ cần viết một trình bao bọc nhỏ.

std::string getcwd_string(void) { 
    char buff[PATH_MAX]; 
    getcwd(buff, PATH_MAX); 
    std::string cwd(buff); 
    return cwd; 
} 
+0

Bạn nên sử dụng PATH_MAX thay vì số ma thuật. – Bill

+0

@Bill cảm ơn, tìm hiểu điều gì đó mới mẻ mỗi ngày. –

+0

Tuyệt vời, cảm ơn! –

11

Hãy thử và viết lại gọi C đơn giản này như C++:

std::string get_working_path() 
{ 
    char temp [ PATH_MAX ]; 

    if (getcwd(temp, PATH_MAX) != 0) 
     return std::string (temp); 

    int error = errno; 

    switch (error) { 
     // EINVAL can't happen - size argument > 0 

     // PATH_MAX includes the terminating nul, 
     // so ERANGE should not be returned 

     case EACCES: 
      throw std::runtime_error("Access denied"); 

     case ENOMEM: 
      // I'm not sure whether this can happen or not 
      throw std::runtime_error("Insufficient storage"); 

     default: { 
      std::ostringstream str; 
      str << "Unrecognised error" << error; 
      throw std::runtime_error(str.str()); 
     } 
    } 
} 

Vấn đề là, khi gói một hàm thư viện trong một hàm khác, bạn phải giả định rằng tất cả các chức năng cần được tiếp xúc, bởi vì một thư viện không biết cái gì sẽ gọi nó. Vì vậy, bạn phải xử lý các trường hợp lỗi thay vì chỉ nuốt chúng hoặc hy vọng chúng sẽ không xảy ra. Nó thường tốt hơn để cho mã khách hàng chỉ cần gọi chức năng thư viện, và đối phó với lỗi tại thời điểm đó - mã khách hàng có lẽ không quan tâm tại sao lỗi xảy ra, và do đó chỉ phải xử lý pass/fail trường hợp, thay vì tất cả các mã lỗi.

+1

Có lỗi đánh máy. Nó phải là '! = 0' thay vì' == 0' trên dòng thứ năm. – Phantrast

2

tôi đã sử dụng getcwd() trong C theo cách sau:

char * cwd; 
cwd = (char*) malloc(FILENAME_MAX * sizeof(char)); 
getcwd(cwd,FILENAME_MAX); 

File header cần thiết là stdio.h. Khi tôi sử dụng trình biên dịch C, nó hoạt động hoàn hảo.

Nếu tôi biên dịch chính xác cùng mã sử dụng trình biên dịch C++, nó báo cáo các thông báo lỗi sau:

identifier "getcwd" is undefined 

Sau đó, tôi bao gồm unistd.h và biên soạn với C++ biên dịch. Lần này, mọi thứ đều hoạt động. Khi tôi chuyển về trình biên dịch C, nó vẫn hoạt động!

Miễn là bạn bao gồm cả stdio.hunistd.h, mã ở trên hoạt động cho trình biên dịch C VÀ C++.

+0

+1 để xác minh trong cả hai trình biên dịch và xác minh lại sau khi thay đổi. –

1

Tôi cũng đã sử dụng tăng cường :: hệ thống tệp như được nêu trong câu trả lời khác ở trên. Tôi chỉ muốn thêm rằng vì hàm current_path() không trả lại chuỗi std ::, bạn cần chuyển đổi nó.

Dưới đây là những gì tôi đã làm:

std::string cwd = boost::filesystem::current_path().generic_string(); 
0

Bạn có thể tạo một hàm mới, mà tôi muốn qua liên kết đến một thư viện như tăng (trừ khi bạn đã có).

std::string getcwd() 
{ 
    char* buff;//automatically cleaned when it exits scope 
    return std::string(getcwd(buff,255)); 
} 
Các vấn đề liên quan