Daten aus CSV Datei mit ANS C lesen

#1
Hallo, ich bin relativ neu hier und noch nicht so fit in C. Ich bin auf ein Problem gestoßen, wobei mir bisher keiner weiterhelfen konnte. Ich hab auch gesehen, das ziemlich viel zu finden ist über Datei auslesen usw., aber wirklich weitergeholfen hat es mir nicht.

Zu meinem Problem: Ich muss in ANS C aus einer CSV Datei Werte lesen. Ich kenn jetzt den unterschied zwischen ANS C und "normal" C nicht wirklich. Ich hab auch schon ein Beispielprogramm bekommen und auch ausprobiert aber irgendwie funktioniert das ganze nicht richtig.

Dazu sei noch gesagt, das ganze wird in einem Programm von Siemens (WinCC V7.3) verarbeitet, deswegen auch ANS C. Und das Programmbeispiel ist auch von Siemens.

Ich bekomm meine gewünschte Datei geöffnet, nur wenn ich versuche irgendwas raus zu lesen, bekomm ich folgenden Fehler: general protection fault (Fehlermeldung vom WinCC). Der Compiler übersetzt alles wunderbar nur mit 3 Warnungen (Anhang).

Ich hoffe ihr könnt mir helfen... Vielen Dank schon einmal im vorraus
 

Anhänge

#2
Hi

bitte Code als Text reinkopieren, in [code=c]hier der code[/code]

Die Sprache C ist seit Erfindung nicht gleich geblieben, sondern wurde mehrmals erweitert/geändert (also nicht nur Compiler usw., sondern die Sprache selber, welche Symbole und Funktionen usw. es gibt).
Es gibt
  • das "Ur-C", wie es von Kernighan und Ritchie irgendwann vor 1980 erfunden wurde
  • C89 (1989, auch ANSI-C genannt)
  • C99 (1999)
  • und C11 (2011)
Die neueren Varianten sind für den Programmierer im Wesentlichen besser (weniger umständlich usw.), wenn es um neue Programme geht. Die älteren Varianten sind trotzdem noch wichtig,
  • wenn es um alte bestehende Programme geht (die sehr oft in den neueren Varianten auch richtig sind, aber nicht immer)
  • wenn man aus irgendeinem Grund keine neue Variante verwenden darf (Chef der die Neuerungen nicht lernen will und deshalb der ganzen Firma die Verwendung verbietet, oder Ähnliches...)
  • oder wenn man, wie du anscheinend, keinen passenden Compiler hat.
In C89 programmieren ist jedenfalls nicht lustig, wenn man C11 auch haben könnte. Aber wenns sein muss...

So, zum Fehler:
Bisher aufgefallen ist mir, dass du "\0" verwendest, was in C ein ganzer String bzw. der Pointer darauf ist. '\0' wie im Beispiel ist ein einzelner Buchstabe (bzw. Byte).

Und "Warnungen" von C-Compilern sind oft schlimmer als die ganzen Fehler. Immer versuchen, alle Warnungen loszuwerden, bzw. zu verstehen warum sie da ist.
 
#3
Vielen dank erst einmal für die schnelle Hilfe Sheel. Hier wie gewünscht der Code
C:
#include "apdefap.h"

int gscAction( void )
{
#define MaxLineLength 80

FILE *fpFile;
char *strTag, *strValue, *pTmp;
char buffer[MaxLineLength];
double dVal;
fpFile = fopen("c:\\Users\\Desktop\\Mappe1.csv", "r");
printf("C-Skript: lese Datei: Mappe1.csv\n");
if(fpFile !=NULL)
{
     while(fgets(buffer,MaxLineLength, fpFile))
     {
          strTag=buffer;
          pTmp = strchr(buffer,(int)';');
          *pTmp='\0';
          strValue=++pTmp;
          strValue[strlen(strValue)-1]='\0';

          pTmp=strchr(strValue,(int)',');
          if(pTmp !=NULL){
             *pTmp='.';
          }

          sscanf (strValue, "%lf", &dVal);
          //SetTagDouble(strTag,dVal);
          printf("%s Value: %lf\r\n", strTag, dVal);
     }
     fclose(fpFile);
} else{
printf("Error: File not found!\n");
}

return 0;
}
Ich hab das geändert mit den " und siehe da es funktioniert. Jetzt hab ich das Problem, dass meine Zahl praktisch gerundet oder abgeschnitten wird... Ich weiß nicht genau was da passiert. Und zwar macht das Programm aus der Zahl 1,1 eine 1.0000000 und das gleiche für 2,2 -> 2.00000.
 

