Numerieke gegevens lezen uit een tekstbestand in C++

Als de gegevens in een extern tekstbestand er bijvoorbeeld zo uitzien:

45.78   67.90   87
34.89   346     0.98

Hoe kan ik dit tekstbestand lezen en elk nummer toewijzen aan een variabele in c++?
Met ifstream kan ik het tekstbestand openen en het eerste nummer aan een variabele toewijzen, maar ik weet niet hoe ik het volgende nummer na de spaties moet lezen.

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    float a;
    ifstream myfile;
    myfile.open("data.txt");
    myfile >> a;
    cout << a;
    myfile.close();
    system("pause");
    return 0;
}
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    int data[6], a, b, c, d, e, f;
    ifstream myfile;
    myfile.open("a.txt");
    for(int i = 0; i << 6; i++)
        myfile >> data[i];
    myfile.close();
    a = data[0];
    b = data[1];
    c = data[2];
    d = data[3];
    e = data[4];
    f = data[5];
    cout << a << "\t" << b << "\t" << c << "\t" << d << "\t" << e << "\t" << f << "\n";
    system("pause");
    return 0;
}

Antwoord 1, autoriteit 100%

Herhaal >> leest in lus.

#include <iostream>
#include <fstream>
int main(int argc, char * argv[])
{
    std::fstream myfile("D:\\data.txt", std::ios_base::in);
    float a;
    while (myfile >> a)
    {
        printf("%f ", a);
    }
    getchar();
    return 0;
}

Resultaat:

45.779999 67.900002 87.000000 34.889999 346.000000 0.980000

Als je preciesweet hoeveel elementen er in een bestand zitten, kun je >> operator:

int main(int argc, char * argv[])
{
    std::fstream myfile("D:\\data.txt", std::ios_base::in);
    float a, b, c, d, e, f;
    myfile >> a >> b >> c >> d >> e >> f;
    printf("%f\t%f\t%f\t%f\t%f\t%f\n", a, b, c, d, e, f);
    getchar();
    return 0;
}

Bewerken:als antwoord op uw opmerkingen in de hoofdvraag.

Je hebt twee opties.

  • Je kunt eerdere code in een lus (of twee lussen) uitvoeren en een bepaald aantal waarden weggooien – als je bijvoorbeeld de waarde bij punt (97, 60) nodig hebt, moet je 5996 overslaan (= 60 * 100 + 96) waarden en gebruik de laatste. Dit werkt als u alleengeïnteresseerd bent in de opgegeven waarde.
  • Je kunt de gegevens in een array laden – zoals Jerry Coffin suggereerde. Hij heeft je al een aardige les gegeven, wat het probleem zal oplossen. Als alternatief kunt u een eenvoudige array gebruiken om de gegevens op te slaan.

Bewerken:waarden in bestand overslaan

Gebruik de volgende code om de 1234e waarde te kiezen:

int skipped = 1233;
for (int i = 0; i < skipped; i++)
{
    float tmp;
    myfile >> tmp;
}
myfile >> value;

Antwoord 2, autoriteit 11%

Het kan ervan afhangen, vooral of uw bestand hetzelfde aantal items op elke rij zal hebben of niet. Als dat zo is, dan wil je waarschijnlijk een soort 2D-matrixklasse, meestal zoiets als dit:

class array2D { 
    std::vector<double> data;
    size_t columns;
public:
    array2D(size_t x, size_t y) : columns(x), data(x*y) {}
    double &operator(size_t x, size_t y) {
       return data[y*columns+x];
    }
};

Houd er rekening mee dat zoals het is geschreven, dit ervan uitgaat dat je van tevoren weet welke maat je nodig hebt. Dat kan worden vermeden, maar de code wordt iets groter en complexer.

In elk geval, om de getallen te lezen en de originele structuur te behouden, zou je meestal regel voor regel in een string lezen en vervolgens een stringstream gebruiken om getallen van de regel te lezen. Hiermee kunt u de gegevens van elke regel in een aparte rij in uw array opslaan.

Als u de grootte niet van tevoren weet of (vooral) als verschillende rijen niet allemaal hetzelfde aantal cijfers bevatten:

11 12 13
23 34 56 78

Misschien wilt u een std::vector<std::vector<double> >in plaats daarvan. Dit brengt wel wat overhead met zich mee, maar als verschillende rijen verschillende afmetingen kunnen hebben, is dit een gemakkelijke manier om het werk te doen.

std::vector<std::vector<double> > numbers;
std::string temp;
while (std::getline(infile, temp)) {
    std::istringstream buffer(temp);
    std::vector<double> line((std::istream_iterator<double>(buffer)),
                             std::istream_iterator<double>());
    numbers.push_back(line);
}

…of, met een moderne (C++11) compiler, kunt u haakjes gebruiken voor de initialisatie van line:

   std::vector<double> line{std::istream_iterator<double>(buffer),
                             std::istream_iterator<double>()};

Antwoord 3, autoriteit 9%

De invoeroperator voor nummer slaat voorloopspatie over, zodat je het nummer gewoon in een lus kunt lezen:

while (myfile >> a)
{
    // ...
}

Antwoord 4, autoriteit 4%

je zou kunnen lezen en schrijven naar een apart zoals anderen.
Maar als je in dezelfde wilt schrijven, kun je dit proberen:

#include <iostream>
#include <fstream>
using namespace std;
int main() {
    double data[size of your data];
    std::ifstream input("file.txt");
    for (int i = 0; i < size of your data; i++) {
        input >> data[i];
        std::cout<< data[i]<<std::endl;
        }
}

Other episodes