| 

.NET C# Java Javascript Exception

2
hallo,

ich habe information zu einzelpersonen und gruppen in einer textdatei gespeichert:

Andre <- name der person oder gruppe
96 <- gewicht der person/gruppe
0 <- gruppenkode gibt an ob es sich hierbei um eine person (0) oder eine gruppe (>0) handelt
<- leere zeile -->
Fc Bayern
6532
23

Müller
134
2


ich möchte nun die daten aller personen/gruppen in eine ausgabedatei schreiben ohne das das gesamtgewicht von 10.000 kg überschritten wird.

meiner idee war es nun die eingelesenen werte variablen zuzuweisen (string name, int gewicht, int gruppenkode) und diese dann für die jeweiligen personen/gruppen in einer liste zu speichern.

mein bisheriger code:
void loadData(){
ifstream readFile( "anfragen.txt" );
if( !readFile.is_open() )
{
cout << "Cannot open file" << endl;
}
else
{
cout << "Open file" << endl;
}

char row[30]; // max length of a value
while(readFile.getline (row, 50))
{
cout << row << endl;
// wie weise ich die werte den variablen zu und speicher diese in einer liste?
}
readFile.close();
}


da ich noch c++ anfänger bin könnte es viellt noch deutlich bessere ansätze geben dieses problem zu lösen. ich bin offen für jegliche vorschläge und anregungen!

ich programmiere in visual studio 2010!
27.08.2011
burner007 790 1 9
Geht es dir nur um die Implementierung oder auch die Lösung des zugrundeliegenden Problems?
ksmx 04.10.2011
3 Antworten
1
Servus,

ich würde - da wir hier in C++ sind - das Ganze auch "objektorientiert" angehen. Sprich das TXT file parsen und entsprechend der einzelnen Datensätze auch Datensatzobjekte anlegen. Ich gehe in meinem Ansatz unten sogar so weit, dass die Datensatzklasse in dessen Konstruktor selbst seinen nächsten Eintrag aus einem istream parsen kann. Die Datencontainer füttern sich quasi selbst mit den Daten aus dem TXT file.

Dann kann man sogar von allen Klassen, die istream implementieren Datensätze einlesen.

Ich benutze zur Speicherung dann eine Liste der STL (Standard Template Library) (std::list) und für die Strings ein stl-String (std::string) - Objekt. Das Vereinfacht die Sache enorm ;-)

Die - eben wie der Namensanfang schon zeigt standarisierte - STL ist heute auch ein fester Bestandteil der Toolchains der diversen Compilerhersteller. Den Code von mir, unten
habe ich unter OS X geschrieben, compiliert aber auch unter Windows (VisualStudio, MingGW, Cygwin), Linux, QNX ...

Vielleicht schaust Du Dir mal das angefügte Codebeispiel an. Ist für einen Einsteger "hard stuff", aber wenn Du Fragen hast - dann frag einfach ;-)

#include <iostream>
#include <fstream>
#include <list>

/** DataSet is a class which is supposed to encapsulate a Weight data set entry.
* In particular a DataSet collects the data as follow:
*
* - The name of the person (the owner) as a string this dataset belongs to.
* - The owners weight in kilogramm.
* - The owner group code as a number. if the owner does not belong to a group then
* this value is 0.
*/
class CDataSet
{
std::string m_Name; //!< The persons name.
unsigned short m_Weight; //!< The weight in kilogramm
unsigned int m_GroupCode; //!< Groupcode (>0) if group , 0 if person

public:
/** Create a new DataSet by reading and parsing the next lines from a given input stream.
* \param inStream The stream to read from.
*/
CDataSet(std::istream& inStream)
: m_Name()
, m_Weight(-1)
, m_GroupCode(0)
{
char buff[512];

// Read the next line from the dataset file: This is the name as a string.
inStream.getline(buff, sizeof(buff));
m_Name = buff;

// Read the next line from the dataset file: This is the weight in kg as a natural number.
inStream.getline(buff, sizeof(buff));
m_Weight = atoi(buff);

// Read the next line from the dataset file: This is the "group code" as a natural number.
inStream.getline(buff, sizeof(buff));
m_GroupCode = atoi(buff);

// Read an "empty line" which is defined to separate the certain data sets.
inStream.getline(buff, sizeof(buff));
}

~CDataSet()
{}

// The accessors.
/** Get the name of the person (the owner) of this data set as a string.
* \return the persons name.
* \see isPerson() const
*/
const std::string& name() const {return m_Name;}

/** Check if this person belongs to a group or is a \i sole person.
* This actually means that groupCode() is zero.
* \return True if the owner is a person and does \b not belong to a group.
* \see groupCode() const
*/
bool isPerson() const {return 0 == m_GroupCode;}

/** Get the owners weight in kilogramm.
* \return The weight in kg.
*/
unsigned short weight() const {return m_Weight;}

/** Get the owners group code. This is zero if the owner does not belong
* to a group 'cos it is a sole person.
* \return The group code.
* \see isPerson() const
*/
int groupCode() const {return m_GroupCode;}
}; // class CDataSet

/* Define a new Datatype "DataSetList" which is a list of DataSets.
*
* We'll use this to store all DataSets which are list in the txt file.
*/
typedef std::list<CDataSet> DataSetList;


