Leider ist so einiges schief an Deinem Projekt und das beginnt schon in main(...)
Code:
int main(int argc, char* argv[]) {
row *r;
s_fill(&r);
Hier wird ein Zeiger auf eine Variable r vereinbart, aber kein Speicher alloziiert.
Quasi eine fiktive Adresse mit Daten. Dieser Pointer ist ungultig.
Selbst wenn Du jetzt Speicher alloziiert hättest geht es dann im Code weiter...
Code:
//f.seekg(sizeof(int));
f.read(reinterpret_cast<char*> (&n), sizeof(n));
cout << n << endl;
// nach diesem read steht der Dateizeiger falsch!
// muss! zurückgesetzt werden
f.seekg( - ( sizeof( n ) ), ios::cur ); //
Du liest von den Daten schon mal einen int Wert aus der Datei ein (hast also eine Seite im Buch aufgeschlagen), gibst die Nummer aus und willst dann von der aktuellen Position ausgehend den kompletten Datensatz einlesen - was auch funktioniert wenn noch weitere Daten verfügbar sind, aber es wird der aktuelle Datensatz und ein Teil vom nächsten Datensatz gelesen! So passt das nicht in Deine Struktur.

Also muss - wenn Du schon mal im Buch vorblätterst - auch zurückgeblättert werden.
Dann das Einlesen der Daten.
Hier hat Du offensichtlich das Pointerkonzept noch nicht so ganz verstanden.
Code:
for(int i = 0; i < n; i++) {
if (!f.read(reinterpret_cast<char*> (&pr), sizeof(row)))
cerr << "Cannot read from input file." << endl;
else
Du willst in &pr einlesen und das bedeutet jetzt folgendes: An die Adresse von pr!
Oder auch so als Code geschrieben: (***pr)! da ja pr schon ein Pointer auf Pointer ist.
Die Adresse ist ja nichts anderes als ein Zeiger auf. Da Du schon Zeiger auf Zeiger hast, sagst Du damit dem Compiler: nimm mal Zeiger auf Zeiger auf Zeiger.
Rate doch mal WAS sich hinter dieser Adresse verbirgt. Keine Ahnung?
Tja der Compiler auch nicht. Das ist Speicher irgendwo ...
Konkret: Dein Zeiger **pr enthält ein Objekt, welches einen Zeiger auf ein Objekt enhält.
Einzige Bedingung: in main muss Speicher für das tatsächliche Objekt alloziiert werden.
Wie wäre der Code richtig?
Anstelle von (&pr) was gleichbedeutend mit (***pr) ist muss (*pr) hin und das Bedeutet, der Zeiger (**pr) wird genau ein mal Dereferenziert. Sprich es wird zur Adresse gegangen, die in der Adresse steht. Also wird aus Zeiger auf Zeiger nur noch der eigentliche Zeiger.
So das ganze jetzt mal komplett wie es laufen sollte, bitte schau Dir auch die Kommentare im Code an.
Code:
#include <iostream>
#include <fstream>
using namespace std;
struct row {
unsigned int nr;
int p;
float n;
};
void s_fill(row **r) {
int n;
row **pr;
fstream f("daten.dat", ios::in|ios::binary);
if (!f.good()) {
cerr << "Cannot open input file." << endl;
return; //raus hier! weitermachen hat eh keinen sinn...
}
//f.seekg(sizeof(int));
f.read(reinterpret_cast<char*> (&n), sizeof(n));
cout << n << endl;
// nach diesem read steht der Dateizeiger falsch!
// muss! zurückgesetzt werden
f.seekg( - ( sizeof( n ) ), ios::cur ); //
*r = new row[n];
// hier sollte *r geprüft werden ob Speicher alloziiert werden konnte!
// ...
pr = r;
for(int i = 0; i < n; i++) {
if (!f.read(reinterpret_cast<char*> (*pr), sizeof(row)))
cerr << "Cannot read from input file." << endl;
else
cout << "Reading values for struct ... OK (" << f.tellg() << ")" << "." << endl;
//cout << pr->nr << endl;
//cout << r.nr << "\t" << r.p << "\t" << r.n << endl;
pr++;
}
cout << "The end of the file has been reached." << endl;
f.close();
}
int main(int argc, char* argv[]) {
row *r = new row[1]; // Reservieren wir doch mal ein Objekt...
if( NULL == r ) {
cerr << "couldnt reserve memory for data!" << endl;
return -1;
}
s_fill(&r);
cout << r[0].nr << endl;
// hier fehlen sämtliche delete zum Speicher abräumen...
return EXIT_SUCCESS;
}
Ich habe den Code jetzt nur überflogen, kann sein das ich noch was übersehen habe!
Wenn es nicht klappt bitte mal Compiler nennen und die genaue

Fehlermeldung.
Gruß René