PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit Namensräumen in C++



Lukas
23.11.2004, 18:19
Ich möchte in einem Programm mit Textdateien arbeiten, allerdings soll der Name der Textdatei vom Benutzer als Argument an das Programm übergeben werden.
Codeschnipsel:

#include <fstream.h>

main(int argc, char* argv[]){
if(argc == 2){
ifstream in(argv[1]);
}

Mit der if-Abfrage will ich abfangen, dass versucht wird, eine Datei zu öffnen, die nicht als Argument übergeben worden ist.
Das Problem: Wenn ich später auf die Variable in (also die Datei) zugreifen will, meckert der Compiler, dass die Variable nicht deklariert worden ist (außerdem wirft er eine Warnung, dass "in" nie benutzt wird).
Die Frage: Wie kann ich das ganze so hinbekommen, dass ich später im Programm auf "in" zugreifen kann?

Ich denke, dass ein paar von euch das wissen. Danke schonmal im Vorraus.

cornuto
23.11.2004, 19:35
#include <iostream>
...
using namespace std;

main(int argc, char* argv[])
{
if(argc!=2) {return 0;}
else
{
fsream file;
file.open(argv[2], ios::out); //out zum lesen, in zun schreiben
if(file.is_open())
{
//was immer du machen willst
file.close();
}
}
return 0;
}



habe den code nicht getestet, sollte allerdings funzen.

Dingsi
23.11.2004, 19:45
Ich erlaub mir mal ein paar fehler zu berichtigen.
fstream war nicht drin. argv[1] muss benutzt werden, nicht 2. und es war ein tippfehler bei fsream ohne t. ^^. ist aber immernoch ungetestet.
außerdem kann man das else{} weglassen, da ja eh return-t wird, sollte argc nicht 2 sein. return = abbruch.



#include <iostream>
#include <fstream>
...
using namespace std;

main(int argc, char* argv[])
{
if(argc!=2) {return 0;}

fstream file;
file.open(argv[1], ios::out); //out zum lesen, in zun schreiben
if(file.is_open())
{
//was immer du machen willst
file.close();
}
return 0;
}

cornuto
23.11.2004, 19:55
fstream muss nicht included werden, ist in iostream beinhaltet

das mit argv[2] war schändlich falsch von mir.

Lukas
23.11.2004, 21:00
Okay, jetzt geht's. Danke.

Edit:
Neues Problem, aber ich will nicht zu viele Threads öffnen.
Wie kann ich eine ganze Zeile von cin auslesen, auch wenn Leerzeichen drin sind? Also dass meinetwegen die Eingabe
hallo 123 test als eine Eingabe gewertet wird und das folgender (als Beispiel ausgedachter) Codeschnipsel die Ausgabe
hallo 123 testund nicht
hallo
123
testerzeugt?

string str;
while(1){
cin >> str;
cout << str;
}

Firzen
23.11.2004, 21:20
afaik geht das mit cin.getline(char*,streamsize,char);
Erster Parameter ist dein String, 2. die Größe, und 3. Parameter ist das Zeichen wo er aufhören soll zu lesen. Es ist afaik '\n' beim 3. Parameter als Default-Wert eingestellt.

Lukas
23.11.2004, 21:58
Okay, das geht. thx

Jesus_666
24.11.2004, 01:07
if(argc!=2) {return 0;}
Das würde ich so auf keinen Fall machen, das ist schlechter Stil. Rückgabewerte wurden nicht dafür eingebaut, daß sie immer gleich sind!

if(argc!=2) {return 1;}So ist es besser; wenn man das Programm beendet, bevor es seine Arbeit getan hat, dann sollte man auch einen Rückgabewert != 0 zurückgeben.

cornuto
24.11.2004, 13:55
die rüchgabewerte werden hauptsächlich verwendet wenn in der shell gescriptet wird, weil keine eigentliche debug möglichkeit besteht. ist in einer ide wohl kaum der fall

Lukas
24.11.2004, 18:36
Nächste Frage:
Ich habe eine Variable vom Typ string. Mit
atoi(str.c_str());(str ist mein String) kann ich ihn in eine int umwandeln. Das Problem ist, dass atoi() 0 zurückgibt, wenn der string nicht konvertierbar ist (sprich keine Zahl enthält). Allerdings möchte ich für mein Programm davon unterscheiden, ob die Zahl im String 0 ist oder ob der String keine Zahl ist. Also in etwa (Pseudo-Code):
if string_contains_int{
return int_im_string
} else{
return irgendwas_bestimmtes_ungleich_null/false
}

Jesus_666
24.11.2004, 18:49
die rüchgabewerte werden hauptsächlich verwendet wenn in der shell gescriptet wird, weil keine eigentliche debug möglichkeit besteht. ist in einer ide wohl kaum der fall
Das ist so eine Sache wie XHTML statt HTML - es geht auch problemlos ohne, aber die momentan als am korrektesten angesehene Variante ist eben mit. Zumal sich aus fallspezifischen Rückgabewerten keinerlei Nachteile ergeben, das Programm sich aber eher so verhält, wie man es als User erwarten würde - was eine Gute Sache ist.

In der Unix-Welt sind Dinge wie mein_programm && etwas_anderes* weit verbreitet und ungemein nützlich; damit so etwas funktioniert müssen die Programme aber auch sagen können, ob sie korrekt beendet wurden.
Argumente wie "ich benutze Windows und da macht man sowas nicht" sehe ich nicht als Begründung dafür an, sich einen schlechten Stil anzugewöhnen - wenn man später mal an einem Programm schreibt kann es gut angehen, daß es auf einer Plattform mit einer starken Shell läuft und saubere Rückgabewerte erwartet werden. Dann ist es gut, wenn man schon von Haus aus darauf achtet, fehlerspezifisch mit != 0 zu terminieren.


* Sprich: mein_programm wird ausgeführt; wenn die Ausführung erfolgreich war wird etwas_anderes ausgeführt.

cornuto
24.11.2004, 18:57
C++ ist keine Skript-sprache. das waren wohl eher c zeiten

vivalaleche
24.11.2004, 19:06
der int return typ ist sowieso ein übrigbleibsel aus der c sprache, heute ist ebenso der void return typ für die main gebräuchlich

Lukas
24.11.2004, 19:08
Ich glaube, laut ANSI-Standard muss das 'ne int sein. Ich kann mich aber auch irren *zumfastallwissendenJeezschiel*

Dingsi
24.11.2004, 20:21
C++ ist keine Skript-sprache. das waren wohl eher c zeitenC ist genauso wenig eine Skriptsprache.
der int return typ ist sowieso ein übrigbleibsel aus der c sprache, heute ist ebenso der void return typ für die main gebräuchlichNein. int ist und bleibt Standard. Alles andere ist MS-C-Mist.

Lukas
24.11.2004, 21:18
Nächste Frage:
Ich habe eine Variable vom Typ string. Mit
atoi(str.c_str());(str ist mein String) kann ich ihn in eine int umwandeln. Das Problem ist, dass atoi() 0 zurückgibt, wenn der string nicht konvertierbar ist (sprich keine Zahl enthält). Allerdings möchte ich für mein Programm davon unterscheiden, ob die Zahl im String 0 ist oder ob der String keine Zahl ist. Also in etwa (Pseudo-Code):
if string_contains_int{
return int_im_string
} else{
return irgendwas_bestimmtes_ungleich_null/false
}

So, die Diskussion um den return wäre damit beendet. Ist mein Zitat Hinweis genug, was ich gerne wissen würde?

Jesus_666
24.11.2004, 21:48
Nein. int ist und bleibt Standard. Alles andere ist MS-C-Mist.
Exakt. Man sollte unter keinen Umständen Microsotfs Methoden mit dem Standard verwechseln.


Zum Thema "Skriptsprache": Das mit den Rückgabewerten hat durchaus seinen Sinn. Nehmen wir mal folgendes Grundproblem: Ich habe einen Haufen Rechner, in denen eine Festplatte durch ein neueres Modell ausgetauscht und die Daten gelöscht werden sollen, nachdem sie archiviert wurden.
Kein Problem; ich erstelle mir ein Skript, das zuerst den Inhalt der alten Festplatte in ein Archiv auf der neuen Platte schreibt. Anschließend wird der Inhalt der alten Festplatte gelöscht.
Der Haken: Das Skript muß wissen, ob das Archiv auch korrekt erstellt wurde. Wenn es einen Fehler nicht erkennt und einfach beim nächsten Schritt weitermacht kann ruck zuck der Inhalt einer Festplatte verschwinden.
Mit Rückgabewerten ist das kein Problem: Ich überprüfe einfach den Rückgabewert jedes aufgerufenen Programms und breche ab, wenn er ungleich 0 ist. Wenn ich eine mächtige Shell wie bash benutze geht das sogar in einer Zeile:
tar -cjf /mnt/platte2/archiv.tar /mnt/platte1/* && rm -rf /mnt/platte1/*
Wenn tar einen Fehler hat wird rm gar nicht erst ausgeführt, was für die Daten sehr gesund ist.

Ohne Rückgabewerte müßte ich nach dem Erstellen jedes Archiv einmal durchgehen und nachsehen, ob auch alle Dateien drin sind, die reinsollen. Unter Umständen ließe sich der Vorgang mit Standardmitteln nicht automatisieren, was für einen relativ einfachen computergestützten Algorithmus absolut lächerlich ist.


Die C-artige Skriptsprache wäre übrigens Ch.


@masterquest: Da dummerweise nicht mal atof in der Lage ist, für einen nichtnumerischen String NaN zurückzugeben, mußt du wohl irgendeinen Workaround finden... Zum Beispiel kannst du den String Zeichen für Zeichen durch isdigit() jagen. isdigit() findest du in ctype.h.

Ineluki
24.11.2004, 23:22
beruecksichtigt isdigit(char) eigentlich auch "." und "E" und "e" und "-" ?

und selbst wenn, wuerde er nicht erkennen, dass "..." oder "1eee" keine Zahl ist.

selbst wenn man die exponentendarstellung (1000 = 1E3) ausschliesst, hat man immer noch das problem des Typeoverflow .... der string kann ja schliesslich nahezu unendlich lang sein, der 32-bit Int ist ja schliesslich begrenzt ....

Jesus_666
25.11.2004, 15:30
beruecksichtigt isdigit(char) eigentlich auch "." und "E" und "e" und "-" ?

und selbst wenn, wuerde er nicht erkennen, dass "..." oder "1eee" keine Zahl ist.

selbst wenn man die exponentendarstellung (1000 = 1E3) ausschliesst, hat man immer noch das problem des Typeoverflow .... der string kann ja schliesslich nahezu unendlich lang sein, der 32-bit Int ist ja schliesslich begrenzt ....
In dem Fall würde ich sagen, daß man um die Konstruktion eines eigenen Parsers nicht herumkommt. Da C++ es nicht erlaubt, daß eine Integerfunktion etwas anderes als Ganzzahlen zurückgibt, kann man mit einer Funktion nicht arbeiten - vielleicht mit einer Prozedur.
Sprich: Du übergibst drei Referenzen (auf den zu überprüfenden String, auf einen Integer und auf einen Boolean); die Prozedur liest dann den String aus und schreibt die erkannte Zahl in den Integer; falls der String keine Zahl enhtält wird der Boolean auf TRUE gesetzt und der Integer leergelassen. Das dürfte die einfachste Methode sein, in C++ einen String in einen Integer umzuwandeln und dabei Nichtzahlen als solche zu kennzechnen.
Ist C++ nicht was Schönes?

Ineluki
25.11.2004, 18:05
besser als ein true/false zurueck zu geben waere es, das ganze so zu handhaben, wie in der pascal-funktion val ...

int val(char* s, int &value, int &errpos)=errpos;
wobei in errpos die position des ersten fehlerhaften zeichens zurueck gegeben wird.

willst du pascal konform sein, so waere errpos==0 kein fehler und erpos==1 wuerde bedeuten, dass das erste zeichen, also s[0] den fehler enthielte

in c waere es aber wegen der 0-indexierung auch moeglich, -1 fuer fehlerfrei anzugeben, und ansonsten den index ,...

wobei man bei der pascalnorm auch einfache ifs der form if(val("d23",zahl,err)) errorhandling; machen koennte

Jesus_666
25.11.2004, 18:33
Das wäre in der Tat eine Möglichkeit; ich bevorzuge aber immer noch den Weg, in dem derartige Sachen bei PHP gerne geregelt werden: Wenn die Funktion erkennt, daß man ihr keine Zahl liefert, gibt sie FALSE oder NULL zurück.

Hmm, können Int-Funktionen bei C++ auch NULL zurückgeben? Bei PHP würde damit die Variable freigegeben werden, sobald man sie mit der Funktion füllt; dann kann man ganz einfach mit if ($variable) arbeiten...

Ineluki
25.11.2004, 21:44
in C(++) ist afaik int(NULL)==0

Dingsi
25.11.2004, 21:59
Ist in PHP false/null nicht auch 0? O_o.

Jesus_666
25.11.2004, 22:46
Ist in PHP false/null nicht auch 0? O_o.
False ist == 0 (aber nicht ===). NULL bedeutet, daß die Variable freigegeben wird. Eine Variable mit dem Wert NULL ist das gleiche wie eine Variable, die nicht existiert.

Ineluki
26.11.2004, 05:33
in php mag das ja stimmen, aber in c(++) ist dem nicht so ...

Dingsi
26.11.2004, 13:40
False ist == 0 (aber nicht ===). NULL bedeutet, daß die Variable freigegeben wird. Eine Variable mit dem Wert NULL ist das gleiche wie eine Variable, die nicht existiert.also unset($var) entspricht dann $var=NULL. mmh. und die var ist dann auch !isset($var)

Jesus_666
26.11.2004, 16:30
in php mag das ja stimmen, aber in c(++) ist dem nicht so ...
Dingsi hat ja auch nach dem Verhalten in PHP gefragt... Das C++ das mal wieder nicht kann weiß ich auch. Naja, IMO ist PHP sowieso die syntaktisch beste Sprache.