Forum: Compiler & IDEs Zeichen im String zählen


von carola (Gast)


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

von Karl H. (kbuchegg)


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

von carola (Gast)


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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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?

von carola (Gast)


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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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:
1
  int c;
2
3
  while ((c = getc()) != EOF) {
4
    if (c ... ) ...
5
  }

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch wrote:
> Die lehrbuchmäßige Version einer derartigen Schleife wäre:
>
>
1
>   int c;
2
> 
3
>   while ((c = getc()) != EOF) {
4
>     if (c ... ) ...
5
>   }
6
>

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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:
1
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).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.