2010-02-04 26 views
24

Vedo getcwd di C tramite: man 3 cwdEsiste un equivalente in C++ per getcwd?

ho il sospetto C++ ha uno simile, che mi potrebbe restituire uno std :: string.

Se sì, come si chiama e dove posso trovare la documentazione?

Grazie!

+4

perché non basta usare 'std :: string cwd = getcwd();' e lasciare che il costruttore di fare il suo lavoro? – LiraNuna

+0

non sarà quella perdita di memoria? – anon

+4

getcwd() perde memoria se non lo si libera? Se è così, allora dovresti liberarlo dopo aver creato la stringa, invece di liberarla quando non ne hai più bisogno, e questo è più conveniente. In caso contrario, l'inizializzazione della stringa non causerà perdite di memoria. –

risposta

20

Ok, sto rispondendo anche se hai già accettato una risposta.

Un modo ancora migliore di racchiudere la chiamata getcwd è utilizzare boost::filesystem, dove si ottiene un oggetto path dalla funzione current_path(). La libreria del filesystem Boost ti permette di fare molte altre cose utili che altrimenti dovresti fare un sacco di parsing di stringhe, come controllare se esistono file/directory, ottenere il percorso genitore, rendere i percorsi completi eccetera. Controllalo, è anche portatile - il che molto probabilmente non sarà il codice di parsing di stringhe che verrebbe altrimenti usato.

Aggiornamento (2016): Il file system è stato pubblicato come technical specification nel 2015, basato su Boost Filesystem v3. Ciò significa che potrebbe essere già disponibile con il compilatore (ad esempio Visual Studio 2015). A me sembra anche probabile che diventerà parte di un futuro standard C++ (assumerei C++ 17, ma non sono a conoscenza dello stato attuale).

Update (2017): Il filesystem library è stata fusa con ISO C++ in C++ 17, per

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

Naturalmente, in alcune situazioni potrebbe non valere la pena includere la libreria boost :: filesystem solo per ottenere la directory di lavoro corrente. Tuttavia, se lui/lei sta facendo un sacco di cose sul filesystem, allora possono anche usare boost per tutto questo. –

+7

Perché ogni risposta aumenta: questa spinta :: quella? – TheRealChx101

+0

@ chx101: Non penso che Boost sia sempre la risposta. Ma in alcuni casi lo è, e usare qualcosa che già esiste e rende la vita più facile di solito è una buona cosa. Nota che alcune cose che sono ora nello standard C++ provengono da Boost e che Boost Filesystem è previsto per l'inclusione come specifica tecnica iirc. – villintehaspam

17

Il costruttore di std::string può prendere tranquillamente un char* come parametro. Sorprendentemente c'è anche lo windows version.

Edit: in realtà è un po 'più complicato:

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

memoria non è un problema - temp è un buffer di stack based, e il costruttore std :: string fa una copia. Probabilmente potresti farlo in un colpo solo, ma non credo che lo standard lo garantirebbe.

chi allocazione di memoria, tramite POSIX: funzione

Il getcwd() appone percorso assoluto della directory di lavoro corrente nell'array puntato da buf, e BUF ritorno. Il percorso copiato nell'array non deve contenere componenti che sono collegamenti simbolici. L'argomento dimensione è la dimensione in byte della matrice di caratteri indicata dall'argomento buf. Se buf è un puntatore nullo, il comportamento di getcwd() non è specificato.

+2

Sia questa risposta che il commento di Liranuna usano 'getcwd' come una funzione senza argomenti, eppure la documentazione che vedo mostra due parametri. Sto leggendo i documenti sbagliati? –

+2

è il char * automaticamente liberato? o questo mi dà una perdita di memoria? – anon

+0

@anon no, il char risultante * è 'malloc' ed e dovrebbe essere' free' d dopo aver creato una stringa std :: da esso. – Bill

3

Tutte le funzioni C sono anche funzioni C++. Se hai bisogno di un std::string, creane uno dal numero char* che getcwd ottiene per te.

4

Dovrai solo scrivere un piccolo involucro.

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

È necessario utilizzare PATH_MAX invece di un numero magico. – Bill

+0

@Bill grazie, impara qualcosa di nuovo ogni giorno. –

+0

Eccellente, grazie! –

11

Proviamo e riscrivere questa semplice chiamata C come 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()); 
     } 
    } 
} 

Il fatto è che quando si avvolge una funzione di libreria in un'altra funzione si deve presupporre che tutte le funzionalità dovrebbero essere esposte, perché una libreria non sa come la chiamerà. Quindi devi gestire i casi di errore piuttosto che inghiottirli o sperare che non succedano.

In genere è preferibile lasciare che il codice client chiami la funzione di libreria e gestisca l'errore a quel punto: il codice client probabilmente non si preoccupa del perché si è verificato l'errore e quindi deve gestire solo il passaggio/errore caso, piuttosto che tutti i codici di errore.

+1

C'è un errore di battitura. Dovrebbe essere '! = 0' invece di' == 0' sulla quinta riga. – Phantrast

2

ho usato getcwd() in C nel seguente modo:

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

Il file di intestazione necessaria è stdio.h. Quando uso il compilatore C, funziona perfettamente.

Se compilo esattamente lo stesso codice usando il compilatore C++, si riporta il seguente messaggio di errore:

identifier "getcwd" is undefined 

Poi ho compreso unistd.h e compilato con compilatore C++. Questa volta, tutto funziona. Quando torno al compilatore C, funziona ancora!

Finché si includono sia stdio.h e unistd.h, il codice precedente funziona per i compilatori C AND C++.

+0

+1 per verificare in entrambi i compilatori e ricontrollarlo dopo le modifiche. –

1

Ho anche utilizzato boost :: filesystem come indicato in un'altra risposta sopra. Volevo solo aggiungere che dal momento che la funzione current_path() non restituisce una stringa std ::, è necessario convertirla.

Ecco quello che ho fatto:

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

è possibile creare una nuova funzione, che io preferirei sopra il collegamento a una libreria come spinta (a meno che già sei).

std::string getcwd() 
{ 
    char* buff;//automatically cleaned when it exits scope 
    return std::string(getcwd(buff,255)); 
} 
Problemi correlati