0

This function is supposed to get a file of vectors. The first line contains the dimension. All other line are in the form of "P:3,5,2". The letter is P or N and the numbers are coordinates. This function read a line each time it is being invoked and it saves the P/N char and the coordinates into an array of double.

void readSamplesFile(FILE *sample_p, double result[])
{
    if (dimension == 0)
    {
    fscanf(sample_p,"%lf",&dimension);
    }
    printf("dimentions: %lf\n",dimension);
    printf("LINE \n");
    int index;
    for (index = 0; index<dimension; index++)
    {
        printf("%d",index);
        fscanf(sample_p,"%lf%*[:,]",&result[index]);
        printf("%lf",result[index]);
    }
}      

when i run it i get an endless loop. the dimension is read correctly but the it prints

LINE 
00.00000010.000000dimentions: 2.000000

endlessly. any ideas why? hope i was clear

EDIT: I've added the calling function:

void fillArray(FILE *sample_p,FILE *separators_p){
    double coordinates[MAX_DIMENSION];
    while (!feof(sample_p)){
        readSamplesFile(sample_p,coordinates);
    }
}

p.s. fscanf is set to read : and , but to ignore them.

yotamoo
  • 5,334
  • 13
  • 49
  • 61
  • 3
    Taken alone, this code won't compile. What are definitions for `dimensions` and its cousin `dimention` (in desperate need of a better variable name)? – phihag Aug 14 '11 at 12:24
  • its the same variable, i have corrected my spelling here and didn't notice the last one. but in my code its the same one. dimension is just a double – yotamoo Aug 14 '11 at 12:27
  • Check the return value of fscanf – Ed Heal Aug 14 '11 at 12:31
  • If it's also printing `LINE` endlessly then the problem is (at least) that you're calling `readSamplesFile` endlessly... – user786653 Aug 14 '11 at 12:40
  • please post an SSCCE or some more relevant code. I think we all need to know 1)where's defined an initialized dimension variable. 2)there's something printed before "dimentions", where and what is printed? 3)why dimentions isn't simply an integer? – Heisenbug Aug 14 '11 at 12:43
  • http://stackoverflow.com/questions/5431941/in-c-is-while-feof-always-wrong – William Pursell Aug 14 '11 at 14:01

1 Answers1

1

Neither 'P' nor 'N' is a valid double, nor are they ':' or ',', so the fscanf() fails. You should always check the return value from fscanf().

We can also debate whether you'd be better off using fgets() to read a line and sscanf() to parse it. Doing so avoids some issues; it is the way I'd code it automatically.


This code seems to work on the input file:

3
P:3,5,2
N:21.12,2.345e6,1.9132e-34

yielding the output:

dimension: 3.000000
LINE: P:3,5,2
P:offset=2:0=3(2):1=5(4):2=2(6):
LINE: N:21.12,2.345e6,1.9132e-34
N:offset=2:0=21.12(2):1=2.345e+06(8):2=1.9132e-34(16):

I'm still not keen on the (mis)use of a floating point dimension, but it works.

#include <stdio.h>

enum { MAX_DIMENSION = 6 };
enum { MAX_BUFFSIZE  = 4096 };

static double dimension = 0.0;

static int get_dimension(FILE *fin)
{
    char buffer[MAX_BUFFSIZE];

    if (fgets(buffer, sizeof(buffer), fin) == 0)
        return -1;
    if (sscanf(buffer, "%lf", &dimension) != 1)
        return -1;
    printf("dimension: %lf\n", dimension);
    return 0;
}

static int readSamplesFile(FILE *sample_p, double result[])
{
    char buffer[MAX_BUFFSIZE];
    if (fgets(buffer, sizeof(buffer), sample_p) == 0)
        return -1;
    printf("LINE: %s", buffer);

    char c;
    int offset;
    if (sscanf(buffer, " %c:%n", &c, &offset) != 1)
        return -1;
    printf("%c:", c);
    printf("offset=%d:", offset);
    for (int index = 0; index < dimension; index++)
    {
        int newoff;
        if (sscanf(&buffer[offset], "%lf%*[:,]%n", &result[index], &newoff) < 1)
            return -1;
        printf("%d=%g(%d):", index, result[index], offset);
        offset += newoff;
    }
    putchar('\n');
    return 0;
}

static void fillArray(FILE *sample_p)
{
    double coordinates[MAX_DIMENSION];
    while (readSamplesFile(sample_p, coordinates) == 0)
        ;
}

int main(void)
{
    if (get_dimension(stdin) == 0)
        fillArray(stdin);
    return 0;
}

Note that the fillArray() function, as written, does not do anything with the line of data. There is no checking that the dimension specified is positive and not greater than MAX_DIMENSION (that would go in get_dimension()). It feels cleaner to separate get_dimension() into a separate function than to hide it inside readSampleFile(). There is an argument that readSampleFile() should be renamed readSampleLine() since it does only process one line at a time, not a whole file at a time.

The use of the %n format specifier is a little tricky, but the code needs to know where to resume reading the buffer on the next cycle.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278