Let's give this another go:
static const unsigned int ID_CAPACITY = 256;
static const unsigned int MAX_UNIQUE_VOLUMES = 512;
struct Record
{
double volume;
int ids[ID_CAPACITY];
unsigned int ids_size;
};
Record database[MAX_UNIQUE_VOLUMES];
int main()
{
double volume;
int id;
static const double epsilon = 1e-06;
unsigned int database_size = 0U;
std::ifstream input_file("data.txt");
while (input_file >> id >> volume)
{
bool volume_is_duplicate(false);
// Find a duplicate volume
for (unsigned int i = 0U; i < database_size; ++i)
{
const double volume_from_database = database[i].volume;
const double diff = std::abs(volume - volume_from_database);
if (diff < epsilon)
{
unsigned int id_index = database[i].ids_size;
database[i].ids[id_index] = id;
++(database[i].ids_size);
duplicate_volume = true;
break;
}
}
if (!duplicate_volume)
{
Record r;
r.volume = volume;
r.ids[0] = id;
r.ids_size = 1;
database[database_size] = r;
++database;
}
}
std::cout << "\n\nPaused. Press ENTER to continue.\n";
std::cin.ignore(100000, '\n');
return 0;
}
In the above program, the record is read in as two separate variables. The database is searched for an equivalent volume. If an equivalent volume exists, the new value is append to the ID container. If the volume is unique, the record is appended to the database.
Printing of the database is left as an exercise for the OP (as well as boundary/range checking).
The trick here is to organize the database by volume, not by ID. Each database record will contain IDs of equivalent volumes:
vol. IDs
+-------+-----+
| 213.1 | 001 |
+-------+-----+-----+
| 414.7 | 002 | 004 |
+-------+-----+-----+
| 718.3 | 003 | 005 |
+-------+-----+-----+
| 114.5 | 006 |
+-------+-----+