Hey,
ich hätte kurz eine Frage:
Das Programm soll die anzahl der Wörter zählen, was es auch tut, jedoch
wenn das erste Zeichen schon ein Enter ist wird in dem Fall auch das
Enter bei fgets als ein Wort gezählt:
1
# include <conio.h>
2
# include <stdio.h>
3
4
intwordcount(chars[]);
5
6
intmain()
7
{
8
charsatz[99],anzahl=0;
9
10
fgets(satz,99,stdin);
11
12
anzahl=wordcount(satz);
13
14
printf("Wortanzahl: %d",anzahl);
15
16
getch();
17
return0;
18
}
19
20
intwordcount(chars[])
21
{
22
inti,count=0;
23
24
for(i=0;s[i]!=0;i++)
25
{
26
27
if(s[i]==' ')
28
{
29
30
count++;
31
32
}
33
}
34
35
returncount+1;
36
}
Wenn ich nicht count+1 zurückgebe wird halt ein Wort weniger ausgegeben,
da das Enter nicht als Wort gezählt wird.
Könnte mir jemand helfen? Danke :)
Muco schrieb:> Könnte mir jemand helfen? Danke :)
dein Programm zählt keine Wörter sondern Leerzeichen.
Was ist wenn 2 Leerzeichen hintereinander kommen?
Da wirst du wohl etwas mehr code schreiben müssen.
Ich weiß, dass mein Programm Leerzeile zählt, aber trotzdem werden
dadurch gleichzeitig auch Wörter gezählt deswegen habe ich halt "Wörter
gezählt" gesagt. Aber sorry falls dich das gestört hat.
Kannst du mir auch meine Frage beantworten? Wäre sehr nett.. Danke
Muco schrieb:> Ich weiß, dass mein Programm Leerzeile zählt, aber trotzdem werden> dadurch gleichzeitig auch Wörter gezählt deswegen habe ich halt "Wörter> gezählt" gesagt.
nein ebend nicht, wie du selber siehst.
Bei dir wird jede Leerzeile und jedes zusätzliche Leerzeichen als Wort
gezählt und das ist falsch.
Ja du hast schon recht aber zuerst wollte ich mal verstehen wie ich das
mit dem Zählen von Leerzeichen hin bekomme.
Wenn ich nicht count+1 zurückgebe wird halt ein Zeichen weniger
ausgegeben.
Wie könnte ich das lösen?
Muco schrieb:> Ja du hast schon recht aber zuerst wollte ich mal verstehen wie> ich das> mit dem Zählen von Leerzeichen hin bekomme.>> Wenn ich nicht count+1 zurückgebe wird halt ein Zeichen weniger> ausgegeben.> Wie könnte ich das lösen?
Schau Dir mal strtok() an.
Grüsse,
R.
@ Muco
Das mit den Leerzeichen ist irgendwie ja eine nette Idee. Hat nur ein
paar Nachteile, sprich: es funktionert nicht. Was z.B. wenn nicht ein
Leerzeichen, Worte trennt, sondern ein Tabulator? Etcpp.
Hab Nachsicht mit uns, die wir hier teilweise erst seit 30 Jahren im
Fach sind. Wir neigen zu inakzeptabler Genauigkeit. :-)
Aber zu Übungszwecken wäre es doch ganz nett wenn Du mal eine positive
Definition von Wörtern erstellst und das Programm dazu. Das freut auch
Deinen Lehrer. Bestimmt!
Wie gesagt - Du zählst keine Worte. Aber das weißt Du ja selbst.
> Wenn ich nicht count+1 zurückgebe wird halt ein Wort weniger ausgegeben,> da das Enter nicht als Wort gezählt wird.
Wenn Du "ENTER" mitzählen willst,
if( (s[i]==' ') || (s[i]=='\r') || (s[i]=='\n') )
Hier würde aber bei einem Windows System CR und LF getrennt gezählt, Du
bekommst nun ein "count" zu viel.
if( (s[i]==' ') || (s[i]=='\n'))
Hier würde "nur" NewLine erkannt. Wenn Deine Eingabe nur mit
Carriage-Return endet, dann würdest Du das nicht nichtig zaehlen.
Tabs und andere Sonderzeichen würdest Du immer noch nicht erkennen.
if (!isprint(s[i])) könnte man auch mal anschauen.
All das zählt aber - wie Du weißt - nicht die Wörter, sondern die
Leer/Sonderzeichen.
Danke an alle also das mit : if( (s[i]==' ') || (s[i]=='\n')) hat eh
geklappt.
Dass da jetzt nicht Wörter sondern Zeichen gezählt werden ist mir auch
klar aber danke an alle. Mir geht es eigentlich daweil darum , dass ich
mit Strings besser umgehen kann und versuche eigentlich den Unterschied
zwischen der Eingabe mit scanf und mit fgets zu verstehen.
Ich hätte evtl. noch eine Frage:
Wenn ich einen String deklariere mit 100 Zeichen: char s[100] dann sind
ja eigentlich 99 Zeichen für mich zur Eingabe reserviert und das letzte
Zeichen ist ein '\0' stimmt das?
Was ist aber bei fgets da muss doch auch ein Enter mit reserviert werden
und ich müsste sozusagen 2 Zeichen mehr reservieren oder?
Danke nochmal
HertzFrequenz schrieb:> Hab Nachsicht mit uns, die wir hier teilweise erst seit 30 Jahren im> Fach sind. Wir neigen zu inakzeptabler Genauigkeit. :-)
Gefaellt mir :D
Muco schrieb:> Was ist aber bei fgets da muss doch auch ein Enter mit reserviert werden> und ich müsste sozusagen 2 Zeichen mehr reservieren oder?
Ja. Nein. Vielleicht.
fgets weiß, das es die '\0' ablegen muss und berücksichtigt das auch.
Mit dem '\n' von der Entertaste kannst du überprüfen, ob die ganze Zeile
eingelesen wurde.
Wenn kein '\n' im Array enthalten ist, hat fgets aus Platzmangel das
einlesen unterbrochen. Es stehen also noch Zeichen von der Zeile im
Eingabestrom.
Bei scanf gibst du die maximal Anzahl an Zeichen an, die scanf einlesen
darf.
Zudem läßt scanf Zeichen, die nicht zum Formatspecifier passen, im
Eingabestrom stehen.
HertzFrequenz schrieb:> Hab Nachsicht mit uns, die wir hier teilweise erst seit 30 Jahren im> Fach sind. Wir neigen zu inakzeptabler Genauigkeit. :-)
Das mag daran liegen, dass der Computer nicht das macht was man will,
sondern das, was man ihm sagt.
Dirk B. schrieb:> Bei scanf gibst du die maximal Anzahl an Zeichen an, die scanf einlesen> darf.
Also nach meinen Wissensstand gibt man da nichts an, von wegen wie viele
Zeichen. So weit ich weiss, liest scanf bis zum ersten White-Space.
Korrigiert mich, falls ich irre.
Gruesse
Kaj schrieb:> So weit ich weiss, liest scanf bis zum ersten White-Space.
Das tut es, und deswegen gehört scanf auch auf die schwarze Liste
der unbedingt verbotenen Funktionen.
fscanf ist hier eindeutig zu bevorzugen. Als Dateihandle ist stdin
zu verwenden, und der Drops ist gelutscht.
-- Nachträgliche Anmerkung:
Hier habe ich Unfug geschrieben. Leider ist das nicht so, die
Weihnachtsfeiertage haben mich irgendwie benebelt.
Kaj schrieb:> Also nach meinen Wissensstand gibt man da nichts an, von wegen wie viele> Zeichen. So weit ich weiss, liest scanf bis zum ersten White-Space.> Korrigiert mich, falls ich irre.
Du beziehst dich auf %s.
Was ist mit %9s ?
Maximal 9 Zeichen oder bis zum Whitespace. Je nachdem was früher
eintritt.
Rufus Τ. Firefly schrieb:> fscanf ist hier eindeutig zu bevorzugen. Als Dateihandle ist stdin> zu verwenden, und der Drops ist gelutscht.
Wo hat fscanf andere Formatspecifiere?
Bzw. wie verhält sich das anders als scanf?
Dirk B. schrieb:> Rufus Τ. Firefly schrieb:>> fscanf ist hier eindeutig zu bevorzugen. Als Dateihandle ist stdin>> zu verwenden, und der Drops ist gelutscht.>> Wo hat fscanf andere Formatspecifiere?> Bzw. wie verhält sich das anders als scanf?
Das würde mich auch interessieren. Evtl. verwechselt mit gets()/fgets()?
Rolf Magnus schrieb:> Das würde mich auch interessieren. Evtl. verwechselt mit gets()/fgets()?Mist.
Ja, Asche auf mein Haupt, die Weihnachtstage und der ganze Brimborium
sind eindeutig nicht gut überstanden.
-------------
Um dem ganzen einen Sinn zu geben:
Eine halbwegs sichere Kombination gibt es nur, wenn die eigentliche
Einleseoperation und das Parsen des eingelesenen Strings getrennt
gehandhabt wird.
Um sicherzustellen, daß nicht zu viel eingegeben wird, ist in einen
ausreichend dimensionierten Zeichenpuffer einzulesen (Danke für den von
Rolf Magnus völlig zurecht angebrachten Hinweis auf gets/fgets) - und
zwar mit fgets, weil da eine Puffergröße angegeben werden kann.
Der so einlesene String kann nun mit sscanf weiter zerlegt werden
(wenn man nicht strok benutzen möchte), und wie von Dirk angemerkt,
sollte hier statt %s der Formatspezifizierer mit Längenangabe verwendet
werden, also z.B. %9s.
Ärgerlicherweise verhält sich %*s bei scanf & Co. anders als bei
printf & Co., so daß die maximale Stringlänge als numerische Konstante
im Formatstring anzugeben ist, und nicht als Argument übergeben werden
kann.
So, ich hoffe, die durch die Weihnachtsdröhnung verursachten
Verwirrungen meinerseits jetzt ein bisschen kompensiert zu haben.
Wenn man schon fgets benutzt, dann weiß man auch, wie groß der Text für
%s bei sscanf maximal sein kann. Dann kann man den Puffer auch groß
genug anlegen.
scanf bzw fscanf hat den Charme, dass man keinen Puffer braucht sondern
die Daten (Zahlen) direkt einlesen kann. Auch der *-Modifiere ist dabei
hilfreich.
Es kommt dabei auch darauf an, was man einlesen möchte.
Und wer überprüft bei fgets schon, ob er die komplette Ziele gelesen
hat.
Dirk B. schrieb:> Wenn man schon fgets benutzt, dann weiß man auch, wie groß der Text für> %s bei sscanf maximal sein kann. Dann kann man den Puffer auch groß> genug anlegen.>> scanf bzw fscanf hat den Charme
scanf bzw. fscanf haben den 'Charme', dass sich damit eine unter allen
Umständen fehlerfreie Einleseprocedure als recht schwierig herausstellt.
Mit den Erweiterungen im Formatstring hat sich zwar einiges gebessert,
nichts desto trotz ist wohl die Kombination aus fgets + sscanf, bzw.
eigene Parse-Funktionen anstatt sscanf, die vernünftigste Lösung.
Hallo Leute,
vor vielen Jahren gab es schon Tools die kostenlos zu haben waren und
vermutlich noch sind (falls es sie überhaupt noch gibt).
Da gab es "YACC", welches dabei half eigene Compiler zu bauen. YACC
hatte einen Scanner und Parser um die Schlüsselworte im Quelltext zu
finden, dazu musste er den Text Wortweise abklappern. Soweit ich mich
erinnere konnte man ihn über eine Tabelle die Zeichen geben, welche ein
Wort begrenzen.
Das Gute daran, YACC lag im Quelltext vor - so kann man nachschauen wie
die das mit der Worterkennung gemacht haben, oder den entsprechenden
Code selbst verwenden. Und es war einfacher C-Code :-)
Ich hoffe es hilft ein wenig.
TomA. schrieb:> Hallo Leute,>> vor vielen Jahren gab es schon Tools die kostenlos zu haben waren
Ich bin mir recht sicher, dass es sich hier einfach nur um ein
Übungsbeispiel handelt und nicht um einen realen Einsatz.
None schrieb:> Dann bekommst Du mit Sicherheit die passenden Ideen.
Da steht aber nicht, wie man strtok programmiert.
Zudem ist es auch gar nicht nötig zeilenweise zu lesen.
Man kann nach jedem Zeichen entscheiden ob es zu einem Wort oder
Leerraum gehört.
Wichtig ist nur die Definition für Wort ( nur Buchstaben, auch Zahlen,
alles was ein darstellbasres Zeichen ist)