Forum: C++, Tenta uppgift? ( I/O )

Forum huvudsida -> Programmering -> C++, Tenta uppgift? ( I/O )

Sidor: 1

Till botten

olle 19:39 - 25:e Augusti 2006 | Post #1
Medlem
Inlägg: 57


Skicka PM
Har försökt göra denna övning, men vet inte riktigt hur jag ska gå tillväga. Försöker göra konstruktorn och tänkte använda getline för att läsa in en rad i vector<string> så att jag vet att varje element representeras av en rad. Men getline har 2 parametrar och jag vet hur man ska göra?

Detta är övningen:

En "wrapper" är som bekant en klass som ger ett för ändamålet anpassat gränssnitt till
datastrukturer och annat. Tekniken kan tex. användas för att ge ett gränssnitt till en textfil
för att få effektiv och enkel direktaccess till varje rad. Nackdelen är att hela filen buffras
i primärminnet, men det kan ibland vara nödvändigt, tex. vid sortering. Iden är att låta
klassens konstruktorn läsa in filen till en vektor vilken senare kan indexeras via operationerna
getLine och putLine ( OBS, dessa opererar på wrapper-objektet, inte på filen). Destruktorn
skriver tillbaka vektorn till filen. Klassen skall alltså ha medlemsfunktionerna:

// -ppna och läs in en fil
FileWrapper( const char *fileName );

// Stäng filen
~FileWrapper();

// Retunera antalet rader
long lineCount() const;

// Retunera den i:et raden
string getLine( int i ) const throw ( range_error);

// Byt ut den i:te raden mot s
void putLine( const string &s, int i ) throw ( range_error);

Inför lämpliga dataattribut och definera medlesfunktionerna. Du får bortse från problemen
som uppkommer om flera FileWrapper-objekt hanterar samma fil.


Koden

  1.  
  2. #include<iostream>
  3. #include<fstream>
  4. #include<vector>
  5. #include<string>
  6.  
  7. using namespace std;
  8.  
  9. class FileWrapper{
  10. public:
  11. FileWrapper( const char *fileName );
  12. ~FileWrapper();
  13. long lineCount() const;
  14. string getLine( int i ) const;// throw (range_error);
  15. void putLine( const string &s, int i );// throw (range_error);
  16. private:
  17. vector<string> v;
  18. };
  19.  
  20. FileWrapper::FileWrapper( const char *fileName ) {
  21. ifstream in;
  22. in.open(fileName);
  23. if (!in){
  24. cerr << "Unable to open" << endl;
  25. exit(1);
  26. }
  27. char *c;
  28. while ( in.getline(c) ) // getline(2 parametrar) ??
  29. v.push_back(s);
  30.  
  31. }
  32.  
  33.  
  34. FileWrapper::~FileWrapper(){}
  35.  
  36. long FileWrapper::lineCount()const {}
  37.  
  38.  
  39. string FileWrapper::getLine( int i )const /* const throw (range_error)*/ {}
  40.  
  41. void FileWrapper::putLine( const string &s, int i )/* throw (range_error) */{}
  42.  
  43. int main() {
  44.  
  45. FileWrapper f("test.txt");
  46.  
  47. cin>> ws;
  48.  
  49. return 0;
  50.  
  51. }




-------------------------
Ingen signatur!



Lajnold 21:44 - 25:e Augusti 2006 | Post #2
Medlem
Inlägg: 65


Skicka PM
string s;
while ( in.getline(in, s) )
    v.push_back(s);


-------------------------
Ingen signatur!



olle 21:57 - 25:e Augusti 2006 | Post #3
Medlem
Inlägg: 57


Skicka PM
får kompileringsfel

