/*******************************************************************************
* datenfilter.c *
* Dieses Programm liest Datensätze zweier Maschinen M1 und M2 aus einer Datei *
* und generiert daraus ein geräteunabhängiges, drittes Format, welches sich *
* zum direkten Ansehen am Bildschirm eignet. Nicht syntax-konforme Zeilen *
* werden in eine Fehlderdatei geschrieben *
* @version $Id: datenfilter.c,v 1.1 2005/12/19 22:20:32 mk Exp $ *
* @author Maximilian Kellner *
*******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define CONFIRMEXIT "\nPress any key to exit ..."
#define MAXFILENAME 255
#define MAXDIGITS 128
#define KELVIN_CELSIUS -273;
#define ERRORFILE "errors.txt"
#define MDFILE "merrs.txt"
/* Datenstruktur fuer das dritte unabhängige Format
* NAME: Zusätzlicher Wert zur Unterscheidung der Maschinen; 0 = ungültig
* TIME: Minuten
* RPM: 1/min
* SPEED: km/h
* FUEL: l/100km
* TEMP: Celsius-Grad
*/
struct mData {
int name;
int time;
int rpm;
int speed;
float fuel;
int temp;
};
/* Prototypes */
void displayTable (struct mData *md);
struct mData getLine (char mdLine[]);
int main (void) {
FILE *mdFile, *errFile;
int i=0;
char mdLine[250];
char mdFilename[MAXFILENAME];
struct mData md;
/* Datei fuer das Fehlerprotokoll zuerst in jedem Fall oeffnen
* Bereits vorhandene Daten werden ueberschrieben!
*/
errFile = fopen (ERRORFILE, "w");
if (errFile == NULL) {
fprintf(stderr, "Fehler beim Oeffnen der Datei %s \n", ERRORFILE);
}
printf("Bitte Pfad der zu oeffnenden Datei angeben: \n");
/* Dateiname eingeben */
fflush(stdin);
scanf("%s", mdFilename);
mdFile = fopen (mdFilename, "r");
if (mdFile == NULL) {
fprintf(stderr, "Fehler beim Oeffnen der Datei %s\n", mdFilename);
} else {
/* Loop durch die Zeilen der Datei bis zum Ende */
while (!feof(mdFile)) {
if (i%20 == 0) {
printf("Zeit Umdrehungen Geschwindigkeit Verbrauch Temperatur\n");
printf("[m:s]\t [1/s]\t [km/h] [l/100km] [Grad C]\n");
}
i++;
fgets (mdLine, sizeof(mdLine), mdFile);
/* Scruct mit den richtig konvertierten Datensaetzen */
md = getLine(mdLine);
/* Kann sein, dass die Zeile fehlerhaft war, also
* kommt ein entsprechendes Scruct zurueck
*/
if (md.name == 0) {
fprintf(errFile, "%s", mdLine);
}
/* Tabellarische Ausgabe der Datensaetze */
displayTable(&md);
}
// Datei mit den Datensaetzen schliessen
fclose(mdFile);
}
if (errFile != NULL) fclose(errFile);
/* Für die Windowsuser: Cmd Box bleibt offen */
printf(CONFIRMEXIT);
fflush(stdin);getchar();
return 0;
}
struct mData getLine (char mdLine[]) {
char cTmp[10]; /* Hilfsvariable zur Zwischernspeicherung von Nachkommastellen */
char sTmp[MAXDIGITS+1]; /* Hilsvariable zur Zwischenspeicherung von strings */
char sTmp1[MAXDIGITS+1]; /* Hilsvariable zur Zwischenspeicherung von strings */
int iTmp[5]; /* Hilfsvariable zur Zwischenspeicherung von ints */
float fTmp[5]; /* Hilfsvariable zur Zwischenspeicherung von floats */
struct mData md;
int x=0;
/* Format von M1
* Testen ob die Zeile zu M1 passt
* %d.%c%c = I-NUMBER.DIGIT DIGIT
* %d = I-NUMBER
*/
if (sscanf(mdLine, "%d.%c%c,%d,%d,%d.%c%c,%s",
&iTmp[0],&cTmp[1],&cTmp[2],
&md.rpm,
&md.speed,
&iTmp[1],&cTmp[3],&cTmp[4],
sTmp) == 9) {
/* Speichern um welche Maschine es sich handelt */
md.name = 1;
/* Umständlicher Sonderfall: Das letze %s kann nicht etwa
* ein %d sein, weil sonst auch Eingaben wie 90.0xyz
* möglich wären - deshalb als string extrahieren und
* gesondert behandeln
*/
if ( sscanf (sTmp, "%d%c", &md.temp) > 1) md.name = 0;
/* Time als String zusammensetzen und anschließend
* in float umwandeln
*/
sprintf(sTmp, "%d.%c%c", iTmp[0],cTmp[1],cTmp[2]);
sscanf(sTmp, "%f", &fTmp[0]);
/* Fuel als String zusammensetzen und anschließend
* in float umwandeln
*/
sprintf(sTmp, "%d.%c%c", iTmp[1],cTmp[3],cTmp[4]);
sscanf(sTmp, "%f", &md.fuel);
/* Prüfen ob einer der Werte negativ ist oder
* ob Name gleich 0 ist
*/
if (md.name == 0 || md.time < 0 || md.rpm < 0 ||
md.speed < 0 || md.fuel < 0 || md.temp < 0 ) md.name = 0;
else {
/* Alle Werte der Zeile sind ok
* Konvertierung von Einheiten */
/* Zeit von Minuten in Sekunden umrechnen */
md.time = fTmp[0] * 60;
md.rpm = md.rpm/60;
}
/* Format von M2
* %d.%c%c = I-NUMBER.DIGIT DIGIT
* %d = DIGIT
* Tricky: M2 Name kann unendlich lang sein
* Muss man mit folgendem Konstrukt filtern: [0-9A-Z]
* %s geht nicht, weil das der komplette Reststring wäre
*/
} else if (sscanf(mdLine, "%d$%[0-9A-Z]$%d$%d$%d$%s",
&md.time,
&sTmp1,
&md.temp,
&md.speed,
&iTmp[3],
sTmp) == 6) {
/* Speichern um welche Maschine es sich handelt */
md.name = 2;
if ( sscanf (sTmp, "%d%c", &md.rpm) > 1) md.name = 0;
/* Name darf nur mit einem Grossbuchstaben anfangen,
* und muss mindestens 2 Zeichen lang sein
*/
if((!isupper(sTmp1[0])) || (strlen(sTmp1) < 2))
md.name = 0;
sprintf(sTmp, "%d", iTmp[3]);
sscanf(sTmp, "%f", &md.fuel);
if (md.name == 0 || md.time < 0 || md.rpm < 0 || md.speed < 0 ||
md.fuel < 0 || md.temp < 0 ) md.name = 0;
else {
/* Alle Werte der Zeile sind ok
* Konvertierung von Einheiten
/* Geschwindigkeit in km */
md.speed = md.speed*3.6;
/* Verbrauch in l/100km */
md.fuel = ((md.fuel/1000*60)/md.speed)*100;
/* RPM in R/s */
md.rpm = md.rpm/60;
/* Gard in Celsius */
md.temp = md.temp + KELVIN_CELSIUS;
}
/* Unbekanntes Format
* Scruct wird mit 0-Werten gefuellt
* Als Name der Maschine wird 0 eingetragen
*/
} else {
md.name = 0;
}
return md;
}
void displayTable (struct mData *md) {
/* Name der Maschine is 0 --> Unbekanntes Format
* Anstatt von Werten sollen * ausgegeben werden
*/
if (md->name == 0)
printf("%5s%13s %17s %11s %11s\n", "*", "*", "*", "*", "*");
/* Tabellarische Ausgabe eines korrekten Datensatzes */
else
printf("%02d:%02d%13d %17d %11.2f %11d\n",
md->time/60, md->time%60, md->rpm, md->speed, md->fuel, md->temp);
}