Anhänge

#5
Hm ... wie schaut denn eine CSV-Zeile bei dir genau aus?

Zum fgets: Ein Einzelner aufruf von fgets liest eben eine Zeile aus der Datei fpFile, in den String buffer, aber maximal MaxLineLength Byte (weil buffer in dem Fall nicht mehr Platz hat; fgets weiß das aber nicht selber, deshalb auch übergeben).
fgets hat aber auch noch einen Returnwert (den man theoretisch mit "varname = fgets(...)" einer Variable zuweisen könnte), und zwar den ersten Parameter (buffer) wenn alles funktioniert hat (als Pointer-/Speicher-Adresse, wie Strings in C eben gehandhabt werden), oder 0 (das nie als Adresse verwendet wird) wenn die Datei schon zu Ende ist oder irgendein anderer Fehler passiert ist.
In dem Fall wird der Wert zwar keiner Variable zugewiesen, sondern als Schleifenbedingung im While verwendet - etwas seltsam (normal wären ja Vergleiche wie "a == b" oder "a < b", und keine einzelnen Werte), aber das kann man in C machen: 0 wird in dem Fall als falsch bzw. Schleife beenden verstanden, und alles andere als wahr bzw. weitermachen. Kann man zum Testen auch einfach so hinschreiben: while(1) wird ewig ausgeführt, und while(0) nie.
Also kurz, solange fgets nicht 0 ergibt, also solange die Datei nicht zu Ende ist...
 
Zuletzt bearbeitet:

cwriter

Erfahrenes Mitglied
#6
Und zwar macht das Programm aus der Zahl 1,1 eine 1.0000000 und das gleiche für 2,2 -> 2.00000.
1,1 ist auch keine Zahl - jedenfalls nicht in wissenschaftlicher Notation. Das wäre dann "1.1". Daher wird bei
C:
strchr(strValue, (int)',');
if(pTmp !=NULL){
             *pTmp='.';
          }
auch das Komma zu einem Punkt gewechselt. Aber nur einmal. Daher:
Hm ... wie schaut denn eine CSV-Zeile bei dir genau aus?
Die Casts von Zeichenliteralen auf int machen auch nicht wirklich viel Sinn - das ist nämlich Standard-Verhalten.

Und:
In C89 programmieren ist jedenfalls nicht lustig, wenn man C11 auch haben könnte. Aber wenns sein muss...
Hehe. Seuche...

Gruss
cwriter
 
#7
Also das mit dem Komma durch Punkt hab ich verstanden, aber das macht er scheinbar nicht richtig. Für den Beispielcode ist in der CSV Datei folgender Inhalt:
TagA; 1,1
TagB; 2,2
TagC; 3,3
usw.

Nochmals danke für die Erklärung, die hilft mir sehr weiter :D
 

cwriter

