Anzeige:
Ergebnis 1 bis 9 von 9

Thema: Bug in gnu-fopen?

  1. #1
    Registrierter Benutzer
    Registriert seit
    22.03.2001
    Beiträge
    650

    Question Bug in gnu-fopen?

    Ich will eine Datei downloaden und verarbeiten, aber das funktioniert nur bis fopen darauf aufgerufen wird:

    ...
    const char ca_file_name[40]="index.html?area\\=update";
    ...
    // clean
    snprintf (cline, MAX_LINE_LENGTH, "rm -- %s", ca_file_name);
    i = system (cline);
    if (i)
    fprintf (stderr, "Error: system(%s) returned %d .\n", cline, i);
    else
    fprintf (stderr, "Ok, %s deleted.\n", ca_file_name);
    ...

    funktioniert, wie ich an der OK-Meldung zur vorher downgeloadeten Datei sehe, aber ein späteres fopen, auf die anschließend downgeloadete Datei schlägt fehl:

    ifp = fopen (ca_file_name, "r");

    Testweise habe ich deshalb das fopen mal schreibend gemacht und als Dateinamen

    index.html?area\\\=update

    erhalten, also mit zwei Backslashes zuviel!!
    Wie kann das sein?

  2. #2
    Registrierter Benutzer Avatar von panzi
    Registriert seit
    04.05.2001
    Ort
    Kottingbrunn
    Beiträge
    609
    Zitat Zitat von nobody0
    Ich will eine Datei downloaden und verarbeiten, aber das funktioniert nur bis fopen darauf aufgerufen wird:

    ...
    const char ca_file_name[40]="index.html?area\\=update";
    ...
    // clean
    snprintf (cline, MAX_LINE_LENGTH, "rm -- %s", ca_file_name);
    i = system (cline);
    if (i)
    fprintf (stderr, "Error: system(%s) returned %d .\n", cline, i);
    else
    fprintf (stderr, "Ok, %s deleted.\n", ca_file_name);
    ...

    funktioniert, wie ich an der OK-Meldung zur vorher downgeloadeten Datei sehe, aber ein späteres fopen, auf die anschließend downgeloadete Datei schlägt fehl:

    ifp = fopen (ca_file_name, "r");

    Testweise habe ich deshalb das fopen mal schreibend gemacht und als Dateinamen

    index.html?area\\\=update

    erhalten, also mit zwei Backslashes zuviel!!
    Wie kann das sein?
    Also 4 Backslashes? Hm. Nunja. In einen C-String musst du \\ schreiben um einen Backslash zu bekommen, da Backslash der Escape-Character ist, der z.B. ein " escaped, so das man mit \" ein " in einen String schreiben kann.

    In Dateinamen können unter Linux alle Zeichen vorkommen, selbst Slash, also /. Das Problem dabei ist aber, wie unterscheidet das System nun ob es sich um einen Verzeichnistrenner handelt, oder um einen Dateinamen mit einen Slash drinnen? Na ganz einfach, man führt einen Escape-Character ein, mit dem man das unterscheiden kann. Und welcher ist das? Richtig! Backslash. Also \/ bedeutet Dateinamen mit / drinnen.

    Will man nun einen Backslash drinnen haben muss man den escapen, also \\ schreiben. Das führt dazu, wenn man in einen C-String einen Dateinamen mit EINEN Backslash schreiben will, muss man VIER schreiben.

    Klinkt komisch, ist aber so.

    PS: Folgt einem Backslash ein Zeichen, das escaped keine besondere bedeutung hat, also z.B. ein buchstabe oder auch =, dann wird das als zwei Zeichen, ein Backslash und eben das zweite Zeichen, interpretiert. Also in dem Fall würden drei Backslashes reichen. Finde ich aber unschön weil inkonsistent.

    PPS: Ich hab das jetzt nicht nachgeprüft, aber ich denk das ist so wie ich geschrieben hab.
    Geändert von panzi (03-06-2006 um 00:23 Uhr)
    Intel Core 2 Duo CPU 2.66GHz; Nvidia GeForce 8 8800 GTS; 4GB RAM; Fedora 12; KDE-testing

  3. #3
    Registrierter Benutzer
    Registriert seit
    22.03.2001
    Beiträge
    650
    Da verwechselst Du etwas; der Verzeichnistrenner ist "/" und nicht "\". Das ist aber auch egal; ein Dateiname darf ja auch einen Pfad enthalten.

    Übrigens habe ich herausgefunden, woran es lag: Nur bei printf und Consorten oder Shell-Variablen ist zur Ausgabe von "\" die Angabe von "\\" nötig; bei Zuweisungen wie

    char ca_bsp[123]="foo\=bar";

    ist es unnötig.
    Verwirrt hatte mich die unnötige Meldung vom gcc:

    warning: unknown escape sequence '\='

    was aber irrelevant ist, da es im String steht.
    Wenn der String einfach angegeben wird und die Warnung ignoriert wird, funktioniert es problemlos

  4. #4
    Registrierter Benutzer Avatar von SeeksTheMoon
    Registriert seit
    22.02.2002
    Beiträge
    762
    ist nicht irrelevant, nur weil es im String steht.
    \<zeichen> ist immer eine Escape-Sequenz. Wenn er bei \= im String nicht meckern soll, dann musst Du den Backslash escapen, damit das = nicht als spezielles Zeichen interpretiert wird und \\= schreiben.
    I haven't lost my mind - It's somewhere on a backup-disc

  5. #5
    Registrierter Benutzer
    Registriert seit
    22.03.2001
    Beiträge
    650
    Ich verwende nun

    Code:
    const char ca_file_name[40] = {'i', 'n', 'd', 'e', 'x', '.', 'h', 't', 'm', 'l', 
     '?', 'a', 'r', 'e', 'a', '\\', '=', 'u', 'p', 'd', 'a', 't', 'e', '\0'};
    um klarzustellen, was gemeint ist, aber das funktioniert nun auch nicht richtig: wenn der Name dem rm -- übergeben wird, funktioniert es, aber wenn
    damit fopen versucht wird, schlägt es fehl, weil fopen einen Bachslash als drei interpretiert
    Wie kann das jetzt sein?
    Laut manpage soll fopen nur einen Filepointer zu einem nullterminierten String liefern; von escapen oder sonstwas steht da nix.

  6. #6
    Registrierter Benutzer
    Registriert seit
    22.03.2001
    Beiträge
    650
    So, nun habe ich den Fehler: Das C funktioniert, aber die Bash escapt: Die Datei heißt "index.html?area=update", aber die Bash zeigt sie als "index.html?area\=update".
    Mit dem richtigen Dateinamen funktionert das C-Programm.

  7. #7
    Registrierter Benutzer Avatar von panzi
    Registriert seit
    04.05.2001
    Ort
    Kottingbrunn
    Beiträge
    609
    Zitat Zitat von nobody0
    So, nun habe ich den Fehler: Das C funktioniert, aber die Bash escapt: Die Datei heißt "index.html?area=update", aber die Bash zeigt sie als "index.html?area\=update".
    Mit dem richtigen Dateinamen funktionert das C-Programm.
    Hast du mein posting überhaupt gelesen? Da hab ich das alles so beschrieben. / ist der verzeicvhnistrenner, \ der escape char. um den esc. char. schreiben zu können muss man ihn escapen -> \\. und das im c-string und im shell-kommando -> \\\\
    Intel Core 2 Duo CPU 2.66GHz; Nvidia GeForce 8 8800 GTS; 4GB RAM; Fedora 12; KDE-testing

  8. #8
    Registrierter Benutzer
    Registriert seit
    22.03.2001
    Beiträge
    650
    Der C-String war nicht das Problem; das Problem war die Shell!
    Da muss man "dreimal um die Ecke denken": Der von ls angezeigte Dateiname wird anders geschrieben als angezeigt ("index.html?area\=update" wird angezeigt, "index.html?area=update" ist der Dateiname); will man den angezeigten Dateinamen als einen kurzen C-String angeben, muss der Backslash escapt werden, also "index.html?area\\=update" geschrieben werden und da der Dateiname aber keinen Backslash enthält, gibt es letztlich nichts zu escapen
    Geändert von nobody0 (03-06-2006 um 15:57 Uhr)

  9. #9
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    Übrigens: zum Löschen von Dateien ruft man nicht rm per system() auf, sondern nutzt einfach unlink()

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •