รับชื่อไดเร็กทอรีจากชื่อไฟล์


85

ฉันมีชื่อไฟล์ (C: \ folder \ foo.txt) และฉันต้องการเรียกชื่อโฟลเดอร์ (C: \ folder) ใน C ++ ที่ไม่มีการจัดการ ใน C # ฉันจะทำสิ่งนี้:

string folder = new FileInfo("C:\folder\foo.txt").DirectoryName;

มีฟังก์ชันที่สามารถใช้ใน C ++ ที่ไม่มีการจัดการเพื่อแยกเส้นทางจากชื่อไฟล์ได้หรือไม่?

คำตอบ:


20

มีฟังก์ชั่นมาตรฐานของ Windows สำหรับเรื่องนี้คือPathRemoveFileSpec หากคุณรองรับเฉพาะ Windows 8 และใหม่กว่าขอแนะนำให้ใช้PathCchRemoveFileSpecแทน ในการปรับปรุงอื่น ๆ จะไม่ จำกัดMAX_PATHอักขระ (260) ตัวอีกต่อไป


2
โปรดทราบว่าฟังก์ชันนี้เลิกใช้งานแล้ว ข้อเสนอแนะจาก Microsoft คือให้ใช้PathCchRemoveFileSpecแทน
ค่าเริ่มต้น

1
@Default: PathCchRemoveFileSpecจะใช้ได้เฉพาะเริ่มต้นกับ Windows 8 ตั้งแต่ Windows Vista และ 7 ได้รับการสนับสนุนยังคงเพื่อให้เป็นPathRemoveFileSpec
IInspectable

154

ใช้ Boost.Filesystem:

boost::filesystem::path p("C:\\folder\\foo.txt");
boost::filesystem::path dir = p.parent_path();


หากคุณยังอาจจัดการกับไดเรกทอรีจะตระหนักถึงความจริงที่ว่าparent_path()จากจะส่งผลให้"C:\\folder" "C:"
Semjon Mössinger

การเพิ่มจำนวนมากได้รับการอัปเกรดเป็น std ดังนั้นลองใช้สิ่งนี้ด้วย .... รวม <filesystem> .... std :: experiment :: filesystem :: path p ("C: \\ folder \\ foo.txt");
S Meaden

72

ตัวอย่างจากhttp://www.cplusplus.com/reference/string/string/find_last_of/

// string::find_last_of
#include <iostream>
#include <string>
using namespace std;

void SplitFilename (const string& str)
{
  size_t found;
  cout << "Splitting: " << str << endl;
  found=str.find_last_of("/\\");
  cout << " folder: " << str.substr(0,found) << endl;
  cout << " file: " << str.substr(found+1) << endl;
}

int main ()
{
  string str1 ("/usr/bin/man");
  string str2 ("c:\\windows\\winhelp.exe");

  SplitFilename (str1);
  SplitFilename (str2);

  return 0;
}

1
นี่เป็นวิธีแก้ปัญหาขั้นต่ำที่ดีที่สุดที่นี่
plasmacel

42

ใน C ++ 17 มีอยู่ในชั้นเรียนโดยใช้วิธีการstd::filesystem::pathparent_path

#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main()
{
    for(fs::path p : {"/var/tmp/example.txt", "/", "/var/tmp/."})
        std::cout << "The parent path of " << p
                  << " is " << p.parent_path() << '\n';
}

ผลลัพธ์ที่เป็นไปได้:

The parent path of "/var/tmp/example.txt" is "/var/tmp"
The parent path of "/" is ""
The parent path of "/var/tmp/." is "/var/tmp"

3
นอกจากนี้ยังมี.remove_filename()วิธีการ
Qqwy

1
ขอบคุณ @Qqwy นอกจากนี้ยังอนุญาตให้ใช้เส้นทางไดเรกทอรีด้วยวิธีการนั้นเพื่อให้ได้ผลลัพธ์ที่ถูกต้องและคาดหวังซึ่งแตกต่างจากวิธีการจากคำตอบ
Herrgott

13

ทำไมมันต้องซับซ้อนขนาดนี้?

#include <windows.h>