Erfahrenes Mitglied
#8
Für den Beispielcode ist in der CSV Datei folgender Inhalt:
Und den Code hast du so bekommen?
Seufz. Manche Leute müssen das Rad aber auch immer neu erfinden...
Der gesamte Code liesse sich sehr viel leichter schreiben (mit ein paar Konzessionen, versteht sich):
C:
setlocale(LC_NUMERIC, "de_DE");
while(fscanf(fpFile, "%[^;]; %lf\n", strName, &strValue) == 2) // strName entsprechend ein Stringbuffer (kein "reiner" Pointer)
{
    //Werte eingelesen
}
setlocale(LC_NUMERIC, ""); //Reset auf (System-)Standard
4 SLOC statt 8.
Einziger "Nachteil": Die Zahlen müssen jetzt mit Kommata statt Dezimalpunkten eingegeben werden. Allerdings wäre das Vermischen von Zahlenformaten ohnehin Blödsinn. Falls du dennoch erlauben wolltest, dass die Zahlenformate gemischt sein dürfen, kannst du statt %lf einfach %s einlesen und dort die Kommata durch Punkte ersetzen.
Übrigens ist das \r\n beim einen printf überflüssig - \n ist der Standard für Zeilenumbrüche (übrigens muss man nur dann auf \r\n achtgeben, wenn man die Datei binär öffnet - aber das ist eine andere Geschichte).

Also das mit dem Komma durch Punkt hab ich verstanden, aber das macht er scheinbar nicht richtig.
Was sagt der Debugger bzw. das printf-Debugging?

Gruss
cwriter

/EDIT: Die locales brachten mich auf die Idee, dass dein System schon Kommata erwartet... Was passiert, wenn du die Kommata nicht durch Punkte ersetzt?
 
Zuletzt bearbeitet:
#9
Vielen Dann cwriter. Ja das ganze ist in der Siemens Sofware WinCC (Visualisierungsprogramm für die Industrie) erstellt und somit ist der Code auch von Siemens.
Deswegen kann ich den Code nur ganz normal Debuggin (keine Ahnung was der printf Debugger ist) und da gibt er 0 Fehler 0 Warnungen aus.

Also in meinem bestimmten Anwendungsfall muss ich aus einer csv Datei 2 Werte zurück schreiben. Deswegen brauch ich die Werte als float. Die csv von mir sieht wie folgt aus:
Text;Text;Text;Text
Zeitpunkt; Zahlenwert; Zahlenwert; Zahlenwert
Zeitpunkt; Zahlenwert; Zahlenwert; zahlenwert
Zeitpunkt; Zahlenwert; Zahlenwert; zahlenwert
usw...

Ich muss jetzt noch wissen wie ich die erste Zeile überspringe... weil wenn ich versuche einen Text als Zahl zu verwenden, wird der sehr wahrscheinlich meckern .... Und dann bräuchte ich letztendlich aus der zweiten Zeile einen Wert und aus der letzten. Das würde ich dann über einen Zähler oder so machen, sprich gucken wann der in der 2 Zeile ist und den Wert wegschreiben und wenn er am Schluss angekommen ist, hat er ja die letzte Zeile....
 

cwriter

Erfahrenes Mitglied
#10
Deswegen kann ich den Code nur ganz normal Debuggin (keine Ahnung was der printf Debugger ist) und da gibt er 0 Fehler 0 Warnungen aus.
Das ist kein Debuggen, sondern ein Kompilieren. Vereinfacht gesagt sagt dir der Compiler, was er nicht versteht (weil Syntaxfehler bestehen). Debuggen beginnt dann, wenn man syntaktisch korrekten Code hat (der Compiler versteht, was du willst), aber die Semantik nicht stimmt (du falsch ausgedrückt hast, was du wolltest).
printf-Debugging heisst nur, dass du dir die Variablenwerte periodisch ausgeben lässt, um die Werte zu überprüfen (statt wie bei einem echten Debugger das Programm anzuhalten).

Also in meinem bestimmten Anwendungsfall muss ich aus einer csv Datei 2 Werte zurück schreiben. Deswegen brauch ich die Werte als float.
Nur zum Kopieren musst du Strings nicht in (double) floats verwandeln.

Die csv von mir sieht wie folgt aus:
Dann kann der Matchstring auf "%[^;]; %lf; %lf; %lf\n" geändert werden. Das ist ja gerade das Tolle an scanf: Es ist sehr flexibel (was auch seine Nachteile hat, siehe vararg-Diskussion).

Ja das ganze ist in der Siemens Sofware WinCC (Visualisierungsprogramm für die Industrie) erstellt und somit ist der Code auch von Siemens.
Verstehe ich nicht. WinCC ist ja kein Compiler? Wurde die CSV-Datei in WinCC erstellt? Das wäre unerheblich - CSV ist CSV.

