mikrocontroller.net

Forum: Compiler & IDEs Zeichen im String zählen


Autor: carola (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich möchte ein Programm schreiben, welches herausfindet, wie viele Werte 
in einer Datei stehen. Dafür hab ich mir überlegt, das ich die Datei in 
einen String lade, um anschließend die Anzahl des Zeichens ";" zu 
zählen. Denn nach jedem Wert folgt ein Semikolon. Das Programm benötige 
ich in C.
Kann mir jemand helfen?
Danke. Carola

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
carola wrote:

> Kann mir jemand helfen?

Sicher.
Wobei hast du denn Schwierigkeiten:

Beim öffnen der Datei
Beim Einlesen der Zeichen
Beim Vergleich
Beim Erhöhen des Zählers
Beim Schliessen der Datei
Beim Aufbau der Schleife.


PS: Es ist unklug die ganze Datei in einem Rutsch
in einen String zu laden. Je nach Größe der Datei
brauchst du dafür
* ne Menge Speicher
* eine vernünftige Allokierungsstrategie um den String
  mit fortschreitender Dateigröße immer größer zu machen

Es ist viel einfacher die Datei Zeichen für Zeichen zu lesen.
Jedesmal wenn aus der Datei ein ';' gelesen wird, erhöhst du
deinen Zähler. Zum Schluss Zähler ausgeben, fertig.


  Datei öffnen

  if Datei nicht offen {
    Fehlermeldung ausgeben
    Programm beenden
  }

  Counter = 0;

  Solange ein Zeichen aus der Datei gelesen werden konnte {
    if Zeichen == ';'
      Counter++
  }

  Datei schliessen
  Counter ausgeben

Autor: carola (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
also im Moment hab ich das beim Vergleichen. Da meine Datei wirklich 
sehr groß ist, ist es wohl klüger jedes Zeichen einzeln zu laden. Da 
ergibt sich allerdings gleich die nächste Frage: Wie ging das nochmal?

Also geöffnet habe ich die Datei bereits mit fopen und das klappt auch.
Wenn ich dann ein einzelnes Zeichen geladen habe, muss ich das ja auf 
"," vergleichen. Da in meiner Datei mehrere Semikolons vorkommen, muss 
ich da dann mit Zeigern arbeiten? Der Vergleich muss ja für das nächste 
erneut durchgeführt werden.

Danke schonmal für die Hilfe.
Carola

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wie ging das nochmal?

Mit getc().

> muss
> ich da dann mit Zeigern arbeiten?

Nein, warum?  Du liest ein Zeichen nach dem anderen ein, bis du
EOF erreicht hast.

Ein Programm dieser Art dürfte sowas wie die #2 der C-Programmierung
sein, kommt gleich nach dem berühmten "Hello, world!".

Ist das 'ne Hausaufgabe?

Autor: carola (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
habe das Problem jetzt folgendermaßen gelöst und es funktioniert auch:-)

    do
    {
     fread(zeichen, 1, 1, fileptr_Quelldatei);
     if(*zeichen == ';')
     {
      zaehler++;
     }
    }while (!feof(fileptr_Quelldatei));

Dies ist ein Teil eines Programms, welches ich für eine 
Datteibearbeitung schreiben muss. Habe lange nicht mehr in C 
programmiert, deswegen die Nachfrage nach einfachen Dingen.

Carola

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
carola wrote:

>      fread(zeichen, 1, 1, fileptr_Quelldatei);

Da bliebe die Frage: wo ist der Speicherplatz reserviert, auf den
zeichen zeigt?

Außerdem wird der Rückkehrcode von fread() nicht ausgewertet.

Die lehrbuchmäßige Version einer derartigen Schleife wäre:
  int c;

  while ((c = getc()) != EOF) {
    if (c ... ) ...
  }

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch wrote:
> Die lehrbuchmäßige Version einer derartigen Schleife wäre:
>
>
>   int c;
> 
>   while ((c = getc()) != EOF) {
>     if (c ... ) ...
>   }
> 

Hab ich auch schon lange nicht mehr gemacht.
Wie verhält sich getc() (ich denke mal du meinst fgetc())
wenn es beim Lesen einen Fehler gab? Wird dann EOF
geliefert?

@Carole:

Die korrekte Form mit fread() wäre

  char zeichen;

  while( fread(&zeichen, 1, 1, fileptr_Quelldatei) ) {
     if( zeichen == ';' )
       zaehler++;
  }

  if( !feof(fileptr_Quelldatei)) {
    // Fehlermeldung: die Datei konnte nicht fehlerfrei bis
    // zum Ende gelesen werden
  }
  else
    // zaehler ausgeben

In dem Moment wo du eine der eof() Funktionen zur Steuerung
der Schleife benutzt, hast du schon einen Fehler gemacht.
Die Schleifensteuerung geschieht praktisch immer über den
Returncode der Lesefunktion. Dazu liefern alle Lesefunktionen
einen Returncode, der dazu geeignet ist. Der wird dazu
benutzt um festzustellen ob der Leseversuch erfolgreich war
oder nicht. Ein Leseversuch kann aus vielen Gründen scheitern:
* Der Benutzer hat die CD aus dem Laufwerk genommen
* Die Netzwerkverbindung ist zusammengbrochen
* Schadhafter Sektor auf der Diskette
* Ausfall des USB Stick
* Das Ende der Datei wurde erreicht.

Die eof() Funktionen sagen dir nur ob das Ende der Datei erreicht
wurde. Sie werden korrekt benutzt um nach dem Abbrechen der
Schleife rauszufinden, warum die Schleife abgebrochen wurde:
War es aufgrund EOF dann ist alles ok: die Datei konnte fehlerfrei
bis zum Ende gelesen werden.


Traurige Geschichte, ich weiss. In 70% aller Lehrbücher findet
sich das nicht sondern der Autor hat (ich behaupte mal aus
Unwissenheit) die klassische

   while( !feof( ... ) )

benutzt.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:

> Wie verhält sich getc() (ich denke mal du meinst fgetc())

getc() und fgetc() sind in ihrer Funktion gleich.  getc() darf aber
als Makro implementiert sein, der sein Argument mehr als einmal
bewertet, daher könnte es u. U. effektiver implementiert sein.

Was ich aber vergessen habe ist:
getc(fileptr_Quelldatei)

Die Funktion bekommt natürlich ein Argument.

> wenn es beim Lesen einen Fehler gab? Wird dann EOF
> geliefert?

Ja, natürlich.  Daher muss der Typ der Variablen, auf die man das
Ergebnis zuweist, auch wirklich `int' sein und nicht etwa `char':
EOF ist -1 und damit von allen Zeichen (0...255) verschieden.

Unterscheidung nach Dateiende oder Fehler wie gehabt mit feof()
oder ferror() (eine dieser beiden Funktionen muss wahr sein,
wenn getc() zuvor EOF gebracht hat).

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.