Problem mit "strtok" und "atol"
-
Hallo Forengemeinde,
ich heiße Chris, bin 21 Jahre alt, studiere seit diesem Semester "Mobile und eingebettete Systeme" an der Uni Passau und bin ganz neu hier.
Ich hatte in meinem Leben bis zum Studiengang noch absolut nichts mit Programmierung am Hut, das ist also alles absolutes Neuland für mich.Ich bräuchte mal eure Hilfe bei einer Übungsaufgabe:
Wir sollen ein Programm schreiben, dass mehrere (Vorzeichenlose) Zahlen auf der Kommandozeile einließt:15
1234
5
46
2
[...]Dann bestimmt, ob es sich bei der jeweiligen Zahl um eine Primzahl handelt und folgendes ausgibt:
prim!
nicht prim!
nicht prim!
prim!
[...]Ich hatte mir das so überlegt, einen String mit "fgets" zu füllen, ihn mit "strtok" zu teilen und die jeweiligen Teilabschnitte mit "atol" in Integers umzuwandeln. Das funktioniert soweit auch schon.
Nur jetzt gibt es folgendes Problem: Der Befehlt "strtok" erkennt die Newlines im String nicht. Heisst, gebe ich die Zahlen mit Leerzeichen an: "12 15 4 1345 1"
spuckt er mir schön meine Tabelle aus:prim!
nicht prim!
nicht prim!
prim!
[...]**
Füttere ich ihn aber mit Zahlen in neuen Zeilen, so gibt er mir nur die Antwort für die erste eingegebene Zahl und hört dann auf.**So sieht mein Code bis dato aus:
//Christian Blechert // Uebungsblatt 5 // Aufgabe 1 #include <stdio.h> #include <string.h> int isprime(int d) { int j; for (j = 2; j <= (d/2) - 1; j++) { if (d % j == 0) return 2; } return 1; } int main(int argc, char *argv[]) { int d; int i; long int value1=0; char str1[100]; char *ptr; for (i=0;i<100;i++) { str1='b'; //fill the whole string with the letter "b" } while (fgets(str1,sizeof(str1),stdin) !=NULL); { ptr=strtok(str1, "\n\t "); //string "ptr" is the first part of str1 (until while(ptr != NULL) //the first token is found) { value1=atol(ptr); //convert "ptr" to an int "value1" d=isprime(value1); //send value to function "isprime" if (d==1) { printf("prim!\n"); } else { printf("nicht prim!\n"); } ptr=strtok(NULL, "\n\t "); //change the last found token into a "/0" } return 0; } }
Jemand eine Idee?
Mit einem extra definierten Seperator [i]char sep[]="\n\t "* habe ich es auch schon ohne Erfolg probiert.
-
Warum '\t' im Seperator?
-
Ich wollte, für den Fall der Fälle, "Neue Zeile" , "Tabeinrückung" und eben "Leerzeichen" für die Trennung berücksichtigen. Ich dachte das \t stünde für Zweiteres.
-
Im zweiten Fall (eine Zeile mit vielen Werten) ist das Trennzeichen das Leerzeichen.
Lass dir in Zeile 34 doch mal den gefundenen Text ausgeben:
printf("gefunden: <%s>\n", ptr);
Bessr noch, du nimmst den Debugger.
-
DirkB schrieb:
Mist
, weil er das Problem falsch verstanden hat.
-
Ich habe für dich mal vernünftig (besser als du) eingerückt.
while (fgets(str1,sizeof(str1),stdin) !=NULL); { ptr=strtok(str1, "\n\t "); //string "ptr" is the first part of str1 (until while(ptr != NULL) //the first token is found) { value1=atol(ptr); //convert "ptr" to an int "value1" d=isprime(value1); //send value to function "isprime" if (d==1) { printf("prim!\n"); } else { printf("nicht prim!\n"); } ptr=strtok(NULL, "\n\t "); //change the last found token into a "/0" } return 0; }
Jetzt kannst du sehen, dass das
return 0
in Zeile 18 noch in derwhile(fgets...)
Schleife steht.
Also wird das Programm nach der ersten Zeile beendet.EOF bekommt man bei Windows indem man CTRL-Z drückt. (Strg-Z)
-
Das mit dem return 0; ist schonmal gut, das habe ich jetzt korrigiert.
Ich habe leider noch kein Internet hier, so das ich nur das Inet meines Handys nutze. Deswegen arbeite ich aktuell unter Ubuntu nur mit Kate + Kommandozeile.Ich habe mal zur Überprüfung die "gefunden"-Zeile eingefügt.
Bei einer Eingabe 5 3 1 132 45 44 spuckt er mir aus, was ich haben will:5 5 2 4 4 3 4
gefunden: <5>
prim!
gefunden: <2>
prim!
gefunden: <3>
prim!Bei der mehrzeiligen angabe gibt er mir nur die letzte eingegebene Zahl.
Außerdem spuckt -Wall folgendes aus:blatt5aufgabe1.c:36:2: Warnung: Implizite Deklaration der Funktion »atol« [-Wimplicit-function-declaration]
Habe das mal gegoogelt, habs aber nicht ganz überrissen.
-
Dein Programm sollte nach jeder Betätigung der Entertaste die Ergebnisse für die Eingaben berechnen und ausgeben.
5 gefunden: <5> prim! 2 gefunden: <2> prim! 3 gefunden: <3> prim!
fgets liest bis (einschließlich) zu einem '\n' (der Entertaste) und beendet die Eingabe.
atol ist in <stdlib.h> deklariert. Musst du noch mit #include einbinden.
-
Richtig, daher hatte ich das "fgets" in eine while-Schleife gelegt, die ich irgendwann mit Ctrl + D beende.
Das Ziel ist ja, mehrere Zeilen eingeben zu können.Edit: Sprich, auf einmal eingeben zu können. Ich gebe dem Programm 3 Zeilen Input, und bekomme anschließend 3 Zeilen Output
-
thegti schrieb:
Richtig, daher hatte ich das "fgets" in eine while-Schleife gelegt, die ich irgendwann mit Ctrl + D beende.
Das Ziel ist ja, mehrere Zeilen eingeben zu können.Dann musst du entweder mehr Zeilen verwalten oder das Einlesen so ändern, das fgets hinter den bisherigen Eingaben abspeichert.
Allerdings soll sich dein Programm demnach anders verhalten, ob du nur einen Wert oder mehrere eingibst.
Ein Wert in der Zeile eingegeben: warten auf of EOF.
Mehr Werte in der Zeile eingegeben: gleich berechnen.
-
Ein Wert in der Zeile eingegeben: warten auf of EOF.
Mehr Werte in der Zeile eingegeben: gleich berechnen.Nicht unbedingt. Die Eingabe über eine Zeile ist nicht einmal verlangt, so das man das auch einfach über Neue Zeile + EOF beenden könnte.
Das mit dem Zwischenspeichern scheint das Problem zu sein. Er "vergisst" die Eingaben der ersten Zeilen.
Kannst du mir einen Tipp geben, wie man realisiert? Oder habe ich die While-Schleife nur falsch formuliert?Eventuell mit strcat die Strings zusammenfügen?
-
Grüß Gott,
vielleicht liege ich ja völlig falsch, aber ich hätte bei dieser interessanten Diskussion doch noch die eine oder andere Frage bzw. einige Anmerkungen.
1. Heißt die Aufgabenstellung wirklich "Kommandozeile"?
Die Kommandozeile kann man nicht einlesen. Die einzelnen Zahlen werden automatisch über die main-Parameter geliefert. Damit erübrigen sich alle Fragen zu fgets usw.
2. Die Prüfung auf prim ist nicht optimal
2.1
Außer der 2 selbst sind alle anderen geraden Zahlen nicht prim, d. h. eine gerades Argument kann also sofort ausgeschlossen werden2.2
Die Prüfschleife kann dann ab 3 in Schritten zu 2 hochlaufen, was also schon einmal mindestens die Hälfte aller Testzahlen einspart.2.3
Die Prüfschleife kann statt d/2 bereits bei sqrt(d) enden, weil alle passenden Faktoren dazu immer kleiner werden und somit bereits geprüft sind.