Und wenn der Code von Siemens ist, dann würde mein Weltbild recht erschüttert...

Ich muss jetzt noch wissen wie ich die erste Zeile überspringe...
Wenn du die Spaltennamen nicht kennen willst, ja.
Möglichkeiten sind fgets() und scanf("%*[^\n]"), wobei das Asterisk bedeutet, dass man das Gelesene nicht speichern will.

weil wenn ich versuche einen Text als Zahl zu verwenden, wird der sehr wahrscheinlich meckern ....
Nö. Wahrscheinlich wird es eher Undefined Behavior sein (bzw. der Wert wird nicht in deine Variable eingetragen, und da du diese nicht definierst, kann irgendwas in der Variable stehen).

Und dann bräuchte ich letztendlich aus der zweiten Zeile einen Wert und aus der letzten.
Und aus dem Rest nix? Dann gäbe es wesentlich schnellere Möglichkeiten als mit einem Zähler (fseek() und Konsorten).

Das würde ich dann über einen Zähler oder so machen, sprich gucken wann der in der 2 Zeile ist und den Wert wegschreiben und wenn er am Schluss angekommen ist, hat er ja die letzte Zeile....
Ja, das würde gehen.

Gruss
cwriter
 
#11
Also sowohl die csv als auch der c Code wird in WinCC erstellt und verarbeitet. Das ist alles nur ein Umweg den ich gegen muss, weil Siemens das gerne kompliziert macht (langjährige Erfahrung).

Ich hab eigentlich im WinCC eine Tabelle in der Werte aus einer Datenbank stehen. Jetzt ist die Tabelle variabel d.h. es kann irgendeine Zeitspanne ausgewählt werden und ich muss dann von dieser Zeitspanne den ersten und den letzten Wert raus suchen, um damit weiter zu rechnen. Jetzt ist das aber so, dass ich nicht auf die Datenbanken zugreifen kann, weil diese verschlüsselt sind. Deswegen wurde mir von Siemens geraten, das über einen Export Import zu machen :D... also erst Tabelle in csv exportieren und direkt wieder zu importieren.

Export bekomm ich hin, das ist nur ein Klick, aber bei dem Import hapert es.

Die zwei Werte die ich praktisch raus schreiben müssen dringend float sein, weil ich sonst im weiteren Verarbeitungsschritt Probleme habe bzw. nichts damit anfangen kann.

Aber vielen vielen Dank, ihr habt mir sehr weitergeholfen. Ich Probier das ganze aus wenn ich wieder zu Hause bin (nächste Woche) und berichte dann.
 
