Question

I'm running into a problem with reading a txt file within a Windows NT 4.0 dll file; and before you ask, I'm not currently interested in migrating this to a new OS. I just want to fix this one issue and let others after me worry with migrating this super-legacy software.

The problem occurs when I read a txt file using fscanf, as shown:

infile_ptr = fopen("c:\\LumaGem\\orbit.txt", "r");
byteoffset=0;
while(!feof(infile_ptr) )
    {   
        r=0.0; s1=0.0; s2=0.0; e1=0.0; e2=0.0; e3=0.0; d=0.0; f=0.0;
        fseek(infile_ptr, byteoffset, SEEK_SET);
        fscanf(infile_ptr,"%7lf %7lf %7lf %7lf %7lf %7lf %7lf %7lf", &r, &s1, &s2, &e1, &e2, &e3, &d, &f);

        byteoffset=0; byteoffset = ftell(infile_ptr);
     }
fclose(infile_ptr);  

The txt file, created with MATLAB, consists of 128 rows of 8 columns separated by 5 spaces and formatted like so within MATLAB:

fprintf(fid,'%7.3f     %7.3f     %7.3f     %7.3f     %7.3f     %7.3f     %7.3f     %7.3f \n', variables);

This code was not written by me, and worked for several years. However, recently we had to rebuild/reinstall the Windows NT 4.0 OS and software, and now I get a strange error. The program reads the txt file fine using the code provided at the top until it gets to line 123, at which point it reads the 8th column twice, resulting in all of the subsequent variables to be shifted by one position, completely screwing up the last few lines of the program. Interestingly enough, this problem can be overcome by manually copying and pasting the first 123 lines in bulk to a new txt file and then the last several lines one-by-one into the same new txt file and using that as the input (copying done on the NT machine within WordPad). Doing so eliminates this double-read issue. I have no idea what problems can cause this error, but also let it be fixed by such a weird/clunky method. The problem happens with new and old inputs, so I don't think the input files are the issue since they haven't changed.

Oh, and additionally, if I change the number of spaces between each column in the txt file, the location of the error shifts. Reducing it to 1 space causes the error to occur at line 120 or so, while increasing the number of spaces (tried 7 instead of 5) pushed the error down to line 124.

I'm no programming expert (always been a learn-as-I-need-it guy), so help figuring this out would be greatly appreciated. Thanks!

Was it helpful?

Solution 2

Candidate simplification

Have not found the source of the issue, but recommended this to simplify debugging. This takes care of PC line endings, excessive manipulation of the file pointer, unneeded limitation of %7lf and provides better error checking.

FILE *infile_ptr = fopen("c:\\LumaGem\\orbit.txt", "rt");  // PC text file
char buf[1000];
while (fgets(buf, sizeof(buf), infile_ptr)) {  // separate I/O from scanning
  int count = sscanf(buf,"%lf%lf%lf%lf%lf%lf%lf%lf", &r, &s1, &s2, &e1, &e2, &e3, &d, &f);  
  if (count != 8) { // check for correct scan count
    ; //handle error;
  }
}
if (ferror(infile_ptr)) {
  ; //handle error;
}
fclose(infile_ptr);

[Edit] OP posted original text file.

Also add this line to the loop to take care of trailing lines consisting of only spaces.

  if (count <= 0) continue;

[Edit] Conclusion.

The use of fseek() and ftell(), usually used with binary files, not needed here IMHO, is a Window's bug reading a UNIX text file (\n) opened in Windows in binary mode "r" and using fscanf() which works best reading text files open "rt". Nothing found to point to line 123 or its neighbors as a problem area.

OTHER TIPS

Trouble with your fscanf() directive.
Recommend %lf instead of %7lf.

Your fprintf() with "%7.3f" prints out floating point numbers using at least 7 characters to do so, padding with ' ' as needed.

Your subsequent use of "%7lf" in fscanf() says to scan at most 7 characters. So when you printf/scanf 999.999 all is OK, but with numbers greater, such as 1000.007, your scanning takes in "1000.00" and leaves the "7" for the next "%7lf".

 int main(void) {
  char buf[1000];
  double f1, f2;
  int r;
  sprintf(buf, "%7.3f %7.3f", 1.23, 4.56);
  r = sscanf(buf, "%7lf %7lf", &f1, &f2);
  printf("'%s'\n%d %g %g\n", buf, r, f1, f2);

  sprintf(buf, "%7.3f %7.3f", 999.999, 4.56);
  r = sscanf(buf, "%7lf %7lf", &f1, &f2);
  printf("'%s'\n%d %.10g %.10g\n", buf, r, f1, f2);

  sprintf(buf, "%7.3f %7.3f", 1000.007, 4.56);
  r = sscanf(buf, "%7lf %7lf", &f1, &f2);
  printf("'%s'\n%d %.10g %.10g\n", buf, r, f1, f2);

  return 0;
}

Output:  
'  1.230   4.560'  
2 1.23 4.56  
'999.999   4.560'  
2 999.999 4.56  
'1000.007   4.560'  
2 1000 7  

BTW: For fscanf(), "%lf%lf%lf ..." is OK. Adding spaces in between the %lf does not change functionality.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top