0

I am trying to write double arrays into files and read them again. Below is my code, but there is something I am missing. It sounds silly but I cannot get it right.

#include <stdio.h>
#include <stdlib.h>

int main(){

  int i,j,k;
  int N = 10;

  double* readIn = new double[N];
  double* ref = new double[N];
  FILE* ptr1, *ptr2;

  ptr1 = fopen("output.txt","w");
  //write out
  for (i = 0; i < N;i++){
    ref[i] = (double)i;
    fprintf(ptr1,"%g\n",(double)i);
  }
  fclose(ptr1);
  //read file
  ptr2 = fopen("output.txt","r+");
  //read in
  for(i = 0;i < N;i++)
    fscanf(ptr2, "%g", &readIn[i]); 


  fclose(ptr2);

  for(i = 0;i<N;i++)
    if(ref[i] != readIn[i]){
      printf("Error:  %g   %g\n",ref[i], readIn[i]);
    }

  return 0;

}
Manolete
  • 3,431
  • 7
  • 54
  • 92
  • What output do you get? – nullptr May 09 '13 at 14:06
  • What's the problem? What result are you expecting that isn't happening? – chrisaycock May 09 '13 at 14:06
  • just garbage data: Error: 0 6.95314e-310 Error: 1 5.26354e-315 Error: 2 5.30499e-315 Error: 3 1.19364e-312 Error: 4 5.34643e-315 Error: 5 5.3568e-315 Error: 6 5.36716e-315 Error: 7 5.37752e-315 Error: 8 6.9532e-310 Error: 9 5.39306e-315 – Manolete May 09 '13 at 14:06

1 Answers1

7

Your fscanf is using the wrong format string (which GCC will tell you about if you enable sufficient warnings).

So your double is filled with float value, which of course leads to rather "random" errors.

If you change the "%g" to "%lg", it should work just fine (at least it does on my Linux box).

Of course, if you use the C++ streams, e.g.

 #include <fstream>

 std::ofstream file1;
 std::ifstream file2;

 file1.open("output.txt");

 for (i = 0; i < N;i++){
    ref[i] = (double)i;
    file1 << (double)i << std::endl;
 }

and

   file2.open("output.txt");
   for(i = 0;i < N;i++)
      file2 >> readIn[i]; 

the whole problem would have been avoided - and if you edit the readIn variable to be float, as long as the values are valid for that, it would be possible to read those values without chaning anything else [assuming the output is also using cout instead of printf, of course].

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • Hell you are right! Awesome! I always thought that `%g` is more than enough for double precision. – Manolete May 09 '13 at 14:13
  • For `printf` all float values are converted to `double`, but for `scanf`, since it's a pointer, the code needs to know the difference between `double` and `float`, and they choose to make `float` the default, and `l` as a prefix for `double`. Don't ask me why... – Mats Petersson May 09 '13 at 14:15
  • @ Mats Peterson Yeah, it would be good to know why `l` a is prefix for double. – Manolete May 09 '13 at 14:17
  • Additionally, I'd suggest using stream operators rather than scanf/printf and friends. They are just far too error-prone, so I've sworn off of them. Due to issues like this one, I would often find myself spending hours (if not days) tracking down "bugs" that are really just misues of printf in debug statements in otherwise perfectly working code. – T.E.D. May 09 '13 at 14:21
  • Yeah, the number of times I've tried to figure out "Why is my result coming out all weird", only to find I'm printing with the wrong format (e.g. trying to print something that USED to be float as a int, or the other way around). At least gcc warns you... – Mats Petersson May 09 '13 at 14:29
  • Yes, you all are damn right. I'll rather go for `fwrite` and `fread` in binary. That should be more than enough in scientific code. – Manolete May 09 '13 at 16:00