Forum: PC-Programmierung [C] Leerzeile hat einen komischen ASCII Wert


von Patrick M. (edge540)


Lesenswert?

Moin,

ich schreibe gerade ein Programm,
welches eine Txt Datei einliest und dann jeweils zählt,
wie häufig jeder Buchstabe vorkommt.
Dafür gehe ich die Zeilen des Textes immer zeichenweise durch
und vergleich sie mit einem Array in welchem ich das ALphabet 
gespeichert
habe. Dann addiere ich zu den jeweiligen Buchstaben Zählern einen hinzu.
Das klappt auch solagen ich keine Leerzeilen habe. Dann nämlich addiert
er mir gerne mal ein oder zwei zusätzlich hinzu.
Ich bin da mit meinem Latein ziemlich am Ende und nach 7 Std Suchen auch 
ziemlich gefrustet^^ Vielleicht ist es ja eine Fehler den einer von euch 
sofort sieht, wäre toll!

Vielen Dank schon mal,

Patrick
1
#include <stdio.h>
2
#include <string.h>
3
#define LNAME 31
4
#define LLINE 81
5
6
int main (void)
7
{
8
  char alphabet[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
9
  int alphcnt[26] = {0};
10
11
  int cnti = 0;
12
  int cntj = 0;
13
  FILE *pin, *pout;
14
  char name_in[LNAME], name_out[LNAME];
15
  char line[LLINE];
16
  memset( line, NULL, 80 ); //Setzt die ersten 80 Zeichen von line auf NULL
17
18
  do
19
  {
20
    printf("Enter name of input file : ");
21
    scanf("%30s", name_in);
22
    pin = fopen(name_in, "r");
23
  } while(pin == NULL);
24
25
26
27
  while(1)
28
  {
29
30
    fgets(line, LLINE, pin);     
31
   
32
    printf("%s", line);
33
34
    for(cntj = 0; cntj < 26; cntj++)
35
    {
36
        for(cnti = 0; cnti < LLINE; cnti++)
37
        {
38
            if(line[cnti] == alphabet[cntj])
39
               {
40
                    alphcnt[cntj]++;
41
                    printf("%d \n", alphcnt[cntj]);
42
               }
43
        }
44
    }
45
46
47
if(feof(pin)) break;
48
  }
49
50
51
52
 fclose(pin);
53
54
 system("PAUSE");
55
  return 0;
56
}

: Bearbeitet durch User
von Martin M. (capiman)


Lesenswert?

Bist du dir sicher, dass eine Zeile immer LLINE lang ist?
Bei der Leerzeile bin ich mir da nicht so sicher...

Ändere doch mal

for(cnti = 0; cnti < LLINE; cnti++)

in

for(cnti = 0; cnti < LLINE && line[cnti] != 0; cnti++)

fgets hat auch einen Returnvalue. Schau dir mal folgende Seite an:

http://www.cplusplus.com/reference/cstdio/fgets/

von Rainer V. (rudi994)


Lesenswert?

Obiges Programm analysiert den Lesepuffer line[] unabhängig davon, wie 
lang der eingelesene Text ist. Somit werden z.B. bei Leerzeilen fast 
alle Zeichen aus der zuvor eingelesenen Zeile solange weitergezählt, bis 
die nächste Zeile aus der Datei keine Leerzeile mehr ist.

Das Programm sollte beim Auftreten der Null-Terminierung bzw. des 
Zeilenendes im Lesepuffer die Zählschleifen verlassen und mit der 
nächsten Zeile aus der Datei fortfahren.

Eine Leerzeile in einer TXT-Datei enthält nur das Zeilenende-Zeichen, 
i.d.R. die 2 ASCII-Codes 13 (Carriage Return) und 10 (Line Feed).

von MWS (Gast)


Lesenswert?

Die innere Schleife hat nicht auf die maximale Länge des Arrays begrenzt 
zu sein, sondern auf die Länge der aktuell gelesenen Zeile. Sonst werden 
laufend Speicherüberreste aus vorigen Zeilen mit einbezogen. Da fgets 
"bis zu" Zeichen holt, d.h. auch weniger, scheitert die Codelogik 
bereits, wenn nachfolgende Zeilen kürzer als vorhergehende sind. Eine 
Leerzeile ist dabei definitiv kürzer.

von Justus S. (jussa)


Lesenswert?

mal abgesehen davon: ist das ganze Prinzip mit dem Alphabet im Array 
nicht eh sehr suboptimal? warum nutzt man nicht aus, das 'a' == 97, 'b' 
== 98,...?

also sowas wie
for(cnti...)
    alphcnt[line[cnti] - 97]++

eventuell noch mit Abfrage, ob ein Buchstabe zwischen 'a' und 'z' 
vorliegt...

von DirkB (Gast)


Lesenswert?

Warum liest du eine ganze Zeile ein, wenn du jedes Zeichen einzeln 
untersuchst?
fgetc statt fgets.

Warum mit jedem Zeichen im Alphabet einzeln überprüfen?
Feststellen ob das eingelesene Zeichen >= 'a' und <= 'z' ist.
(Dafür gibt es die Funktion islower() aus der ctype.h)

Wenn das Zeichen ein Kleinbuchstabe ist, dann kannst du es als Index im 
Array nutzen.
alphcnt[zeichen-'a']++;

Aber warum auf Kleinbuchstaben einschränken?
1
  unsigned int alphcnt[256] = {0};
2
3
  int c;
4
5
 ... Datei öffnen 
6
7
  while((c=fgetc(pin)!=EOF)
8
  { 
9
      alphcnt[c]++
10
  }
11
12
  fertig
13
  Datei schließen

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.