2009-04-16 11 views
8

Okay, hier ist der Deal, ich nehme ein Intro in C++ - Klasse an meiner Universität und habe Probleme herauszufinden, wie man die Erweiterung einer Datei ändert. Zuerst sollten wir in einer .txt-Datei lesen und Wörter, Sätze, Vokale usw. zählen. Nun, ich habe das verstanden, aber der nächste Schritt ist, was mich beunruhigt. Wir sollen dann eine neue Datei erstellen, die den gleichen Dateinamen wie die Eingabedatei aber mit der Endung .code anstelle von .txt verwendet (in dieser neuen Datei sollen wir dann die Zeichenkette durch Hinzufügen von Zufallszahlen zu deren ASCII-Code codieren) Zeichen, wenn Sie interessiert waren). Als Anfänger in der Programmierung bin ich mir nicht ganz sicher, wie ich das machen soll. Ich verwende den folgenden Code, um zunächst die Eingabedatei zu erhalten:Wie ändern Sie die in einer Zeichenfolge in C++ gespeicherte Dateinamenerweiterung?

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

Ich gehe davon aus, eine neue Datei zu erstellen, ich werde so etwas wie werden:

outfile.open("test.code"); 

Aber ich werde nicht wissen, was der Dateiname ist, bis der Benutzer es eingibt, also kann ich "test.txt" nicht sagen. Wenn jemand weiß, wie man diese Erweiterung ändert, wenn ich eine neue Datei erstelle, würde ich das sehr schätzen!

Antwort

8

Es gibt mehrere Ansätze dazu.

Sie können den super faulen Ansatz verwenden und nur den Dateinamen eingeben, nicht die Erweiterung .txt. In diesem Fall können Sie .txt anhängen, um die Eingabedatei zu öffnen.

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

Dann rufen Sie einfach

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

Der nächste Ansatz den gesamten Dateinamen einschließlich Erweiterung zu nehmen wäre, und nur .code ihm anhängen, so dass Sie test.txt.code haben würde.

Es ist ein wenig mehrdeutig, ob dies akzeptabel ist oder nicht.

Schließlich können Sie std::string Methoden find und replace verwenden, um den Dateinamen ohne Erweiterung zu erhalten, und verwenden Sie das.

+0

Okay, ich denke, dass die Optionen eher dem entsprechen, wonach ich gesucht habe, wie wir gerade über String-Methoden gelernt haben. Danke für die Eingabe! –

+2

Bessere rfind(), da es das letzte "." anstelle der ersten in dem Fall, dass 'a.b.c.txt' ist ein gültiger Dateiname –

+1

.open() nimmt eine const char *, nicht ein std :: sting leider. – MSalters

3

Hier sind ein paar Hinweise. Sie haben ein Dateiname bereits eingetragen - was Sie tun möchten, ist das Teil des Dateinamens erhalten, die nicht die Erweiterung enthält:

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

diese Funktion geschrieben haben, können Sie es verwenden, den Namen des neuen erstellen Datei:

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

Sie zu testen nicht vergessen. Ich mag es, meine files.like.this zu benennen. – veefu

0

Pseudo-Code wäre, etwas zu tun wie

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

Für outfilename ändern, sehen Sie strrchr und strcpy als Ausgangspunkt (könnte besser geeignet sein Methoden - das würde mit einem char * aber gut funktionieren)

+0

Warum vorschlagen C Stil Methoden, wenn der Code C++ ist? –

4

Nicht zu verraten, da Lernen der ganze Sinn der Übung ist, aber hier ist ein Hinweis. Sie werden wahrscheinlich eine Kombination von find_last_of und replace wollen.

-1

Was Sie tun müssen, ist den ursprünglichen Dateinamen in eine neue Variable kopieren, wo Sie die Erweiterung ändern können.Etwas wie folgt aus:

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. 
} 

Es ist möglich, Sie könnten die „Dateiname“ Variable verwenden, wenn Sie den ursprünglichen Dateinamen nicht um für den späteren Gebrauch halten müssen. In diesem Fall könnten Sie nur verwenden:

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

Der Schlüssel bei der Definition der C++ String-Klasse zu sehen und zu verstehen ist, was jedes Mitglied Funktion tut. Wenn Sie rfind verwenden, wird rückwärts durch die Zeichenfolge gesucht, und Sie werden nicht versehentlich auf Erweiterungen in Ordnernamen stoßen, die Teil des ursprünglichen Dateinamens sein könnten (z. B. "C: \ MyStuff.School \ MyFile.txt"). Wenn Sie mit den Offsets von find, rfind usw. arbeiten, sollten Sie auch darauf achten, sie richtig zu verwenden, wenn Sie sie an andere Methoden übergeben (zB verwenden Sie assign (Dateiname, 0, extPos-1), zuweisen (Dateiname, 0, extPos), zuweisen (Dateiname, 0, extPos + 1)).

Hoffe, dass hilft.

+3

Da es sich um eine Hausaufgabe handelt, bitte verrate nicht alles –

8

Natürlich, wenn dies keine Hausaufgaben sondern ein reales Projekt wären, würden Sie wahrscheinlich selbst - sowie andere Leute, die Ihren Code lesen - einen Gefallen tun, indem Sie Boost.Filesystem 's replace_extension() statt Ihre eigenen rollen . Es gibt einfach keine Funktionalität, die einfach genug ist, dass Sie zumindest in einem bestimmten Fall keinen Fehler finden könnten.

0

warum nicht mit der string-methode 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 (mindestens) Sie _splitpath sezieren den Basisnamen aus dem Rest der Stücke verwenden können, und sie dann wieder zusammenbauen Ihre Lieblings String Formatierer verwenden.

0

Wie wäre es strstr mit:

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

Ich würde nur anhängen ".code" an den Dateinamen der Benutzer eingegeben. Wenn sie "test.txt" eingeben, lautet die Ausgabedatei "test.txt.code". Wenn sie einen Dateinamen ohne Erweiterung eingeben, wie "Test", dann wäre die Ausgabedatei "test.code".

Ich benutze diese Technik die ganze Zeit mit Programmen, die Ausgabedateien und eine Art von verwandten Protokollierung/Diagnose-Ausgabe generieren. Es ist einfach zu implementieren und macht meiner Meinung nach die Beziehungen zwischen Dateien viel expliziter.

5

ich mich hin und wieder diese Frage stellen und auf dieser Seite am Ende, so dass für die Zukunft, hier ist die einzeilige Syntax:

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

Funktioniert nicht mit etwas wie "file.tar.gz" –

+0

Es funktioniert, wenn die Definition von "Erweiterung" ist "was auch immer hinter dem letzten Punkt ist", was ist vernünftig, wenn wir nach einer einfachen Faustregel suchen. Für spezielle Fälle wie gezippte Archive, Dateinamen mit Versionsnummern, Makefiles usw. sollte man nur eine spezielle Richtlinie definieren und diese in eine dedizierte Methode implementieren. – Narcolessico

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

Bitte aktualisieren Sie Ihre Antwort mit einer Erklärung. –

+0

Obwohl dieser Code die Frage beantworten kann, zusätzliche Kontext in Bezug auf _why_ und/oder _how_ es Antworten die Frage würde erheblich verbessern seine langfristige Wert. Bitte [bearbeiten] Sie Ihre Antwort, um eine Erklärung hinzuzufügen. –

+0

std :: string :: replace kann string :: npos als len (anstelle von length - pos) nehmen, was bis zum Ende der Zeichenfolge ersetzt. – user79878

Verwandte Themen