[C] fprintf() macht zuviele Ausgaben

Hallo,

ich habe ein garantiert einfaches Problem mit der fprintf()-Funktion, aber ich finde keine Lösung.

Ich möchte eine Datei erstellen und nach jedem Programmstart modifizieren
Dazu soll eine Datei erstellt und wenn diese bereits existiert, deren Inhalt einlesen werden.
(Inhalt pro Zeile: "C 0.8382 1.83347 -2.3884" -> C Zahl Zahl Zahl)

Beim Wiederholen dieser Prozedur schreibt irgendwann (meist nach 7-20 Wdhg) fprintf() extra Zahlen
nach dem letzten Zeilenumbruch. An der Stelle sollte eigentlich nichts mehr kommen, da die Datei direkt im nächsten Schritt mit fclose() geschlossen wird.

Wenn ich auf den Buchstaben "C" in der Aus- und Eingabe verzichte, so gibt es keine Probleme.
fscanf() hat keine Probleme beim einlesen nur die Ausgabe fprintf().

Ich hab den Code hinzugefügt und ein Script damit einem ein ständiges Neustarten erspart bleibt.

Wenn das Script läuft, stoppt fscanf() irgendwann, da das Ausgabefile "test.dat" nun ein zusätzliches
Zeichen enthält, was es natürlich nicht erwartet.
Bei mir lässt sich dieser "Fehler" ziemlich zuverlässig zu reproduzieren.

Ich wäre dankbar über Hinweise woran es liegen könnte.

Gruß,
LM

C++:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void main(argc,argv )
int argc; char *argv[];
{
 
  double x[7],y[7],z[7];
  int N=7,i;
  FILE *fp;
 
  srand(time(NULL));
 
  /*Datei anlegen oder auslesen wenn die Datei bereits vorhanden.*/
  fp=fopen("test.dat","r+");
  if(NULL==fp){
  fp=fopen("test.dat","w+");
  for(i=0;i<N;i++){  x[i]=0; y[i]=0; z[i]=0;  }
  }else{
  i=0;
  while((fscanf(fp,"C\t%lf\t%lf\t%lf\n",&x[i],&y[i],&z[i]))!=EOF)
  {   i++;  }
  }
 
  /*Felder x,y,z beliebig verändern.*/
  for(i=0;i<7;i++){  x[i]+=(rand()%10)-5; y[i]+=(rand()%10)-5; z[i]+=(rand()%10)-5; }
 
  /*Felder x,y,z in Datei schreiben. Hier tritt irgendwann der Fehler auf*/
  rewind(fp);
  for(i=0;i<N;i++){   
    fprintf(fp,"C\t%12.15lf\t%12.15lf\t%12.15lf\n",x[i],y[i],z[i]);
  }
  fclose(fp);
 
}

Code:
#! /bin/bash
cc simpel.c

for i in `seq 1 30`;
do
  ./a.out
  echo $i
  sleep .5
done
 
Hallo Lodda,

wo steht wann was falsch? :confused:
Beschreib' mal genauer, was Du erwartest und was stattdessen da steht .....

Gruß Klaus
 
Hallo Klaus,
der Fehler tritt in der Ausgabedatei auf.
Man bemerkt es so erst, wenn das Ausgabefile wieder eingelesen wird, dann stoppt das Programm.

So sieht es bspw. in der Ausgabedatei aus wenn der Fehler aufgetreten ist:
Code:
C    -17.000000000000000    -32.000000000000000    -13.000000000000000
C    -28.000000000000000    -9.000000000000000    10.000000000000000
C    -3.000000000000000    -17.000000000000000    -3.000000000000000
C    8.000000000000000    -9.000000000000000    20.000000000000000
C    -10.000000000000000    12.000000000000000    -8.000000000000000
C    -25.000000000000000    -30.000000000000000    -25.000000000000000
C    -5.000000000000000    -31.000000000000000    -9.000000000000000
0
Die "0" in der 8. Zeile gehört da eigentlich nicht hin...

EDIT: Vielleicht sollte ich noch sagen das ich unter Linux (Suse) arbeite.
 
Moinsen,

