replax replax - 2 days ago 4
C Question

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!

Answer
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);

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;
    }
Comments