Reputation: 307
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
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 float
s 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
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