/** Read in all data Sets from a given File and store them into a DataSetList.
* The given txt file will be parsed and its data sets will be stored into the DataSetList.
* The DataSetList will be erased on the function entry.
*
* \param inFilename The name to read the dataset from.
* \param outDataSet The data Set used to store the contents of the file..
* \return true on success, false on failure (e.g. the txt file could not be opened for reading).
*/
static bool loadData(const char *inFilename, DataSetList& outDataSet)
{
outDataSet.clear(); // remove all old entries

std::ifstream readFile( inFilename );

if( !readFile.is_open() )
{
std::cout << "Cannot open file '!" << inFilename << "'" << std::endl;
return false; // indicate error
}

for(; !readFile.eof();) // Read until "End Of file" condition is reached...
{
CDataSet dataSet(readFile);
outDataSet.push_back(dataSet);
}

readFile.close();

return true; // indicate success
}


// The main entry.
int main (int argc, const char * argv[])
{
DataSetList dataSets; // This list will be used to store all data sets.

const char *dataSetFilename("anfragen.txt");
// const char *dataSetFilename("/Users/hdusel/Desktop/CodeReader/anfragen.txt");

// Read and parse the data set file name and store their data sets into 'dataSets'.
bool rc = loadData(dataSetFilename, dataSets);
if ( false == rc )
{
std::cerr << "*** ERROR: Could not read data set '" << dataSetFilename << "'!" << std::endl;
return EXIT_FAILURE;
}
else
{
// Dump out the contents of dataSets.
std::cout << "outDataSet carries " << dataSets.size() << " entries:" << std::endl;

// Now, iterate through the list and dump all entries
DataSetList::const_iterator it;

int idx = 0;
for (it = dataSets.begin(); it != dataSets.end(); ++it, ++idx)
{
std::cout << " entry #" << idx << ": ";

const CDataSet& entry(*it);

std::cout << "name=" << entry.name().c_str() << \
", weight=" << entry.weight() << \
", group code=" << entry.groupCode() << std::endl;
}
}
return EXIT_SUCCESS;
}
28.08.2011
hdusel 186 4
1
das hier ist mein aktueller code

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <limits>

struct entry
{
entry()
: weight()
{ }

// passengers data
std::string name;
int weight; // kg
std::string group_code; // <- is a number!
};

int main()
{
std::ifstream stream_in("data.txt");
if (stream_in)
{
std::cerr << "open file" << std::endl;
std::vector<entry> v;

const int limit_total_weight = 10000; // kg
int total_weight = 0; // kg

entry current;
while (std::getline(stream_in, current.name) &&
stream_in >> current.weight &&
std::getline(stream_in, current.group_code) &&
stream_in.ignore(std::numeric_limits<std::streamsize>::max(), '\n') // skip the rest of the line containing the weight
)
{
if ((total_weight + current.weight) < limit_total_weight)
{
v.push_back(current);
total_weight += current.weight;
}
else
{
std::cerr << "rest kg: " << limit_total_weight - total_weight << std::endl; // show difference
break;
}
if (total_weight >= limit_total_weight)
{
break;
}

// ignore empty line
stream_in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
else
{
std::cerr << "could not open the file" << std::endl;
}
// display vector data
std::vector<entry>::iterator pos;
for (pos = v.begin(); pos != v.end(); ++pos) // error: v ist unbekannt
std::cerr << *pos << std::endl;
cout << std::endl;
}


ich möchte den inhalt vom vector in eine externe textdatei schreiben! für den anfang aber kann ich nichtmal den inhalt des vectors ausgeben lassen!

wo ist der fehler im code?
28.08.2011
burner007 790 1 9
1
Zum Fehler "error: v ist unbekannt": Du kannst auf den Vector 'v' nicht zugreifen, weil, der innerhalb des Scopes von "if (stream_in) {...}" deklariert wurde, Du aber beim lesenden Zugriff *ausserhalb* dieses Scopes bist!

Zur Erinnerung: Eine Variable ist nur innerhalb des Scopes und seiner *sub*-scopes sichtbar! Ausserhalb sind sie es *nicht*! Deklariere sie vor "if (stream_in) {...}" und gut ist es. Übrigens: Willst Du wirklich weitermachen, wenn das File nicht lesend geöffnet werden kann?

Zum Thema Ausgabe des Vectors poste ich gleich ein Snippet... ;)
hdusel 28.08.2011
0
Servus, anbei meine Anmerkungen:

  • Wie oben angemerkt musst Du die Varaiblendeklaration des Vectors aus dem if (stream_in) {...} rausziehen. Dann hast Du ab '// display vector data' auch Zugriff darauf!

  • Zum Zugriff auf den Iterator: Der Iterator zeigt jeweils auf elemente seines Templatetyps - in Deinem Fall eben auf entry. Daher ist es viel einfacher (und auch übersichlicher), wenn Du mit einer Zwischenvariablen arbeitest. Und auch hier gilt: Referenzen verwenden wenn möglich! Dann kostet die Zwischenvariable auch nichts ;)

    Danach greifst Du einfach auf die strukturmembers von entry zu.


... Wie man das File dann schreibt, kriegst Du hin?

Hier das korrigierte und von mir an den geänderten Stellen kommentierte snippet:

Happy codin'! - Peter -

...
// display vector data
std::vector<entry>::const_iterator pos; // Nimm hier bitte einen const_iterator.
// Das ist für Deinen Fall typsicherer! ;)
for (pos = v.begin(); pos != v.end(); ++pos)
{
// hdusel: Arbeite mit zwischenvariablen...
const entry& thisEntry(*pos); // ...und lass sie auf eine Referenz vom Typ
// entry zeigen (performance, da "no copy"!) ;)

// ...dann greife einfach auf die Elemente "old school" mäßig zu! ;)
std::cerr << "name:" << thisEntry.name << std::endl;
std::cerr << "weight:" << thisEntry.weight << std::endl;
std::cerr << "group_code:" << thisEntry.group_code << std::endl;
}
std::cout << std::endl;
28.08.2011
hdusel 186 4

Stelle deine Cplusplus-Frage jetzt!