ah ja ...
sicher das das Zeichen nicht schon in der Datei steht, die Du einliest?
Welchen Wert hat i nach der while-Schleife?

Gruß Klaus
 
Hi

C++:
while( (fscanf(fp,"C\t%lf\t%lf\t%lf\n",&x[i],&y[i],&z[i])) != EOF)
{
    i++;
}
Zwei Probleme hier:

a) EOF ist nur ein mögliches Problem, die anderen werden hier nicht erkennt.
Prüf zB. auf ==3 (ob drei Variablen erfolgreich eingelesen wurden)

b) Keine Prüfung ob zu viel Zeilen da sind. Ggf. werden zu hohe Arrayindizes
befüllt, was zu allen möglichen Problem führen kann. Mit Prüfung:
C++:
while(i < N && fscanf(fp,"C\t%lf\t%lf\t%lf\n",&x[i],&y[i],&z[i]) == 3)
{
    i++;
}
Dass das i<N vor dem fscanf in der Bedingung steht ist wichtig,
wenn es danach wäre würde noch ein letztes fscanf ausgeführt,
bevor gemerkt wird, dass man schon zu weit ist

Zwei kleinere Sachen:

C++:
void main(argc,argv )
int argc; char *argv[];
Das ist Uralt-Syntax, und halbwegs neue Compiler beschweren
sich darüber (falls man die Warnungen ein hat und liest).
Warum nicht einfach folgendes?
C++:
void main(int argc, char *argv[])

Und bei einer der Schleifen gehst du von 0 bis 7 statt 0 bis N,
bei anderen N wird das zum Problem.
 
Zuletzt bearbeitet:
Hi,

die Datei existiert vor dem 1. Start nicht, dann werden die Werte, welche später geschrieben werden, gesetzt und modifiziert.
Anschließend schreibt fprintf() diese Zahlen mit dem vorgestellten "C" in die Ausgabedatei.

Ich habe die Ausgabedatei nach jeder Änderung angeschaut aber dort ist alles so wie es sein soll bis zu dem Zeitpunkt wenn es falsch ausgeben wird.
Ich hab es mir auch zusätzlich direkt über printf() ausgeben lassen aber der printf() Befehl macht auch alles so wie er soll.

Ich denk ich habe jetzt die Lösung:

Code:
fprintf(fp,"C\0\t%12.15lf\t%12.15lf\t%12.15lf\n",x[i],y[i],z[i]);

Hab jetzt ein "\0" hinter das "C" geschrieben und es scheint zu funktionieren.
Scheinbar ist das "C" ein String welcher beendet werden muss... .
Das Problem hatte ich noch nie mit gemischten Ausgaben von Buchstaben und Zahlen ... .

Ich denke das Problem ist damit gelöst aber richtig zufrieden bin ich irgendwie nicht.

Ein Danke an Klaus für die Denkanstöße!!!

EDIT:

Hallo sheel,

die fscanf Ausgabe scheint wirklich der bzw. auch ein Fehler gewesen zu sein.

Die Übergabe der Argumente an main hab ich erst einmal so gelassen wie ich es kenne... da hab ich wohl aus alten Büchern gelernt, bzw. mein Kollege ist etwas älter :)

Der Code ist nur auf das wesentliche reduziert um den Fehler zu reproduzieren, das mit dem N=7 und Schleifenwert auf 7 gesetzt ist also nicht weiter schlimm, aber du hast Recht!


Danke für die Anmerkungen und die Korrekturen!
LM
 
Zuletzt bearbeitet:
Ich denk ich habe jetzt die Lösung:

Code:
fprintf(fp,"C\0\t%12.15lf\t%12.15lf\t%12.15lf\n",x[i],y[i],z[i]);

Hab jetzt ein "\0" hinter das "C" geschrieben und es scheint zu funktionieren.
Das funktioniert nicht, du probierst nur herum.
"\0" schreibt eine Binär-Null in deine Text-Datei, das ist Unsinn.
Außerdem muss field width (12) immer >= precision (15) sein, du wirst sicher einsehen, dass das bei dir auch falsch ist.
 
Zurück