Zeichenlängen in .txt erkennen



  • Moin liebe Community 🙂

    ⚠ Achtung! Das Hauptproblem wurde bereits gelöst! Zur Lösung gehe bitte auf Seite #2

    Zunächst ein Verweis auf meinen Beitrag im IT-Forum (http://www.c-plusplus.net/forum/p2405654#2405654

    Da schrieb ich über das Problem mit dem 255 Pfadlängenproblem und wie man es beheben könne.
    Dies am Besten als OpenSource ... und naja ihr könnts ja lesen wenn es euch interessiert 😃

    Nun wollte ich parallel dazu euch fragen, wie man das in C-Code umwandelt.
    Meine eigenen Kenntnisse begrenzen sich auf C bzw. PHP, wobei ich C auch nur Anfängerkenntnisse... (ehm keine Ahnung wie ich das beschreiben soll: wenn ich etwas programmiere muss ich mindestens eine stunde oder zwei nachschauen, was was bedeutet ... aber ich mache Fortschritte ^^)

    Um auf den Punkt zu kommen:
    Ich hab mal angefangen ein paar Ideen dafür aufzustellen und schreibe euch das mal:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include 'alledateien.txt'  	
    
    int main()
    {
                                    // Anzahl der Zeilen im Dokument erfassen
    	for (i = 0; i < x; i++)
                                   // for-schleife: i stellt hierbei die derzeitige position (zeile) dar und x (kommt aus der vorherigen funktion) die gesamte anzahl der zeilen		            
                                   // Innerhalb der for-schleife: anzahl der zeichen erfassen.    
                                   //if-verzweigung: wenn (anzahl der zeichen > 255) printf("%d ist zu lang!!!", i);  									  
    }
    

    (Sorry, falls der Code etwas blöd aussieht ... muss mich erstmal dran gewöhnen, dass hier zu schreiben)

    Nun kommt die Erklärung dazu:
    #include <string.h> // Man könnte das ganze auch über Strings lösen (da Pfade ja nichts anderes sind, oder 😕 )

    #include 'alledateien.txt' //Die CMD-Kommandozeile erzeugt eine Textdatei, die ich dann untersuche.

    /*Hier fällt mir ein, dass ich euch garnicht geschrieben hab, wie ich die Textdatei erzeuge 😮
    => (in cmd) dir /s /b /ad c:\Users\Vinni\Desktop\ > alledateien.txt
    */

    Jetz kommen wir zum eigentlichen Punkt ^^

    Zunächst soll die Anzahl der Zeilen im Dokument gelesen und gespeichert werden.
    Diese Zeilen könnten evtl als String gespeichert werden (einzeln). Dazu noch die Frage, ob man ein String-Array bauen kann, also ein Array, dass als Elemente Strings hat. (oder auch Pointer auf Strings ... weiß aber nich ob man das so umsetzen kann)

    Dann eine for-Schleife, die die Strings bzw. Zeilen abläuft und die Zeichen darin liest.
    Mit der If-Verzweigung (auch innerhalb der Schleife) wird dann ausgegeben: String/Zeile x ist länger als 255 Zeichen oder es wird zurück zum Anfang der Schleife gegangen. (So zumindest die Theorie)

    Ich würde mich über ein paar Anregungen freuen.
    Ihr müsst mir nicht komplette Codes schreiben, nur evtl ein paar Hinweise und Methoden ( readchar oder sowas hieß glaube ich eine Funktion 😕),
    die ich dann umsetzen kann 🙂
    Will ja schließlich auch was lernen hier und nicht den ganzen Code vorgekaut bekommen.

    Beste Grüße wünscht
    Lordakius :p



  • #include 'alledateien.txt'
    

    Das ist lustig, geht aber so nicht.
    Mit #include bindet man C-Quellcode-Dateien ein und keine Anwenderdateien.
    Der beschriebene Weg über cmd > Datei > Datei zeilenweise lesen ist möglich aber umständlich.
    Besser wäre die Verwendung der POSIX Funktion popen und dabei dann die WinApi Variante _popen, die die o.g. Sache für dich erledigt, also in etwa

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
      char zeile[10000];
      FILE *f = _popen("dir /s /b /ad c:\Users\Vinni\Desktop\","r");  
      if(!f) return 1;
    
      while( fgets(zeile,10000,f) )
        if( strlen(zeile)>255 )
          printf("\nPfad laenger als 255: \"%s\"",zeile);
    
      _pclose(f);
      return 0;
    }
    


  • Ich würde so beginnen:

    Datei zum Lesen öffnen
    
    Eine Zeile einlesen
    
    while(Datei nicht zu Ende)
    {
       Zeilenanzahl um 1 erhöhen
       Zeilenlänge ermitteln
       Abhängig von der Zeilenlänge was auch immer machen
       Eine Zeile einlesen
    }
    
    Zeilenanzahl ausgeben (oder auch nicht)
    


  • Danke für die schnellen Antworten 🙂

    @Wutz Habe es mal mit deinem Code versucht und MS Visual Studio Express 2013 gibt mir folgende Fehlermeldungen:
    Zeile 7: Falsch formatierter universeller Zeichenname.

    FILE *f = _popen("dir /s /b /ad c:\Users\Vinni\Desktop\","r");
    

    Zeile 7: Fehlende schließende Anführungszeichen
    Zeile 7: Zu wenig Argumente im Funktionsaufruf

    Nur zum verständnis:
    FILE *f => Pointer *f auf einen FILE-Typ? Kenn Pointer nur mit int, float und co.

    Außerdem: Muss ich nicht beim Pfad noch die .txt datei angeben?
    Sonst sucht er ja einfach in dem Verzeichnis nach einer FILE-Data oder?

    Mit besten Grüßen
    Lordakius

    #Edit:
    @Belli Toller Ansatz, werde es gleich bei mir verändern (vllt schreib ich die Version nochmal komplett selbst a.k.a. Übung macht den Meister 🕶 )



  • Ja du hast recht, das muss für Windows

    FILE *f = _popen("dir /s /b /ad c:\\Users\\Vinni\\Desktop\\","r");
    

    heißen.



  • Da der \ eine Escapesequenz einleitet, muss er doppelt angegeben werden, wenn er selber gemeint ist.
    \" ist eine gültige Sequenz, von daher erkennt der Compiler das " nicht als Abschluss vom Stringliteral.

    FILE *f = _popen("dir /s /b /ad c:\\Users\\Vinni\\Desktop\\","r");
    

    Ist das in PHP nicht genau so?

    Lordakius schrieb:

    Nur zum verständnis:
    FILE *f => Pointer *f auf einen FILE-Typ? Kenn Pointer nur mit int, float und co.

    Ja, lies ein Buch über C.

    Lordakius schrieb:

    Außerdem: Muss ich nicht beim Pfad noch die .txt datei angeben?
    Sonst sucht er ja einfach in dem Verzeichnis nach einer FILE-Data oder?

    Das Kommando "erzeugt" deine Textdatei intern. Das dir ... wird ausgeführt und die Ausgabe davon wird gleich vom Programm gelesen.

    Vielleicht machst du das in PHP, wenn du PHP besser kannst als C.



  • Wutz schrieb:

    Ja du hast recht

    Okay, dass mit dem Code hab ich korrigiert.
    Was ist jedoch mit der .txt?
    Muss ich die nicht noch irgendwo angeben?

    Wenn ja, wo? 😃

    Lordakius



  • DirkB schrieb:

    Da der \ eine Escapesequenz einleitet, muss er doppelt angegeben werden, wenn er selber gemeint ist.
    \" ist eine gültige Sequenz, von daher erkennt der Compiler das " nicht als Abschluss vom Stringliteral.

    Danke 🙂

    DirkB schrieb:

    Vielleicht machst du das in PHP, wenn du PHP besser kannst als C.

    Hätte ich vielleicht erwähnen sollen: PHP lerne ich gerade erst ^^



  • So, der Code sieht zunächst gut aus, nach dem Debuggen kommen folgende Meldungen rein:

    "Projekt7.exe" (Win32): "C:\Users\Vinni\Documents\Visual Studio 2013\Projects\Projekt7\Debug\Projekt7.exe" geladen. Symbole wurden geladen.
    "Projekt7.exe" (Win32): "C:\Windows\SysWOW64\ntdll.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Projekt7.exe" (Win32): "C:\Windows\SysWOW64\kernel32.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Projekt7.exe" (Win32): "C:\Windows\SysWOW64\KernelBase.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Projekt7.exe" (Win32): "C:\Windows\SysWOW64\msvcr120d.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Projekt7.exe" (Win32): "C:\Windows\SysWOW64\apphelp.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Projekt7.exe" (Win32): "C:\Windows\SysWOW64\cmd.exe" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Projekt7.exe" (Win32): "C:\Windows\SysWOW64\cmd.exe" wurde entladen.
    Das Programm "[3376] Projekt7.exe" wurde mit Code 0 (0x0) beendet.
    

    Meine eigene Schätzung wäre, dass ich noch einen Verweis auf die entsprechenden PDB-Dateien geben muss. Außerdem kam auch eine Fehlermeldung in cmd, die ich mir auch nicht erklären kann:

    Der Befehl ""C:\Users\Vinni\AppData\Local\Temp\jgmqpdwcspniuccts.exe"" ist entweder falsch geschrieben oder konnte nicht gefunden werden.
    

    sieht mir stark nach einem Befehl aus, der nicht mehr existiert, evtl. ein Virus, den ich gelöscht, wo aber noch was in der Registry übrig ist?
    Diese Fehlermeldung erscheint auch, wenn ich einfach nur cmd ausführe (über windows + R)

    beste grüße
    Lordakius

    #Edit: ich seh grad noch ne Warnung:
    Warning C4013: 'strlen' undefiniert; Annahme: extern mit Rückgabetyp int

    muss ich vllt doch string.h implementieren? fällt mir grad auf 😮



  • Lordakius schrieb:

    Was ist jedoch mit der .txt?
    Muss ich die nicht noch irgendwo angeben?

    Wutz schrieb:

    Der beschriebene Weg über cmd > Datei > Datei zeilenweise lesen ist möglich aber umständlich.
    Besser wäre die Verwendung der POSIX Funktion popen und dabei dann die WinApi Variante _popen, die die o.g. Sache für dich erledigt, also in etwa

    Lordakius schrieb:

    Hätte ich vielleicht erwähnen sollen: PHP lerne ich gerade erst ^^

    C kannst du ja auch nicht. Von daher spielt es dann keine Rolle womit du das programmierst.
    (Du hast nur deine C-Fähigkeiten eingeschränkt.)



  • Lordakius schrieb:

    #Edit: ich seh grad noch ne Warnung:
    Warning C4013: 'strlen' undefiniert; Annahme: extern mit Rückgabetyp int

    muss ich vllt doch string.h implementieren? fällt mir grad auf 😮

    Nein, implementieren musst du es nicht. Die Funktion gibt es schon in der C-Standardlibrary.
    Aber damit der Compiler weiß, wie die Funktion aufgerufen wird, muss er die Deklaration der Funktion kennen.
    Die steht in string.h.
    Daher reicht es aus, wenn du ein #include <string.h> am Anfang von deinem Code machst.

    Steht aber auch in dem C-Buch



  • Jo das einfügen der string.h hab ich auch gemacht,
    (bissel C kann ich ja doch ^^)

    Allerdings hab ich keine Ahnung was mit den PDB-Dateien sein soll.
    Sehen mir wie Standard Windows-befehle aus. Warum gibts also Fehler?

    #Edit:
    http://msdn.microsoft.com/de-de/library/aa292304(v=vs.71).aspx
    Heißt das, bei mir fehlen die Befehle?
    lg Lordakius



  • Das ist die leidige Unsitte bei MS mit den vorcompilierten Headerdateien.
    Die solltest du in den Projekteinstellungen abschalten.



  • Wutz schrieb:

    Die solltest du in den Projekteinstellungen abschalten.

    Wo finde ich die?

    Ich weiß gerade nicht, ob ich es nicht schon gesagt habe, aber wenn beim ausführen die cmd geöffnet wird, passiert garnichts. Es wird weder eine neue Textdatei geschrieben, noch wird eine untersucht ( zumindest krieg ich nix zurück ... das kann aber auch daran liegen, dass ich nix über 255 zeichen hab)
    Ich werde mal die grenze runtersetzen und schauen ob was passiert.

    #edit:
    Okay, habs getestet und es gibt auch was in cmd aus.
    An diesem Punkt: danke für eure Mühen 🙂
    Jetz gibts noch 2 Probleme:
    Einmal krieg ich in cmd ständig dieses "Der befehl wurde nicht gefunden" (habs ja oben schon geschrieben, auch wenn es wahrscheinlich systemseitig ist, nervt das ganz schön 😡 )
    Und bei Visual Studio beim Debug-fenster mit den PDB dateien.

    #Edit²: Das mit der cmd-Fehlermeldung hat sich geklärt ^^
    War der Überrest eines Virus ... Musste das System sowieso mal wieder neu aufsetzen 😃 😃

    Hier noch einmal der "gefixte" Code für das Problem, falls noch jemand das Problem hat:

    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h>
    
    int main()
    {
    	char zeile[10000];
    	FILE *f = _popen("dir /s /b /ad c:\\Users\\Vinni\\Desktop\\", "r");
    		if (!f) return 1;
    
    	while (fgets(zeile, 10000, f))
    		if (strlen(zeile)>255)
    			printf("\nPfad laenger als 255: \"%s\"", zeile);
    
    	_pclose(f);
    	system("PAUSE");  //Optional: Damit das CMD-fenster bleibt.
    	return 0;
    }
    

    #Edit²: da hab ich doch glatt noch meine 150 Grenze reingenommen 😃

    Beste grüße
    Lordakius



  • Hey ihr Lieben 🙂

    Jetzt sagt mir Visual Studio beim Release debuggen (nennt man den Vorgang so?),
    dass die Funktion fopen unsicher sei und ich fopen_s nehmen sollte.

    Visual Studio schrieb:

    error C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

    Dazu folgende Help-Seite von Windows:
    http://msdn.microsoft.com/en-us/library/ttcz0bys.aspx

    Nun könnte ich natürlich fopen_s benutzen, beim Suchen nach der Syntax ist mir folgende Seite vor die Augen gekommen:
    http://stackoverflow.com/questions/21873048/getting-an-error-fopen-this-function-or-variable-may-be-unsafe-when-complin

    Es wird gesagt, dass fopen_s nur unter MS Windows komaptibel ist . (so habe ich es zumindest verstanden :p )

    Nun meine Frage:
    Wie kann ich die Warning abschalten bzw. eine "sicherere" Funktion benutzen, die jedoch auch unter Linux zB kompatibel ist?

    Mit besten Grüßen
    Lordakius



  • Das wurde dir doch bereits vom Compiler gesagt:

    To disable deprecation, use _CRT_SECURE_NO_WARNINGS

    Und auf der von dir verlinkten MS-Seite steht es ebenfalls:

    To turn off CRT deprecation warnings, define _CRT_SECURE_NO_WARNINGS.

    Ebenso auf SO. Da ist es sogar die akzeptierte Antwort!



  • Ja das war mir bereits aufgefallen ...
    Hab ich wohl vergessen zu erwähnen, dass ich das bereits versucht habe es damals aber nicht geklappt hatte ... Gerade hats geklappt. Danke trotzdem 😃

    Nun aber zu der Frage einer "sicheren" Funktion:
    Gibts sowas für alle OS? oder hab ich da was falsch verstanden mit der inkompatibilität? (was ein Wort 😮 ).

    #Neue Aufgabe :
    Das Programm arbeitet jetzt auf Konsolenebene. Ich möchte nun aber eine GUI dafür entwickeln, habe sowas allerdings noch nie vorher gemacht. Ich hab mal bei den Foren durchgeschaut und da gibts auch ein Forum das heißt MFC (Visual Studio ++ (oder so ähnlich)) und darunter gibts ein Forum namens "andere GUI's".
    Muss ich also für eine GUI eine komplett neue Programmiersprache lernen (und das Forum wechseln 😃 :p ).

    Beste Grüße
    Lordakius



  • Bei SO ist sogar noch eine zweite Möglichkeit mit #pragma genannt.

    #pragma warning(disable:4496)
    

    Als erste Zeile in deinem Code.



  • DirkB schrieb:

    Bei SO ist sogar noch eine zweite Möglichkeit mit #pragma genannt.

    #pragma warning(disable:4496)
    

    Als erste Zeile in deinem Code.

    Probiert und hat nicht geklappt . Von daher auch nicht in meine Beschreibung aufgenommen. (werd ich nächstes mal machen)



  • Nicht alle angemeckerten Funktion sind unsicher.
    Viele davon sind nur unsicher, wenn man sie falsch benutzt. (NULL-Zeiger, fehlenden Angabe der Arraylänge, ...)

    Die "Ersatzfunktionen" brauchen (teilweise) mehr/andere Parameter und verhalten sich auch anders, als die originalen. Eine 1:1 Umsetzung ist also schwierig.

    Die Security Features in the CRT kannst du nachlesen: http://msdn.microsoft.com/en-us/library/8ef0s5kh.aspx

    Willst du etwas von Microsoft wissen, dann kannst du im MSDN suchen, oder google nach "MSDN Stichwort"
    Willst du etwas über *ix wissen, dann schau in die man-Page, oder google nach "man Stichwort"

    Zur GUI.
    Schau mal was darüber steht: "Frameworks"
    Das sind keine Programmiersprachen. Sondern ~(lies es bei Wikipedia nach)~

    Welches Framework du nehmen kannst, hängt auch von deinen Zielen (Plattform, komplexität) ab.
    Aber nur mit C wirst du nicht weit kommen.


Anmelden zum Antworten