2009-04-16 6 views
8

Va bene, ecco l'accordo, sto prendendo un'introduzione alla classe C++ presso la mia università e sto avendo problemi a capire come modificare l'estensione di un file. Primo, quello che dovremmo fare è leggere in un file .txt e contare parole, frasi, vocali, ecc. Ho capito, ma il passo successivo è quello che mi preoccupa. Supponiamo quindi di creare un nuovo file usando lo stesso nome file del file di input ma con estensione .code anziché .txt (in quel nuovo file dobbiamo quindi codificare la stringa aggiungendo numeri casuali al codice ASCII di ogni personaggio se fossi interessato). Essendo un principiante nella programmazione, non sono abbastanza sicuro di come farlo. Sto utilizzando il seguente pezzo di codice per ottenere in un primo momento il file di input:Come si modifica l'estensione del nome file memorizzata in una stringa in C++?

cout << "Enter filename: "; 
cin >> filename; 
infile.open(filename.c_str()); 

sto assumendo per creare un nuovo file che ho intenzione di essere utilizzando qualcosa di simile:

outfile.open("test.code"); 

Ma non saprò quale sia il nome del file finché l'utente non lo inserirà, quindi non posso dire "test.txt". Quindi se qualcuno sa come cambiare quell'estensione quando creo un nuovo file lo apprezzerei molto!

risposta

8

Ci sono diversi approcci a questo.

È possibile adottare l'approccio super pigro e inserirli solo nel nome del file e non nell'estensione .txt. In tal caso, puoi aggiungere .txt ad esso per aprire il file di input.

infile.open(filename + ".txt"); 

Poi basta chiamare

outfile.open(filename + ".code"); 

L'approccio successivo sarebbe quello di prendere l'intero nome di file inclusa l'estensione, e basta aggiungere .code ad esso in modo che avresti avuto test.txt.code.

È un po 'ambiguo se questo è accettabile o meno.

Infine, è possibile utilizzare i metodi std::stringfind e replace per ottenere il nome file senza estensione e utilizzarlo.

+0

Va bene, penso che le opzioni siano più in linea con quello che stavo cercando, come abbiamo appreso di recente sui metodi di stringa. Grazie per l'input! –

+2

Better rfind() poiché troverà l'ultimo "." invece del primo nel caso in cui 'a.b.c.txt' è un nome file valido –

+1

.open() accetta un const char *, non un std :: sting purtroppo. – MSalters

3

Ecco alcuni suggerimenti. Si dispone di un nome di file già entrato - ciò che si vuole fare è ottenere la parte del nome del file che non include l'estensione:

std::string basename(const std::string &filename) 
{ 
    // fill this bit in 
} 

Dopo aver scritto quella funzione, è possibile utilizzarlo per creare il nome del nuovo File:

std::string codeFile = basename(filename) + ".code"; 
outFile.open(codeFile); 
+0

Non dimenticare di testare. Mi piace nominare i miei files.like.questo – veefu

0

Pseudo codice sarebbe quello di fare qualcosa di simile

outFilename = filename; 
<change outFilename> 
outfile.open(outFilename); 

per cambiare outFilename, guarda strrchr e strcpy come punto di partenza (potrebbe essere metodi più appropriati - che funzionerebbe benissimo con un char * però)

+0

Perché suggerire metodi in stile C quando il codice è C++? –

4

Non darlo via poiché l'apprendimento è l'intero punto dell'esercizio, ma ecco un suggerimento. Probabilmente vorrai una combinazione di find_last_of e replace.

-1

Quello che devi fare è copiare il nome file originale in una nuova variabile in cui puoi modificare l'estensione.Qualcosa di simile a questo:

string outFilename; 
size_t extPos = filename.rfind('.'); 
if (extPos != string::npos) 
{ 
    // Copy everything up to (but not including) the '.' 
    outFilename.assign(filename, 0, extPos); 
    // Add the new extension. 
    outFilename.append(".code"); 
    // outFilename now has the filename with the .code extension. 
} 

E 'possibile si potrebbe usare il "nomefile" variabile se non è necessario per mantenere il nome del file originale intorno per un uso successivo. In questo caso si potrebbe utilizzare:

size_t extPos = filename.rfind('.'); 
if (extPos != string::npos) 
{ 
    // Erase the current extension. 
    filename.erase(extPos); 
    // Add the new extension. 
    filename.append(".code"); 
} 

La chiave è quello di esaminare la definizione della classe string C++ e capire ciò che ogni funzione membro fa. Usando rfind cercheremo al contrario attraverso la stringa e non perderesti accidentalmente le estensioni nei nomi delle cartelle che potrebbero far parte del nome file originale (ad esempio "C: \ MyStuff.School \ MyFile.txt"). Quando lavori con gli offset da find, rfind, ecc., Dovrai anche fare attenzione a usarli correttamente quando li passi come conteggi ad altri metodi (ad esempio usi assign (nomefile, 0, extPos-1), assegna (nomefile, 0, extPos), assegna (nome file, 0, extPos + 1)).

Spero che questo aiuti.

+3

Dato che si tratta di una domanda sui compiti, per favore non dare via tutto –

8

Ovviamente, se non si trattasse di compiti a casa ma di un progetto del mondo reale, probabilmente faresti tu stesso - così come altre persone che leggono il tuo codice - un favore usando Boost.Filesystem di replace_extension() invece di rotolare il tuo . Non c'è semplicemente alcuna funzionalità che sia abbastanza semplice da non riuscire a trovare un bug, almeno in alcuni casi.

0

perché non utilizzare il metodo stringa find_last_of()?

std::string new_filename = filename; 
size_type result = new_filename.find_last_of('.'); 

// Does new_filename.erase(std::string::npos) working here in place of this following test? 
if (std::string::npos != result) 
    new_filename.erase(result); 

// append extension: 
filename.append(".code"); 
0

In Windows (almeno) è possibile utilizzare _splitpath di sezionare il nome di base dal resto dei pezzi, e poi riassemblare utilizzando la tua formattatore stringa preferito.

0

Come sull'utilizzo strstr:

char* lastSlash; 
char* newExtension = ".code"; 
ChangeFileExtension(char* filename) { 
    lastSlash = strstr(filename, "."); 
    strcpy(lastSlash, newExtension); 
} 
0

vorrei solo aggiungere ".code" al nome del file l'utente ha inserito. Se immessi "test.txt", il file di output sarebbe "test.txt.code". Se hanno inserito un nome di file senza estensione, come "test", il file di output sarebbe "test.code".

Utilizzo questa tecnica sempre con programmi che generano file di output e una sorta di output di registrazione/diagnostica correlato. È semplice da implementare e, a mio parere, rende le relazioni tra file molto più esplicite.

5

tanto in tanto pongo questa domanda e finiscono in questa pagina, in modo da per riferimento futuro, qui è la sintassi a riga singola:

string newfilename=filename.substr(0,filename.find_last_of('.'))+".code"; 
+0

Non funziona con qualcosa come "file.tar.gz" –

+0

Funziona se la definizione di "estensione" è "qualunque cosa sia dopo l'ultimo punto", che è ragionevole se stiamo cercando una semplice regola empirica. Per casi speciali come archivi gzip, nomi di file con numeri di versione, Makefile, ecc., Basta definire una politica speciale e implementarla in un metodo dedicato. – Narcolessico

0
size_t pos = filename.rfind('.'); 
if(pos != string::npos) 
    filename.replace(pos, filename.length() - pos, ".code"); 
else 
    filename.append(".code"); 
+0

Si prega di aggiornare la risposta con una spiegazione. –

+0

Sebbene questo codice possa rispondere alla domanda, fornendo il contesto aggiuntivo per _why_ e/o _how_ risponde allo la domanda migliorerebbe significativamente il suo valore a lungo termine . Per favore [modifica] la tua risposta per aggiungere qualche spiegazione. –

+0

std :: string :: replace può prendere string :: npos come len (piuttosto che calcolare lunghezza - pos), che sostituirà fino alla fine della stringa. – user79878