int main(int argc, char** argv)         // argv[0] = C:\dev\test.exe
{
    char *p = strrchr(argv[0], '\\');
    if(p) p[0] = 0;

    printf(argv[0]);                    // argv[0] = C:\dev
}

10
ไม่สามารถพกพาได้ ตัวคั่นเส้นทางใน linux คือ "/" std :: filesystem :: path เป็นมาตรฐานและพกพาได้
Rémi

7
 auto p = boost::filesystem::path("test/folder/file.txt");
 std::cout << p.parent_path() << '\n';             // test/folder
 std::cout << p.parent_path().filename() << '\n';  // folder
 std::cout << p.filename() << '\n';                // file.txt

คุณอาจต้องp.parent_path().filename()ได้รับชื่อของโฟลเดอร์หลัก


5

ใช้ boost :: filesystem มันจะรวมอยู่ในมาตรฐานถัดไปดังนั้นคุณอาจคุ้นเคยกับมันเช่นกัน


1
คุณกำลังพูดถึงมาตรฐานใด ฉันรู้ว่ามีการเพิ่มหลายอย่างจากการเพิ่มลงใน C ++ std lib ระบบไฟล์จะถูกเพิ่มด้วยหรือไม่?
McLeary

7
"มันจะรวมอยู่ในมาตรฐานต่อไป" และมันก็ไม่ใช่
Anton K

@AntonK อาจจะ C ++ 2017?
Alessandro Jacopson

6
@AlessandroJacopson Cool ดูเหมือนว่าจะรวมอยู่ใน C ++ 17 - th.cppreference.com/w/cpp/filesystem
Anton K


1

ฉันประหลาดใจมากที่ไม่มีใครพูดถึงวิธีมาตรฐานใน Posix

โปรดใช้basename / dirnameโครงสร้าง

ผู้ชายพื้นฐาน


1
ฟังก์ชัน POSIX ไม่ได้ปราศจากข้อบกพร่อง โดยเฉพาะอย่างยิ่งพวกเขาอาจแก้ไขบัฟเฟอร์ที่คุณส่งผ่าน (จริงๆแล้วหมายถึงลายเซ็นbasname(char * path)ไม่ใช่basename(const char * path)) และการใช้งานที่ดูเหมือนจะไม่ต้องใช้บัฟเฟอร์แบบคงที่ซึ่งทำให้เธรดไม่ปลอดภัย (โดยหลักการแล้วคุณ นอกจากนี้ยังสามารถส่งคืนผลลัพธ์ที่จัดสรรแบบไดนามิก แต่นั่นทำให้คุณต้องพึ่งพาallocฟังก์ชันครอบครัวซึ่งไม่สะดวกใน C ++)
dmckee --- อดีตผู้ดูแลลูกแมว

-1

C ++ มาตรฐานจะไม่ทำอะไรให้คุณมากนักในเรื่องนี้เนื่องจากชื่อพา ธ เป็นชื่อเฉพาะแพลตฟอร์ม คุณสามารถแยกวิเคราะห์สตริงด้วยตนเอง (ตามคำตอบของ glowcoder) ใช้สิ่งอำนวยความสะดวกของระบบปฏิบัติการ (เช่นhttp://msdn.microsoft.com/en-us/library/aa364232(v=VS.85).aspx ) หรืออาจเป็น แนวทางที่ดีที่สุดคุณสามารถใช้ไลบรารีระบบไฟล์ของบุคคลที่สามเช่น boost :: filesystem


C ++ 1z ของมาตรฐานกำลังพยายามนำไลบรารีระบบไฟล์บูสต์มาใช้ในขณะนี้ทำให้ความเป็นมิตรกับแพลตฟอร์มน้อยลงมาก ยังคงอยู่ในส่วนหัวการทดลองสำหรับ MSVC เป็นอย่างน้อย
kayleeFrye_onDeck

-6

เพียงใช้สิ่งนี้: ExtractFilePath (your_path_file_name)


5
ฉันเชื่อว่านี่เป็นวิธีเดลฟีไม่ใช่บางอย่างใน C ++
Ian Hunter
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.