5.cpp In constructor `FileWrapper::FileWrapper(const char*)':
5.cpp no matching function for call to `std::basic_ifstream<char, std::char_traits<char> >::getline(std::ifstream&, std::string&)'
note C:\Dev-Cpp\include\c++\3.4.2\bits\istream.tcc:582 candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::getline(_CharT*, std::streamsize, _CharT) [with _CharT =
char, _Traits = std::char_traits<char>]
note C:\Dev-Cpp\include\c++\3.4.2\bits\istream.tcc:582 std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::getline(_CharT*, std::streamsize) [with _CharT = char, _Traits = std::char_traits<char>]

  1.  
  2. #include<iostream>
  3. #include<fstream>
  4. #include<vector>
  5. #include<string>
  6.  
  7. using namespace std;
  8.  
  9. class FileWrapper{
  10. public:
  11. FileWrapper( const char *fileName );
  12. ~FileWrapper();
  13. long lineCount() const;
  14. string getLine( int i ) const;// throw (range_error);
  15. void putLine( const string &s, int i );// throw (range_error);
  16. private:
  17. vector<string> v;
  18. };
  19.  
  20. FileWrapper::FileWrapper( const char *fileName ) {
  21. ifstream in;
  22. in.open(fileName);
  23. if (!in){
  24. cerr << "Unable to open" << endl;
  25. exit(1);
  26. }
  27. string s;
  28. while ( in.getline(in,s) )
  29. v.push_back(s);
  30.  
  31. }
  32.  
  33.  
  34. FileWrapper::~FileWrapper(){}
  35.  
  36. long FileWrapper::lineCount()const {}
  37.  
  38.  
  39. string FileWrapper::getLine( int i )const /* const throw (range_error)*/ {}
  40.  
  41. void FileWrapper::putLine( const string &s, int i )/* throw (range_error) */{}
  42.  
  43. int main() {
  44.  
  45. FileWrapper f("test.txt");
  46.  
  47. cin>> ws;
  48.  
  49. return 0;
  50.  
  51. }


-------------------------
Ingen signatur!



Lajnold 22:09 - 25:e Augusti 2006 | Post #4
Medlem
Inlägg: 65


Skicka PM
Ah, det var std::istream::getline som användes. Använd std::getline istället.

string s;
while ( getline(in, s) )
    v.push_back(s);


Men vill du använda istream::getline ändå så är det rätt att skicka en char-pekare som argument. Men innan dess så måste du allokera minne för den. Och andra argumentet är då max antal tecken att läsa in.

char c[256]; //Välj själv storleken.
while ( in.getline(c, 256) )
    v.push_back(s);


-------------------------
Ingen signatur!

Senast redigerad 22:10 - 25:e Augusti 2006


olle 22:17 - 25:e Augusti 2006 | Post #5
Medlem
Inlägg: 57


Skicka PM
tackar. fungerar nu.
ska försöka fixa dom andra medlemsfunktionerna. Annars återkommer jag

-------------------------
Ingen signatur!



olle 22:56 - 25:e Augusti 2006 | Post #6
Medlem
Inlägg: 57


Skicka PM
Kommit lite längre nu. Enda som är kvar är destruktorn.
Försöker använda mig utav put funktionen i ofstream typen. Men den vill ha en char. Medans jag måste använda string för att min getLine funktionen retunerar string.
Hur ska jag göra?


  1.  
  2.  
  3. FileWrapper::~FileWrapper(){
  4.  
  5. ofstream ut;
  6. ut.open(file);
  7. if ( !ut){
  8. cerr <<"unable to open" << endl;
  9. exit(1);
  10. }
  11.  
  12. string tmp; // om char c[256], hur ska jag fixa rad 15 utan att ändra funktionen?
  13.  
  14. for ( int i=0;i<v.size();i++ ){
  15. tmp = getLine(i); // retunerar string.
  16. ut.put(tmp); // char som parameter
  17. }
  18. ut.close();
  19. }
  20.  


-------------------------
Ingen signatur!



olle 22:59 - 25:e Augusti 2006 | Post #7
Medlem
Inlägg: 57


Skicka PM
tänkte oxo fråga om detta är okey

  1.  
  2. string FileWrapper::getLine( int i )const /* const throw (range_error)*/ {
  3. string line;
  4. return line = v[i];
  5. }
  6.  
  7. void FileWrapper::putLine( const string &s, int i )/* throw (range_error) */{
  8. v[i]=s;
  9. }
  10.  


Känns som det är fel pga att det är lite kod Smiley
Fungerar dock

-------------------------
Ingen signatur!



olle 23:48 - 25:e Augusti 2006 | Post #8
Medlem
Inlägg: 57


Skicka PM
Har löst problemet.

hoppas denna lösning duger

Sen tänkte jag lägga till "throw (range_error) som finns i
getLine( int i ) const;// throw (range_error) och putLine( const string &s, int i ). Men vet inte hur man går tillväga?

