replax
replax

Reputation: 307

How to compare the value of an array element passed to a function

I am trying to write a function which gets input from the user in the following format: 0.3,0.2,1 in datatypes: float,float,int. If both floats have a value of 0.0 the data entry is finished. I initialise the three arrays

float col1Train[1000];
float col2Train[1000];
int col3Train[1000];

in the main function (it can reasonably be assumed that there are less than 1k data entries by the user), and call the function like this:

nTrainSets = readTrainingData(&col1Train, &col2Train, &col3Train);

Now, my problem is that the IF condition (marked below) crashes my program and I am not sure why. I want to check if the contained array element is zero..

Also, the alternative formulation of the same statement (at least I believed it to be the same?) Is not compiling citing a mismatch of float and *float - why is that / how can I fix that?

int readTrainingData(float *col1[], float *col2[], int *col3[])
{
    int i = 0;
    int scanfReturn = scanf("%f,%f,%d", &col1[i], &col2[i], &col3[i]);
    while (scanfReturn == 3) {
        printf ("read: %f, %f, %d", col1[i], col2[i], col3[i]); // Debug statement, execution succeeds
        if (*col1[i] == 0.0f && *col2[i] == 0.0f) {  // Causing the error
        //if (*(col1 + i) == 0.0f && *(col2 + i) == 0.0f) {  // Not even compiling
            col1[i] = NULL;
            col2[i] = NULL;
            col3[i] = NULL;
            break;
        }
        ++i;
        scanfReturn = scanf("%f,%f,%d", &col1[i], &col2[i], &col3[i]);
    }
    return i - 1;    
}

Thank you!

Upvotes: 0

Views: 68

Answers (2)

Bodo Thiesen
Bodo Thiesen

Reputation: 2514

float col1Train[1000];
float col2Train[1000];
int col3Train[1000];

consider using a struct here:

struct train {
    float col1;
    float col2;
    int col3;
};

struct train Train[1000];

it can reasonably be assumed that there are less than 1k data entries by the user

Never ever assume anything. Just pass the number of elements in the function call. So instead of

nTrainSets = readTrainingData(&col1Train, &col2Train, &col3Train);

use

nTrainSets = readTrainingData(1000, &col1Train, &col2Train, &col3Train);

Also, passing an array to a function effectively is passing a pointer to it's first argument to the function. So, call it like this:

nTrainSets = readTrainingData(1000, col1Train, col2Train, col3Train);

And then the function prototype needs a change too. Instead of

int readTrainingData(float *col1[], float *col2[], int *col3[])

either write

int readTrainingData(size_t size, float col1[], float col2[], int col3[])

or

int readTrainingData(size_t size, float * col1, float col2, int col3)

Which both are basicly the same. I prefer just the variant float * col1 but one could argue, that float col1[] documents, that an actual array is expected and not only a pointer to a single value.

int scanfReturn = scanf("%lf,%lf,%d", &col1[i], &col2[i], &col3[i]);

Since scanf needs a pointer anyway, just calculate a pointer:

int scanfReturn = scanf("%lf,%lf,%d", col1 + i, col2 + i, col3 + i);

Now, in contrast to printf, where "%f" expects a double argument and floats being promoted to double due to type promotion rules (and "%lf" only having later been allowed to be used as synonym for "%f"), the scanf-family of functions actually have to distinguish between the two data types. So, to scan a double, you would use "%lf" but for a float (what you are using here) you must restrain to "%f" like so:

int scanfReturn = scanf("%f,%f,%d", col1 + i, col2 + i, col3 + i);

And then

    if (*(col1 + i) == 0.0f && *(col2 + i) == 0.0f) {

or (col1[i] == 0.0f && col2[i] == 0.0f) {

world work perfectly with the Cish way being:

    if (!col1[i] && !col2[i]) {

.

        col1[i] = NULL;
        col2[i] = NULL;
        col3[i] = NULL;

Here, please use 0 not NULL, because NULL might be a pointer and thus fail to assign to a non pointer variable.

        col1[i] = 0;
        col2[i] = 0;
        col3[i] = 0;

And finally to conclude the "never assume anything" part: In the i increment, test for buffer overflow:

    if (++i == size-1) {
        col1[i] = 0;
        col2[i] = 0;
        col3[i] = 0;
        break;
    }

Upvotes: 1

Fabulous
Fabulous

Reputation: 776

The statement if (*col1[i] == 0.0f && *col2[i] == 0.0f) is wrong. The compiler will take the above condition to be a comparison between an array of pointers (*col[i]) and a float value (0.0f), and not the array you need to compare. The error

mismatch between float* and float

occurs because you are comparing an address pointing to floating value (float* ) to a float value, i.e *col[i] == 0.0f

Rewrite the condition to if (col1[i] == 0.0f && col2[i] == 0.0f) or if ( (*(col1+i)) == 0.0f && (*(col2+i)) == 0.0f)

EDIT : As pointed out in the comments, you must change your function prototype as well for the if condition to work. instead of passing a pointer of arrays float *col[i], pass the array float col[i] itself. Array to pointer conversion shall take place when the if condition is evaluated, thus making your code work as expected.

Upvotes: 0

Related Questions