Hallo leute!
Versuche seit einigen Stunden vergeblich zu einer Lösung meines Problems
zu kommen. Aber was ich auch probiert habe, es funktioniert nicht.
Ich hoffe von euch kann mir wer helfen?
Hier mein Problem:
Ich lese eine Datei zeilenweise ein, und speichere jede zeile immer in
ein Array. in dieser Datei werden allerdings alle Kommazahlen mit einem
"," geschrieben. Damit das C-Programm diese als Kommazahlen erkennt muss
ich nun alle "," durch "." ersetzen.
sollte das nicht so funktionieren:
char Line[120] = "eingelesene,Zeile";
Line = Line.Replace("," , ".");
Bei mir funktioniert das jedenfalls nicht könnte mir da jemand
weiterhelfen und mir eine andere Methode zeigen oder mich auf meine/n
Fehler hinweisen.
Bitte berücksichtigt dass ich noch ein blutiger Anfänger bin was
C-Programmierung angeht.
mfg. Reini
Bittesehr.
> Ich lese eine Datei zeilenweise ein, und speichere jede zeile immer> in ein Array.
Musst du nicht, Kannst auch nen ret = fread(...) machen, da stehen dann
die Newlines als CR, LF oder CRLF drin.
Zum Ersetzen von Zeichen ist das völlig unerheblich, und du bist damit
schneller.
Hallo Reini,
verwechselst du gerade C und C#?
Was du da vor hast, geht nicht. Line ist ein Array aus chars und kennt
daher keine Methode "Replace".
Hier eine kleine Funktion, mit der du das machen kannst:
Reinhard Leitgeb schrieb:> sollte das nicht so funktionieren:>> char Line[120] = "eingelesene,Zeile";> Line = Line.Replace("," , ".");
Das ist kein C, sondern C++ oder eine andere objektorientierte Variante.
In Standard C würdest du eine Funktion selbst schreiben (so wie
Thorsten) und ggf. Funktionen aus der Standardbibliothek /string.h/
verwenden.
> Bei mir funktioniert das jedenfalls nicht könnte mir da jemand> weiterhelfen und mir eine andere Methode zeigen oder mich auf meine/n> Fehler hinweisen.
Was sagt denn dein Compiler zu deinem Code???
> Bitte berücksichtigt dass ich noch ein blutiger Anfänger bin was> C-Programmierung angeht.
Kein Problem, wir haben alle mal klein angefangen. Was ich aber sehr
empfehlen kann: Beginne mal mit einem Buch über C, wie dem Klassiker von
K&R:
http://en.wikipedia.org/wiki/The_C_Programming_Language
MFG
Helfer
Du liesst deine Zeilen warscheinlich mit fscanf(...) ein. Bei einigen
wenigen Daten ist das durchaus ok.
Ich habe einen XML Reader/Interpreter/Codegenerator geschrieben, und dem
gleich mehrere Streams verpasst. Im Reader selbst brauche ich zwar alles
zeichenweise, aber meine interne GetNextChar() stuppst einen Loader an,
der sich die nächsten 5MB des Files automatisch reinzieht. Enormer
Performancegewinn.
Hier geht es aber auch um 3-20MB/XML File, bzw. >500MB insgesamt.
Genauso verhält es sich mit meiner Ausgabe in Files. Ich dachte, dass
Windows das Streaming von Files bereits selbst macht, aber das scheint
nicht der Fall zu sein. Vielleicht kann man das auch irgendwie
aktivieren, oder andere Funktionen nutzen, ka, ich bin bei fread/fwrite
geblieben und mache die Bufferung selbst. In/Output "vernünftig" zu
buffern bringt nen enormen Performanceschub.
>Was sagt denn dein Compiler zu deinem Code???
Ich bekomme folgende Fehlermeldung:
error C2228: left of '.Replace' must have class/struct/union type
Wisst ihr zufällig wie ich dieses problem behandeln soll?
Random ... schrieb:> Du liesst deine Zeilen warscheinlich mit fscanf(...) ein.
Warum sollte man das tun? Mit fgets() kann man problemlos zeilenweise
le_s_en (ein s).
den Aufwand kannst Du DIr sparen.
google mal unter 'c++ culture' , da wird Dir gezeigt wie
amerikanische Zahlen ( mit . halt ) in einem 'deutschen' Programm
eingelesen werden können , das deutsche Programm verlangt hat ',' .
Rufus Τ. Firefly schrieb:> Random ... schrieb:>> Du liesst deine Zeilen warscheinlich mit fscanf(...) ein.>> Warum sollte man das tun? Mit fgets() kann man problemlos zeilenweise> le_s_en (ein s).Reinhard Leitgeb schrieb:> Bitte berücksichtigt dass ich noch ein blutiger Anfänger bin was> C-Programmierung angeht.
deshalb :-)
printf und scanf sind idR. die ersten IO Funktionen, die man beim Lernen
von C "zu Gesicht" bekommt.
Oder halt cin/cout, wobei ich mich mit den Dingern nie anfreunden
konnte. Die sind ja auch C++, wobei C/C++ vielfach
durcheinanderzermischt wird...
Ich bevorzuge fread/fwrite BIN/ASCII, je nach Bedarf :-)
Martin schrieb:> den Aufwand kannst Du DIr sparen.>> google mal unter 'c++ culture' , da wird Dir gezeigt wie> amerikanische Zahlen ( mit . halt ) in einem 'deutschen' Programm> eingelesen werden können , das deutsche Programm verlangt hat ',' .
Du kannst das auch mit Klassen in C++ realisieren, z.B. mit CString
unter MS VC. CString bringt dann glaub ich auch so replacer mit. Benutze
ich aber nicht, ist mir alles zu langsam und zu viel Overhead :-)
Reinhard Leitgeb schrieb:> Wisst ihr zufällig wie ich dieses problem behandeln soll?
So wie Random ... in seinem ersten Beitrag geschrieben hat: Schreib
Replace als Funktion, bei der der zu bearbeitende String als Argument
übergeben wird.
Übrigens kannst du dir auch mal die Funktion setlocale der C-Standard-
bibliothek anschauen. Damit kannst du das Verhalten von scanf,
printf usw. landesspezifisch einstellen. Das ist vor allem dann
sinnvoll, wenn die Datei mit den Kommata als Dezimaltrennzeichen auf dem
gleichen PC erstellt wird, auf dem auch dein C-Programm läuft. Mit
1
setlocale(LC_ALL,"");
wird das vom Benutzer als Default definierte Locale (in Windows Länder-
einstellungen), also u.a. auch das richtige Dezimaltrennzeichen für Ein-
und Ausgaben verwendet. Auch das Datumsformat, die Sortierreihenfolge
von Strings uvw. werden davon beeinflusst.
Sollen allerdings nur beim Einlesen von Zahlen (nicht bei der Ausgabe)
Kommata als Dezimaltrennzeichen verwendet werden, und ist sicherge-
stellt, dass wirklich jedes in der Datei vorkommende Komma ein Dezi-
maltrennzeichen ist, ist die Konvertierung mit der /Replace/-Funktion
praktischer, weil sie unabhängig vom eingestellten Locale funktioniert
und sowohl Kommate als auch Punkte zulässt.
Random ... schrieb:> Im Reader selbst brauche ich zwar alles zeichenweise, aber meine> interne GetNextChar() stuppst einen Loader an, der sich die nächsten> 5MB des Files automatisch reinzieht.
Das ist eigentlich genau das, was die Funktionen fread, fscanf, fgetc
usw. sowieso schon tun, deswegen werden sie auch von "buffered I/O
functions" genannt. Evtl. musst du mit setvbuf die Puffergröße und
-charakteristik deinen Wünschen anpassen.
Schau Dir an was deine Umgebung an "Regular
Expressions"-Funktionalitäten im Angebot hat, das ist eines der
Werkzeuge die man kennen sollte wenn man viel mit Textdaten hantieren
muss. Sonst gibt es auch noch eine freie Bibliothek namens PCRE...
Yalu X. schrieb:> Das ist eigentlich genau das, was die Funktionen fread, fscanf, fgetc> usw. sowieso schon tun, deswegen werden sie auch von "buffered I/O> functions" genannt. Evtl. musst du mit setvbuf die Puffergröße und> -charakteristik deinen Wünschen anpassen.
Stimmt, da war was :-)
Da hab ich mich beim retargeting der ARM <stdio> auf ein eigenes
virtuelles Filesystem mal mit rumgeärgert **g** Beim retarget-Ziel
"UARTn" soll der ja nicht buffern, sondern jedes Zeichen rausschieben
ans Terminal.
Trotzdem bleib ich bei meinem eigenen Buffer, der ist "dichter dran" und
einfacher anzupassen :-)
Reinhard Leitgeb schrieb:> Ich bekomme folgende Fehlermeldung:>> error C2228: left of '.Replace' must have class/struct/union type>> Wisst ihr zufällig wie ich dieses problem behandeln soll?
Indem du dir überlegst, dass es in C keine Klassen und daher auch keine
Methoden innerhalb von Klassen gibt. Etwas von der Form a.b (welches
keine Gleitkommazahl ist), kann in C nur eine Struktur sein. a ist der
Variablenname der Struktur und b ist der Name der gewünschten Komponente
der Struktur.
Hast du eine Struktur?
Nein! Du hast ein Array. Also kann die Syntax Line.Replace schon mal
nicht richtig sein.
Wie du dieses Problem behandeln sollst?
Indem du jetzt endlich einmal anfängst ein C-Buch von vorne bis hinten
durchzuackern! Das ist ja nicht das erste mal, dass du hier eklatantes
Nichwissen von absoluten Grundlagen zeigst und es wurde dir schon oft
genug nahegelegt, dass du mit dem Lesen eines Buches anfangen musst. Tu
es endlich! Du wirst aus deinem Viertelwissen nie herauskommen, wenn du
nicht anfängst, dir die Sprache, ihre Möglichkeiten und ihre Syntax
systematisch beizubringen. Durch immer wieder Aufschnappen von Brocken
in Foren wird das nichts werden. Das hat noch bei keinem Neuling
funktioniert und bei dir funktioniert es erst recht nicht.
> Bitte berücksichtigt dass ich noch ein blutiger Anfänger> bin was C-Programmierung angeht.
Eine Zeitlang kriegst du diesen Bonus. Aber irgendwann ist schluss.
Irgendwann heißt es dann: Warum tust du eigentlich nicht, was dir schon
viele nahegelegt haben?
Wer einmal als Flachlandtiroler mit Sandalen in die Berge geht und von
der Bergwacht gerettet werden muss, hat einen gut. Wer es aber ständig
tut, muss damit rechnen, dass ihn dieses Verhalten irgendwann als
"resistenter Wiederholungstäter" teuer kommt.
Das andere, was ich aus der Fehlermeldung herauslesen kann: Du
verwendest einen C++ Compiler. Man kann einen C++ Compiler als eine Art
'besseren C-Compiler' benutzen, wenn man sich bewusst ist, dass es im
'C-Teil' von C++ Unterschiede zu C gibt. Dessen ist man sich aber nur
dann bewusst, wenn man C auch wirklich beherrscht. Daher ist es für
Anfänger allemal besser, erst einmal mit einem richtigen C-Compiler an
die Sache heranzugehen und nicht von einem C++ Compiler nur den 'C-Teil'
zu benutzen.
http://blog.plover.com/2006/09/11/ ziemlicher AHA-Effekt was C vs C++
angeht.
...
Ein anderes Gedankenspiel welches hilft C-Arrays zu verstehen: Warum
sind a[i] und i[a] in C identisch?
>a[i] und i[a] in C identisch?
(ich hab ja GOTT SEI DANK NIX mit C zu tun..)
was erwartest für Antwort:
weil a und i einfach zusammengezählt werden
stimmt aber vermutlich nur bei byte und char array...
bei einem array mit Integern wird es nicht funktionieren?!?
Robert L. schrieb:> stimmt aber vermutlich nur bei byte und char array...
nein , denn i wird implizit zu (*)(i*sizeof(*a)) erweitert.
Danach werden die beiden Zeiger addiert.
Volker
und deshalb kann ich a und i vertauschen?
das ist a ziemlich unwahrscheinlich weil IMHO der pointer auf das array
z.b. mit z.B. 4 multipliziert werden würde und man damit "irgendwo"
ist..
und B
>sizeof(*a)
nachdem i ja "alles mögliche" sein kann (byte/word/int usw.)
wird, wenn man a und i vertauscht aus sizeof(*a) (also sizeof(*i) wird)
ja entweder 1, 2, 4 ...
man multipliziert also entweder mit 1, 2 oder 4
was nicht stimmen kann
würd mich jetzt also WIRKLICH interessieren, was ich da jetzt übersehen
hab..
http://manderc.manderby.com/operators/arrayelementoperator/index.php
Vermutlich hat der Compiler intelligent genug zu sein um nachzuhalten
welcher Teil des Ausdrucks ein Pointer und welcher ein Integer ist. Bei
einer Pointeraddition addiert man ja auch nicht zwei Pointer sondern
Pointer und Integer.
Auch gut fürs C-Verständnis: Die Aufgabe aus dem K&R, eine Funktion zu
schreiben die messen kann wieviel Byte ein Integertyp nun wirklich hat
(IIRC nach dem 4. oder 5. Kapitel in der 2. Ausgabe).
Robert L. schrieb:> kann mir das jetzt jemand erklären oder nicht?
In C ist -entgegen anderslautender Behauptungen- nicht alles erlaubt.
Erlaubt ist beispielsweise int+int, char+int, char+char etc..
Nicht erlaubt ist beispielsweise Zeiger+Zeiger.
Dagegen wieder erlaubt ist Zeiger+int ebenso wie int+Zeiger (wegen der
Kommutativität der Addition beide Versionen).
Dabei ist festgelegt, daß erstens ein Zeiger rauskommt, und zweitens
das Ergebnis sich ergibt, indem der int-Operand mit der Größe
dessen multipliziert wird, worauf der Zeiger zeigt, erhöht um den Wert
des Zeigers.
Und das eben unabhängig davon, ob der Zeiger vorne steht oder die int.
Damit ist geregelt, was Zeiger+int bewirkt, also ist damit auch klar,
was *(Zeiger+int) macht, ebenso wie das gleichwertige *(int+Zeiger).
Weiterhin ist eines[anderes] nur eine andere Schreibweise für
*(eines+anderes).
Also steht zeiger[int] für *(zeiger+int) und int[zeiger] steht für
*(int+zeiger).
Beides ist nach obiger Regel aber gleichwertig.
hey super
habs verstanden
wenigstens einer der sich in c auskennt, und nicht nur so tut als ob ;-)
>indem der int-Operand mit der Größe>dessen multipliziert wird, worauf der Zeiger zeigt,
DAS war das was ich nicht wusste...
Moin.
Hab das hier grad mal ein wenig überflogen.
Nur nochmal als kleine ergänzung:
Das "Zeiger + Zeiger" nicht erlaubt ist, ist so nicht ganz richtig.
Es gibt einfach keine praktisch sinnvolle Anwendung, weshalb man 2
Zeiger addieren sollte. Deswegen wurde dies nicht implementiert.
und zu der ursprünglichen Frage / dem Ursprünglichen Problem:
"," durch "." ersetzen....
Gehe Das Array Zeichen für Zeichen durch und schaue ob das Zeichen
ein"," ist. Wenn ja, dann ersetze "," durch ".", wenn nicht, lass das
zeichen in ruhe.
Ich denke mal, das das Problem schon gelöst ist, trotzdem nochmal
standard
C-Code dazu:
(Dies ist nur ein Beispiel mit einem vordefinierten Array! Der Code ist
für ein Win32-Konsolenprojekt ausgelegt!)
Klaus Wachtler schrieb:> Dabei ist festgelegt, daß erstens ein Zeiger rauskommt, und zweitens> das Ergebnis sich ergibt, indem der int-Operand mit der Größe> dessen multipliziert wird, worauf der Zeiger zeigt, erhöht um den Wert> des Zeigers.
Das ist ja auch mit der Hauptgrund, warum es in C überhaupt Zeigertypen
gibt.
Chocco schrieb:> Das "Zeiger + Zeiger" nicht erlaubt ist, ist so nicht ganz richtig.
Doch, das ist richtig. Es ergibt auch keinen Sinn, weil ein Zeiger immer
eine absolute Adresse darstellt. Das ist etwa so, als wolle man den
3.5.2010 und den 24.10.2011 addieren. Man kann Tage zu einem Datum
hinzuzählen, dann kommt man bei einem neuen Datum heraus, aber man kann
kein anderes Datum dazuaddieren, weil das keinen Sinn ergibt. Man kann
aber umgekehrt von einem Datum ein anderes abziehen und bekommt dann
eine Differenz in Tagen. Und genau nach dem selben Prinzip verhalten
sich auch Zeiger.
> Es gibt einfach keine praktisch sinnvolle Anwendung, weshalb man 2> Zeiger addieren sollte. Deswegen wurde dies nicht implementiert.
Ähm, die Konseuqenz aus dieser Aussage wäre dann doch,
> Das "Zeiger + Zeiger" nicht erlaubt ist
oder?
auch wenn es "nur" ein Beispiel ist, aber DAS macht man nicht:
for( i=0 ; i<23
(das 23 mein ich)
(IMHO sind in "good old" C auch eher 0 terminierte "Strings" üblich
(und keine array)
Außerdem leben wird im "Zeitalter" von unicode
da ist das Ganze nicht mehr so trivial..
Das Beispiel ist eh ziemlich schrullig.
Es sind ja nur 22 Byte Nutzdaten im String, und die abschließende 0.
Trotzdem werden 23 Zeichen geprüft.
Und wie
> standard C-Code
und
> #include <windows.h>
...
> Win32-Konsolenprojekt
...
> system("pause");
zusammengehen, weiß ich auch nicht so recht.
Entschuldigt bitte, aber das, was ich da oben an Code gepostet habe
wurde MIR, so wie es da steht, als Standard C-Code beigebracht! :(
Klärt mich doch bitte auf, wenn dies so nicht der wahrheit entsprechen
sollte.
Und zu den Zeigern: Meine Aussage war falsch formuliert, und dafür
entschuldige ich mich viel mals. Es sollte eigentlich nur eine ergänzung
sein, warum Zeiger+Zeiger nicht erlaubt / möglich ist.
Entschludigt bitte mein unwissen, ich kann nichts dafür, das in
Lehranstalten nur noch die halbe wahrheit erzählt wird. :(
Chocco schrieb:> Entschuldigt bitte, aber das, was ich da oben an Code gepostet habe> wurde MIR, so wie es da steht, als Standard C-Code beigebracht! :(
Standard ist im Zweifelsfall, was im K&R oder im entsprechenen ISO-Blatt
steht, je nach C-Version.
(Es sei denn, man folgt dem, was Microsoft als Standard gern hätte, dann
ist das natürlich was anderes.)
Dazu gehört schon mal kein windows.h.
Weiterhin ist zwar system() eine Standardfunktion, aber was man an
system() als Kommando übergeben kann und wie das dann funktioniert, ist
schwer vom Betriebssystem bzw. der Umgebung des Programms abhängig.
PAUSE geht halt nur unter Windows, auf einem anderen System braucht man
auch den ganzen Plunder mit system an der Stelle nicht.
Abgesehen davon, daß es mit Kanonen auf Spatzen geschossen ist, wenn man
einen Kommandointerpreter startet, den ein Kommando ausführen lässt, was
dann wieder auf eine Eingabe wartet, nur um das eigenen Programmende zu
verzögern, bis der Benutzer Return tippt. Ein schnödes getchar() würde
auf jedem System funktionieren (deklariert in stdio.h auf jedem System).
Chocco schrieb:> Entschludigt bitte mein unwissen, ich kann nichts dafür, das in> Lehranstalten nur noch die halbe wahrheit erzählt wird. :(
Du kannst nur etwas dafür, wenn du es unreflektiert weiter erzählst :-)
Den Rest der Wahrheit muß man immer selbst besorgen...