Koden
  1. #include<iostream>
  2. #include<fstream>
  3. #include<vector>
  4. #include<string>
  5. using namespace std;
  6. class FileWrapper{
  7. public:
  8. FileWrapper( const char *fileName );
  9. ~FileWrapper();
  10. long lineCount() const;
  11. string getLine( int i ) const throw (range_error);
  12. void putLine( const string &s, int i ) throw (range_error);
  13. void print();
  14. private:
  15. vector<string> v;
  16. char file[50];
  17. };
  18. FileWrapper::FileWrapper( const char *fileName ) {
  19. ifstream in;
  20. in.open(fileName);
  21. if (!in){
  22. cerr << "Unable to open" << endl;
  23. exit(1);
  24. }
  25. char c[256];
  26. while ( in.getline(c,256) )
  27. v.push_back(c);
  28. strcpy(file,fileName);
  29. }
  30. FileWrapper::~FileWrapper(){
  31. ofstream ut;
  32. ut.open(file);
  33. if ( !ut){
  34. cerr <<"unable to open" << endl;
  35. exit(1);
  36. }
  37. for ( int i=0;i<v.size();i++ )
  38. ut << getLine(i) << endl;
  39. }
  40. long FileWrapper::lineCount()const {
  41. long count = 0;
  42. for ( int i=0; i<v.size();i++ )
  43. count++;
  44. return count;
  45. }
  46. string FileWrapper::getLine( int i ) const throw (range_error){
  47. string line;
  48. return line = v[i];
  49. }
  50. void FileWrapper::putLine( const string &s, int i )throw (range_error) {
  51. v[i]=s;
  52. }
  53. void FileWrapper::print(){
  54. for ( int i=0; i<v.size();i++ )
  55. cout <<v[i]<<endl;
  56. }
  57. int main() {
  58. FileWrapper f("test.txt");
  59. f.putLine("hej",6);
  60. f.print();
  61. cin>> ws;
  62. return 0;
  63. }


-------------------------
Ingen signatur!

Senast redigerad 23:51 - 25:e Augusti 2006


Lajnold 01:01 - 26:e Augusti 2006 | Post #9
Medlem
Inlägg: 65


Skicka PM
// vector har en funktion, size, som returnerar antalet element. Utnyttja den.
long FileWrapper::lineCount() const {
    return v.size();
}

// Det räcker att du returnerar det element som ska returneras.
string FileWrapper::getLine( int i ) const throw (range_error) {
    return v[i];
}


Angående "throw (range_error)". Det antyder att denna funktion kan komma att kasta ett undantag, range_error. Så det du borde göra är att lägga till en out of bounds-check och kasta ett range_error vid behov. Och förstås se till att fånga detta. Kolla upp "exceptions" om du inte vet hur dessa fungerar.

-------------------------
Ingen signatur!



olle 12:54 - 26:e Augusti 2006 | Post #10
Medlem
Inlägg: 57


Skicka PM
ska ta reda på hur exceptions fungerar. Har använt det tidigare med try och catch. Men aldrig sett throw (range_error) vet liksom inte vad man ska göra med range_error.. Klagar på den om att den inte är någon identiefer.

-------------------------
Ingen signatur!



Lajnold 12:56 - 26:e Augusti 2006 | Post #11
Medlem
Inlägg: 65


Skicka PM
Inkludera stdexcept.

-------------------------
Ingen signatur!



olle 13:07 - 26:e Augusti 2006 | Post #12
Medlem
Inlägg: 57


Skicka PM
så här blev det nu

fungerar och kompilera

  1. string FileWrapper::getLine( int i )const throw(range_error) {
  2. try
  3. {
  4. return v[i];
  5. }
  6. catch(range_error)
  7. {
  8. cout << "Caught an exception with range_error: ";
  9. }
  10. }


undrar om det ser rätt ut? Eller måste man använda range_error i cout?

-------------------------
Ingen signatur!

Senast redigerad 13:10 - 26:e Augusti 2006


Lajnold 20:19 - 26:e Augusti 2006 | Post #13
Medlem
Inlägg: 65


Skicka PM
"throw(range_error)" betyder att funktionen ska kasta ut undantaget vid behov. Det ska sedan vara den anropande funktionens ansvar att fånga detta undantag.

-------------------------
Ingen signatur!



olle 22:26 - 26:e Augusti 2006 | Post #14
Medlem
Inlägg: 57


Skicka PM
tack för infot.

Då förmodar jag att jag har gjort rätt i koden.


-------------------------
Ingen signatur!



Lajnold 22:47 - 26:e Augusti 2006 | Post #15
Medlem
Inlägg: 65


Skicka PM
Du ska kasta ut undantaget från funktionen.
string FileWrapper::getLine( int i )const throw(range_error) {
    if(i < 0 || i > v.size() - 1)
        throw range_error("Out of bounds.");
    return v[i];
}


Sedan ska funktionen som anropar getLine ta hand om det med hjälp av try-catch.

-------------------------
Ingen signatur!



olle 11:10 - 29:e Augusti 2006 | Post #16
Medlem
Inlägg: 57


Skicka PM
Nu fungerar koden, tack för hjälpen.

-------------------------
Ingen signatur!



Sidor: 1

Forum huvudsida -> Programmering -> C++, Tenta uppgift? ( I/O )
Atom feed

Du får inte posta i den här tråden | Till toppen