#12
Hallo cwriter,
was meinst du damit genau? Ich bin immer noch unsicher was ich jetzt genau machen soll? Soll ich das fgets durch fscanf austauschen und bleibt der mittlere Teil erhalten:
C:
          strTag=buffer;
          pTmp = strchr(buffer,(int)';');
          *pTmp='\0';
          strValue=++pTmp;
          strValue[strlen(strValue)-1]='\0';

          pTmp=strchr(strValue,(int)',');
          if(pTmp !=NULL){
             *pTmp='.';
Mit fgets hol ich mir ja jede Zeile nach einander. Buffer ist die maximale Länge die ich mit übernehme (in dem Fall 80, hab ich ja bei MaxLineLength definiert). das übergebe ich praktisch strTag. Aber was ab
C:
pTmp=strchr(buffer,(int)';');
versteh ich nicht mehr wirklich. Ich denk da wird der ganze String (Ganze Zeile) aufgetrennt und zwar immer bei dem ';' Simikolon oder?
das *pTmp='\0'; damit setzte ich am ende noch die \0, damit der weiß das hier ende ist?
dann wird pTmp erst um eins erhöht und in strValue geschrieben (
C:
 strValue=++pTmp;
)?
C:
strValue[strlen(strValue)-1]='\0';
da bin ich wieder voll raus.
und hier:
C:
    pTmp=strchr(strValue,(int)',');
          if(pTmp !=NULL){
             *pTmp='.';
ersetzt er einfach das Komma durch einen Punkt.

in meinem strValue steht jetzt so gesehen jede Zelle von mir und wird ständig wieder überschrieben?

Und wo bzw. wann wird da strTag beschrieben?
 
Zuletzt bearbeitet:

cwriter

Erfahrenes Mitglied
#13
Source Lines Of Code.
(Der Code ist syntaktisch aufgeräumter, aber semantisch äquivalent).

Soll ich das fgets durch fscanf austauschen und bleibt der mittlere Teil erhalten
fscanf ersetzt fgets und sscanf (nur in Verbindung mit setlocale() ). Der Inhalt der Schleife bleibt damit nicht erhalten.

versteh ich nicht mehr wirklich. Ich denk da wird der ganze String (Ganze Zeile) aufgetrennt und zwar immer bei dem ';' Simikolon oder?
Nein, das wäre die Funktionsweise von strtok().
strchr könnte so implementiert sein:
C:
const char* strchr(const char* str, const char* delim)
{
for(const char* it = str; it < str + strlen(str); it++)
for(const char* it2 = delim; it2 < delim + strlen(delim); it2++)
if(*it == *it2) return it;
return (const char*)0;
}
Es gibt also die Position des ersten Zeichens in Delim innerhalb des Strings zurück. Der String wird aber NICHT verändert.
das *pTmp='\0'; damit setzte ich am ende noch die \0, damit der weiß das hier ende ist?
Nein, du ersetzt das Semikolon mit 0 (strtok()-Behavior).
dann wird pTmp erst um eins erhöht und in strValue geschrieben
Ja. pTmp zeigt zuerst auf den nächsten Teilstring, dann wird erhöht.

Die Länge des 2. Strings wird um 1 gekürzt.

in meinem strValue steht jetzt so gesehen jede Zelle von mir und wird ständig wieder überschrieben?
Überschrieben.

Gruss
cwriter
 
#14
Also ich hab mal jetzt jede Zeile von mir Ausgegeben und da hab ich folgendes raus:
C:
#include "apdefap.h"

int gscAction( void )
{
#define MaxLineLength 80

FILE *fpFile;
char *strTag, *strValue, *pTmp;
char buffer[MaxLineLength];
double dVal, dVal2, dVal3;
int i=0;

fpFile = fopen("c:\\Users\\Desktop\\Mappe1.csv","r");
printf("C-Skript: lese Datei: Mappe1.csv\n");
if(fpFile !=NULL)
{
     while(fgets(buffer,MaxLineLength, fpFile))
     {
          i++;
          strTag=buffer;
printf("strTag1: %s   Buffer: %s\n", strTag, buffer);
          pTmp = strchr(buffer,(int)';');
printf("pTmp1: %s\n", pTmp);
          *pTmp='\0';
printf("pTmp2: %s\n", pTmp);
          strValue=++pTmp;
printf("strValue1: %s\n", strValue);
          strValue[strlen(strValue)-1]='\0';
printf("strValue2: %s\n", strValue);
          pTmp=strchr(strValue,(int)',');
printf("pTmp3: %s\n", pTmp);
          if(pTmp !=NULL){
             *pTmp='.';
printf("pTmp4: %s\n", pTmp);
          }
          sscanf (strValue, "%lf", &dVal);
          //SetTagDouble(strTag,dVal);
          printf("%s Value: %lf pTmp: %s  strValue: %s \r\n", strTag, dVal, pTmp, strValue);
printf("------------------------------------------Zeile: %d--------------------------------------------\n", i);
     }
     fclose(fpFile);
} else{
printf("Error: File not found!\n");
}

return 0;
}
Im Anhang ist die Ausgabedatei. Wie man sieht, nimmer der Code die Nachkommastelle nicht mit. also er nimmt die Zahl vor dem Komma, ersetzt das Komma durch den Punkt, aber vernachlässigt die Nachkommastelle. Ich hab auch mal jetzt die csv Datei um eine Spalte ergänzt.

und cwriter: wenn ich jetzt dieses strtok() von dir verwende, wird die Zeile ja immer bei dem Simikolon getrennt oder? Das heißt ich kann die ganze Zeile direkt so nehmen, dieses strtok() anwenden und direkt in Variablen speichern, sprich erste ist %s und dan %lf und noch ein %lf. Ich kenn ja den aufbau meiner csv. Die Spalten bleiben immer gleich nur die Anzahl der Zeilen variiert, aber das ist ja bei der Schleife egal.
 

Anhänge

Zuletzt bearbeitet:
#15
  • while(fscanf(fpFile, "%[^;]; %lf\n", strName, &strValue) == 2) // strName entsprechend ein Stringbuffer (kein "reiner" Pointer)
  • {
  • //Werte eingelesen
  • }
setlocale(LC_NUMERIC, ""); //Reset auf (System-)Standard
das wär praktisch der Code den ich verwenden müsste oder? Aber was meinst du mit //Werte eingelesen? Da muss ich doch nichts merh machen, weil ich oben doch schon in strName und strValue schreibe oder nicht?
 
#16
Also ich hab mal setlocale verwendet aber scheinbar nicht richtig. Sorry nochmal dafür das ich etwas länger brauche um das zu verstehen, aber wie gesagt, programmier eher selten mit C bzw. programmiere eigentlich garnicht.

C:
#include "apdefap.h"

int gscAction( void )
{

#define MaxLineLength 80

FILE *fpFile;
char *strTag, *strValue, *pTmp;
char buffer[MaxLineLength];
double dVal, dVal2, dVal3;
int i=0;

fpFile = fopen("c:\\Users\\Desktop\\Mappe1.csv","r");
printf("C-Skript: lese Datei: Mappe1.csv\n");
if(fpFile !=NULL)
{
setlocale(LC_NUMERIC, "de_DE");
while(fscanf(fpFile, "%[^;]; %lf; lf\n", strTag, &dVal, &dVal2)==2)
{
//Werte eingelesen?
}
setlocale(LC_NUMERIC, "");

          }

          sscanf (strValue, "%lf", &dVal);
          //SetTagDouble(strTag,dVal);
          printf("%s Value: %lf pTmp: %s  strValue: %s  Value2: %lf \r\n", strTag, dVal, pTmp, strValue, dVal2);

printf("------------------------------------------Zeile: %d--------------------------------------------\n", i);
     
     fclose(fpFile);

else{
printf("Error: File not found!\n");
}

return 0;
}
Folgende Fehlermeldungen beim Compiling:
line 18: error (003f) : undefined identifier 'setlocale'
line 18: error (003f) : undefined identifier 'LC_NUMERIC'
line 18: error (0066) : 'setlocale' is not a function
line 23: error (0066) : 'setlocale' is not a function
line 35: error (0040) : <ident> expected before 'else'
 

cwriter

Erfahrenes Mitglied
#17
Im Anhang ist die Ausgabedatei. Wie man sieht, nimmer der Code die Nachkommastelle nicht mit.
Naja. Du hast ja auch einen Wert "zu viel": "1.2;1,1" ist ein unbequemes Datenformat.

Folgende Fehlermeldungen beim Compiling:
C:
#include <locale.h>
Da muss ich doch nichts merh machen, weil ich oben doch schon in strName und strValue schreibe oder nicht?
Partizip. Du musst die Werte nicht mehr einlesen, wohl doch aber verarbeiten, oder? Strvalue solltest du auch nicht verwenden... Wenn du den Code ein bisschen aufräumst, sollte es klarer werden.

und cwriter: wenn ich jetzt dieses strtok() von dir verwende, wird die Zeile ja immer bei dem Simikolon getrennt oder?
strtok() ist nicht threadsafe. Aber generell würde strtok einiges vereinfachen, ja. Du kannst es aber auch selbst threadsafe machen (siehe strtok_s() von Microsoft).
Ich habe aber ein Beispiel für strchr und nicht strtok gegeben.

Das heißt ich kann die ganze Zeile direkt so nehmen, dieses strtok() anwenden und direkt in Variablen speichern, sprich erste ist %s und dan %lf und noch ein %lf. Ich kenn ja den aufbau meiner csv. Die Spalten bleiben immer gleich nur die Anzahl der Zeilen variiert, aber das ist ja bei der Schleife egal.
Gewissermassen. Dann kannst du aber auch gleich *scanf() verwenden, was ein bisschen schöner (und mit Posix-Erweiterungen ("Halbstandard") sogar um einiges mächtiger) ist.

Gruss
cwriter
 
#18
Vielen Dank cwriter, bin schon sehr weit gekommen
Mein Code sieht wie folgt aus:
C:
#include "apdefap.h"

int gscAction( void )
{
#define MaxLineLength 80
FILE *fpFile;
char *strTag, *strValue, *pTmp;
char buffer[MaxLineLength];
char delimiter[]=";";
double dVal, dVal2, dVal3;
int i=0, j=0;
fpFile = fopen("C:\\Users\\18.01.2017 12_15.csv","r");
printf("C-Skript: lese Datei: Mappe1.csv\n");
if(fpFile !=NULL)
{
     while(fgets(buffer,MaxLineLength, fpFile))
     {
        
          strTag=buffer;
printf("strTag1: %s   Buffer: %s\n", strTag, buffer);
pTmp = strtok(strTag, delimiter);
printf("strTag2: %s    pTmp1: %s\n", strTag, pTmp);

//printf("dVal: %lf\n", dVal);
while(pTmp != NULL) {
i++;
printf("strTag3: %s      pTmp2: %s\n", strTag, pTmp);
dVal=atof(pTmp);
printf("dVal: %lf\n", dVal);
if(i==2)
{dVal2=dVal;}
if(i==3)
{dVal3=dVal;}

SetTagDouble("wert4", dVal2); //Wert rausschreiben
SetTagDouble("wert5", dVal3); //Wert rausschreiben

//nächsten Abschnitt erstellen
pTmp=strtok(NULL, delimiter);
printf("strTag4. %s      pTmp3: %s\n", strTag, pTmp);
//printf("dVal3: %lf\n", dVal3);
}
j++;

printf("------------------------------------------Zeile: %d     %d--------------------------------------------\n", i, j);
     }
     fclose(fpFile);
} else{
printf("Error: File not found!\n");
}
return 0;

}
Meine Ausgabe ist auch im Anhang zu sehen.
Also ich bekomm jetzt die einzelnen Werte raus gelesen, funktioniert alles wunderbar. Muss dann nur noch irgendwas finden wie ich die Werte rausschreibe die ich brauche (Werte aus zweiter Zeile und Wert aus letzter Zeile). Aber das bekomm ich schon hin, das wird nicht das Problem sein.

Jetzt hab ich nur noch ein Problem. Wenn ich die csv Datei in Excel öffne, hab ich zwei Varianten einmal:
Spalte1;Zeile1: wert1
Spalte2;Zeile1: wert2
Spalte3;Zeile1: wert3
Spalte1;Zeile2: wert4
Spalte2;Zeile2: wert5
Spalte3;Zeile2: wert6
Bei dieser Variante funktioniert das C-Skript.

Zweite Variante:
Spalte1;Zeile1: wert1;wert2;wert3
Spalte1;Zeile2: wert4;wert5;wert6
Spalte1;Zeile3: wert7;wert8;wert9

Bei dieser Variante funktioniert das Skript nicht. Ich muss erst die Datei in Excel öffnen und ';' als Trennzeichen eintragen, damit er die Felder trennt und neu speichern. Erst dann wird die Datei von dem Skript richtig verarbeitet. Da gibts doch sicher eine elegantere Lösung oder?
 

Anhänge

#19
Das Problem hat sich auch erledigt :D haha. Ich muss einfach die csv Datei als UTF-8 Dateiformat speichern, dann klappt alles wunderbar.
vielen Dank nochmal für die hilfe