Problem beim Öffnen von Datei gemäß Parameterliste



  • Hi(gh)!

    Nach langer Zeit versuche ich mich wieder an einem C++-Programm... aber entweder hat sich mein Compiler (gcc/g++) drastisch verändert oder meine C++-Kenntnisse sind völlig verkümmert.

    Konkret:
    Ich will mittels Parameter beim Aufruf des Programmes eine Datei öffnen, also:

    int main(int argc, char* argv[])
    {
      ifstream datei;
      string source; // eingelesene Original-HTML-Textdatei als String
      char c; // eingelesenes Zeichen aus Original-HTML-Textdatei
      
      if (datei.open(argv[0], ios_base::in))
    

    bekomme aber schon beim Kompilieren ständig die Fehlermeldung:

    oac.cc:17:17: error: could not convert ‘datei.std::basic_ifstream<char>::open(((const char*)(* argv)), ((std::ios_base::openmode)std::ios_base::in))’ from ‘void’ to ‘bool’
       17 |   if (datei.open(argv[0], ios_base::in))
          |       ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
          |                 |
          |                 void
    

    ...dabei entscheidet sich doch erst beim Aufruf des fertigen Programms(!), ob argv[1] (also der erste Parameter nach dem Programmnamen) leer ist! Läßt sich dies irgendwie deaktivieren?

    Bis bald im Khyberspace!

    Yadgar



  • @Yadgar sagte in Problem beim Öffnen von Datei gemäß Parameterliste:

    Hi(gh)!

    Nach langer Zeit versuche ich mich wieder an einem C++-Programm... aber entweder hat sich mein Compiler (gcc/g++) drastisch verändert oder meine C++-Kenntnisse sind völlig verkümmert.

    Konkret:
    Ich will mittels Parameter beim Aufruf des Programmes eine Datei öffnen, also:

    int main(int argc, char* argv[])
    {
      ifstream datei;
      string source; // eingelesene Original-HTML-Textdatei als String
      char c; // eingelesenes Zeichen aus Original-HTML-Textdatei
      
      if (datei.open(argv[0], ios_base::in))
    

    bekomme aber schon beim Kompilieren ständig die Fehlermeldung:

    oac.cc:17:17: error: could not convert ‘datei.std::basic_ifstream<char>::open(((const char*)(* argv)), ((std::ios_base::openmode)std::ios_base::in))’ from ‘void’ to ‘bool’
       17 |   if (datei.open(argv[0], ios_base::in))
          |       ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
          |                 |
          |                 void
    

    ...dabei entscheidet sich doch erst beim Aufruf des fertigen Programms(!), ob argv[1] (also der erste Parameter nach dem Programmnamen) leer ist! Läßt sich dies irgendwie deaktivieren?

    Bis bald im Khyberspace!

    Yadgar

    Hast du die Fehlermeldung auch gelesen? Das open gibt nix (also void) zurück und damit kann ein if nunmal nix anfangen. Das braucht nen bool.



  • Hi(gh)!

    Hast du die Fehlermeldung auch gelesen? Das open gibt nix (also void) zurück und damit kann ein if nunmal nix anfangen. Das braucht nen bool.

    Und wie bekommt es das bool? Explizite Typumwandlung mit vorangestelltem Dateityp in Klammern (die gute alte C-Methode)? Tut mir leid, ich verstehe das nicht mehr, ich bin zu dumm dafür geworden! Digitale Demenz nennt man das wohl...

    Oder sollte ich das, was ich eigentlich vorhabe, nicht doch besser mit einem bash-Skript machen? Es geht darum, aus einem HTML-Codetext allen Code zwischen bestimmten Schlüsselwörtern zu entfernen und den so geänderten Text neu abzuspeichern...

    Bis bald im Khyberspace!

    Yadgar



  • @Tyrdal sagte in [Problem beim Öffnen von Datei gemäß Parameterliste]>
    Hast du die Fehlermeldung auch gelesen? Das open gibt nix (also void) zurück und damit kann ein if nunmal nix anfangen. Das braucht nen bool.

    Heißt dass, dass ich gar nicht mit open auf Erfolg oder Nichterfolg des Öffnens testen kann?



  • Der Stream selbst hat einen Zustand und den kannst du per bool-Operator abfragen. Und am besten gleich den passenden Konstruktor nehmen:

    ifstream datei(argv[0]) // ios_base::in ist schon voreingestellt beim ifstream
    if (datei)
    {
      // ...
    }
    


  • @Tyrdal sagte in Problem beim Öffnen von Datei gemäß Parameterliste:

    argv[0]

    Das ist der Programmname (oder irgendwas, das den Programmnamen repräsentiert). Nicht der erste Parameter. Der steht in argv[1]. Überprüfe also erst argc und öffne dann argv[1] nur dann, wenn du auch (min.) 1 Argument hast, d.h wenn argc > 1 ist.



  • Hi(gh)!

    <öl>
    ieku, ieku
    </öl>
    (C++-Erinnerungen aufgefrischt und Hirnspeicherbereiche gängig gemacht...)

    Ich hatte zwischenzeitlich mal nachgesehen, wie ich das bei früheren Projekten gemacht hatte, auch in der C++ Reference unter fstream, ifstream und open - klar, open ist eine Methode von z. B. ifstream und gibt natürlich nichts ans Hauptprogramm zurück, sondern ändert den Zustand des ifstream-Objekts, also in meinem Fall datei

    Jetzt sieht mein Programm so aus:

    /* oac (Organ Ads Compressor) 
     Programm zur Reduzierung von archivierten eBay-Elektroorgel-Anzeigen auf das zur Erfassung in Datenbanken erforderliche Minimum */
    
    #include<iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include <dirent.h>
    using namespace std;
    
    int main(int argc, char* argv[])
    {
      ifstream datei;
      ofstream datei_neu;
      string source; // eingelesene Original-HTML-Textdatei als String
      char c; // eingelesenes Zeichen aus Original-HTML-Textdatei
    
      if (argc == 2)
      {  
        datei.open(argv[1]/*, ios_base::in*/);
        if (!datei)
        {
          cerr << "Datei kann nicht geöffnet werden!" << endl;
          return 1;
        }
        else
        {  
          while (datei.get(c))
          {
            source.push_back(c);
          }
          cout << source; // Testausgabe der eingelesenen HTML-Textdatei
        }
        
        datei_neu.open("testdatei.html");
        if (!datei_neu)
        {
          cerr << "Ausgabedatei kann nicht geöffnet werden!" << endl;
          return 1;
        }
        else
        {
          datei_neu << "<!DOCTYPE html>\n"
                    << "<html>\n"
                    << "<head>\n"
                    << "  <meta charset=\"UTF-8\">\n"
                    << "  <title>Anzeige" << endl;
        }
        
      }
      else
      {
        cerr << "Kein oder mehr als ein Parameter eingegeben!" << endl;
        return 1;
      }
      
      return 0;
    }
    

    ...und kompiliert fehlerfrei!

    Das nächste Problem ist jetzt ein Aufrufzähler für main(), also das Programm oac selbst - in Zukunft soll es in einer bash-Skript-Schleife laufen und die HTML-Dateien eines Verzeichnisses abarbeiten. In den <title>-Tag des HTML-Headers soll nämlich Datum und Nummer der Anzeige eingefügt werden - das Datum steht natürlich in der Original-HTML-Datei, wohingegen die Nummer sich vom Aufrufzähler ableitet (bzw. bei jedem neuen Datum wieder auf 1 zurückgesetzt wird), so dass dann z. B. dort steht:

    <title>Anzeige: 20180316-002 Technics SX-U90 in Wuppertal</title>

    Wie bekomme ich so etwas hin?

    Bis bald im Khyberspace!

    Yadgar



  • @Yadgar Wenn das aus einer Schleife aus einem Bashskript aufgerufen wird, warum überhaupt C++ verwenden und das nicht komplett in Bash lösen? Oder, warum die Schleife nicht auch in C++ schreiben?

    Sonst musst du dir irgendwo den Aufruf merken, oder an das Programm übergeben.



  • Hi(gh)!

    @Schlangenmensch sagte in Problem beim Öffnen von Datei gemäß Parameterliste:

    @Yadgar Wenn das aus einer Schleife aus einem Bashskript aufgerufen wird, warum überhaupt C++ verwenden und das nicht komplett in Bash lösen? Oder, warum die Schleife nicht auch in C++ schreiben?

    Daran hatte ich auch schon gedacht, weshalb ich <dirent.h> inkludiert habe... aber ich war mir nicht so ganz sicher, was eventuelle Komplikationen mit dieser Bibliothek anging. Es würde auf jeden Fall relativ komplex werden, da - ich vermute mal - die dirent-Funktionen das Verzeichnis nicht aufsteigend nach Speicherdatum durchgehen können... da müsste ich einen zweidimensionalen vector (das Gerödel mit klassischen Arrays tue ich mir nicht an) für Anzeigen-Datumsangaben und Anzeigen-Anzahlen pro Datum anlegen!

    Bis bald im Khyberspace!

    Yadgar


  • Mod

    @Yadgar sagte in Problem beim Öffnen von Datei gemäß Parameterliste:

    da müsste ich einen zweidimensionalen vector (das Gerödel mit klassischen Arrays tue ich mir nicht an) für Anzeigen-Datumsangaben und Anzeigen-Anzahlen pro Datum

    Wenn es doch bloß etwas gäbe, womit man in C++ zwei Dinge zu einem verbinden könnte, das weder Vector noch C-Array ist. Aber so etwas wird es wohl nie geben, schade…



  • @Yadgar dirent.h kenne ich nicht, du könntest dir aber std::filesystem angucken.



  • @Yadgar Ehrlich gesagt habe ich dein Ziel nicht verstanden. Wenn du irgendwas aus html in einem Bash-Script per Loop extrahieren willst, warum dann überhaupt C++? Ich würde das wohl schnell in Python machen (z.B. mit scrapy oder beautifulsoup). Oder irgendeine andere Sprache nehmen, in der solche Aufgaben einfach & schnell gehen.



  • @Yadgar sagte in Problem beim Öffnen von Datei gemäß Parameterliste:

          while (datei.get(c))
          {
            source.push_back(c);
          }
          cout << source; // Testausgabe der eingelesenen HTML-Textdatei
    

    Wäre es nicht schöner, einfach die Größe der Datei zu ermitteln, einen entsprechenden Speicherblock bereitzustellen und die Datei als ein Klotz in diesen Speicherbereich zu laden?

    Da hättest du als Ausgang entweder einen Speicherblock oder bad_alloc.


Anmelden zum Antworten