Reputation: 437
I have a set of Data in the following form:
a1 b1 c1 d1
a2 b2 c2 d2
...
an bn cn dn
My goal is to find the row which has the smallest value for the c column.
I did the following:
const int limit=100000;
float Array[limit][4];
int main() {
double a, b, c, d, smallest, ref1, ref2;
ifstream in("data.dat");
int idx=-1, point;
while(!in.eof()) {
idx++;
in >> a >> b >> c >> d;
Array[idx][0]=a; Array[idx][1]=b; Array[idx][2]=c; Array[idx][3]=d;
} \\end of while
in.close();
int count=idx;
for(int i=1; i<count; i++) {
ref1= Array[0][2];
ref2 = Array[i][2];
if(ref2 < ref1) {ref1 = ref2; point=i;} //I thought this will save the smallest value
smallest = ref1; point= i;
} \\end for
cout << "point" << Array[point][0] << Array[point][1] << .. etc.
return 0;
}
However, the output was the last point in the data. (As of typing this question, I realised that ref1 will always be the Array[0][2] as the new line is read. So now I'm totally lost!)
How to save one point as a reference point, such that it is compared to the rest of the data, and it changes to a smaller value each time it is compared to a smaller point?
UPDATE: I fixed this by taking ref1=Array[0][2]; out of the for loop.
Upvotes: 2
Views: 1165
Reputation: 76498
On a different note, the input loop control is incorrect:
while(!in.eof()) {
eof() doesn't get triggered until a read has failed. In practice, this means that the input loop executes one extra time, and you get nonsense values the last time through.
The correct test is
while(in >> a >> b >> c >> d) {
If any of the extractors fails (hopefully because in
is at the end of the input, the while loop will end.
Upvotes: 1
Reputation: 32538
To certify that you've found the smallest value in a set of values, change your for-loop to the following:
int smallest_val = std::numeric_limits<int>::max();
for(int i=0; i < idx; i++)
{
if (Array[i][2] < smallest_val)
smallest_val = Array[i][2];
}
Basically you start off by setting smallest_val
to the largest possible value that it can possible have using std::numeric_limits<int>::max()
. Now every value in the array will have to be at least as large as smallest_value
or smaller (nothing can be larger). When you loop through the array, once you hit a value less than the value currently in smaller_value
, you will properly re-assign the value in smaller_value
to that new lower value. By starting off with the largest possible that can be represented by the int
type, you avoid the problem you're encountering where your smallest values are relative to each other. Using mathematical induction, that type of method is unnecessary for what you're attempting to-do here.
Upvotes: 3
Reputation: 1942
You should set a reference as I do outside the loop and update the smallest, btw, do not mix floats with doubles however here is a sample code:
#include <iostream>
#include <fstream>
using namespace std;
const int limit=100000;
float Array[limit][4];
int main() {
double a, b, c, d, smallest, ref1, ref2;
ifstream in("data.dat");
int idx=-1, point;
while(!in.eof()) {
idx++;
in >> a >> b >> c >> d;
Array[idx][0]=a;
Array[idx][1]=b;
Array[idx][2]=c;
Array[idx][3]=d;
} //end of while
in.close();
int i = 0;
int count;
smallest = Array[i][2];
for( i=1; i<count; i++) {
ref2 = Array[i][2];
if(ref2 < smallest) {
smallest = ref2;
point=i;
}
}
std::cout << "point" << Array[point][0] << " "
<< Array[point][1] << " "
<< Array[point][2] << " "
<< Array[point][3] << std::endl;
return 0;
}
With data file
1 2 3 4
2 3 8 9
1 3 5 2
1 1 1 1
2 4 2 4
3 1 0 1
HTH
Upvotes: 3
Reputation: 571
The problem here is that you never compare to your smallest. You assign the lowest value between ref1 and ref2 without considering the previous iterations. Also, ref1 is always the first value in your data so if the last value is bigger than the first, the smallest will always be the last. Changing the loop to what Jason posted will solve your problem.
Upvotes: 0