Чытанне дадзеных з тэкставага файла. Мне трэба зрабіць дзве рэчы, першая мне трэба прачытаць лік кропак

У мяне ёсць тэкставы файл, размешчаны як:

Diam
          4.2      
05:21:26 02:Apr:2012
Point 1
       2   
       5
       6  
Point 2
       4   
       2
       0
Point 3
       4 
       1 
       2 
End
End

Мне трэба зрабіць дзве рэчы, спачатку я павінен прачытаць колькасць ачкоў, таму ў асноўным чытаць, як многія радкі пачынаюцца з кропкі, для гэтага я пісаў:

#include 
#include 

using namespace std;

int main()
{
    //count number of data points in file (only count lines starting with P)
    const char FileName[] = "myfile.txt";
    int num = 0.;
    string line;
    ifstream file;
    file.open (FileName);
    while(file.eof() == false)
    {
        getline(file, line);
        if (line[0]=='P')  num++;
    }
    file.close();

    return 0;
}

Гэта дае мне правільнае лік кропак (хоць паляпшэння ў кодзе вітаюцца), а па-другое, мне трэба прачытаць x, y, і каардынаты Z і ігнараваць усе астатняе. Не ведаеце, як ісці аб гэтым, любыя прапановы?

Загадзя дзякую!

EDIT:

Дзякуй усім за вялікія ідэі і адказы! Капітан Obvlious прадаставіў вялікі адказ, і я хачу так бачыць, калі ён можа быць адаптаваны няшмат.

Такім чынам, атрымліваецца, файл .txt будзе мець наступны фармат:

Diam
          4.2      5    6    4   2
05:21:26 02:Apr:2012
Point 1
       2   5    6    4   2
       5   4    4    8   3
       6   7    6    0   2
Point 2
       4   2    6    4   2
       2   3    5    8   4
       0   7    6    3   2
Point 3
       4   0    6    2   2
       1   5    6    7   4
       2   0    6    5   3
End
End

Зноў жа, мне трэба толькі першы слупок значэнняў, усё астатняе пасля гэтага можна выкінуць. Я Int для прастаты, але лічбы будуць двайны . Пасля чытання я спрабую змясціць значэння ў браняносец матрыцы, так што мая матрыца выглядае наступным чынам:

cout << matrix << endl;
2 5 6
4 2 0
4 1 2 

Такім чынам, я змяніў рашэнне капітана Obvlious ', каб змясціць дадзеныя ў матрыцы:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
using namespace arma;

int main()
{
    mat matrix(3,3);  //here is where I set the size of the matrix, 
                      //different files have different number of points,
                      //that's why I use my counting points code to set the size.
    const char FileName[] = "myfile.txt";
    string line;
    ifstream file;
    file.open (FileName);

    for(;;)
    {
        getline(file, line);
        if( file.eof() ) {
            break;
        }

        if (line.size() && line[0]=='P')
        {
           //Change "int" to "double" if necessary.
            struct { double  x, y, z; } data;

            for(int i = 0; i < 3; i++)
            {
                getline(file, line);
                if(line.size() > 3 && line[0] == '<' && line[2] == '>')
                {
                    string::value_type pointElement = line[1];

                   //skip spaces and process data here to get the value
                    string::size_type offset = line.find(' ');
                    if(string::npos == offset)
                    {
                        throw invalid_argument("Invalid data format");
                    }

                    stringstream sline(line.substr(offset));
                    int value;
                    if(!(sline >> value))
                    {
                        throw invalid_argument("invalid data format");
                    }


                    switch(pointElement)
                    {
                    case 'X':   data.x = value; break;
                    case 'Y':   data.y = value; break;
                    case 'Z':   data.z = value; break;
                    default:
                       //error in data format
                        throw invalid_argument("invalid data format");
                    }
                }
                else
                {
                   //error in data format
                    throw invalid_argument("invalid data format");
                }
            }

           //Do something with the values in data
            cout
                << "point[x=" << data.x
                << ", y=" << data.y
                << ", z=" << data.z
                << "]" << endl;
           //place data in matrix
           //need to loop over k where k is the row of the matrix
            matrix(k,0) = data.x;//format is matrix(rows,columns)
            matrix(k,1) = data.y;
            matrix(k,2) = data.z;
        }
    }
    file.close();

    return 0;
}

Не ўпэўнены, куды змясціць пятлю над да, які задае радок матрыцы для вылучэння значэнняў. Выбачайце за супер доўгі пост, і загадзя дзякуй за любую дапамогу. Гэта вельмі карысны матэрыял, каб мець вакол для будучай спасылкі на мой погляд.

2
@ User1981855: Калі «праграміст» вам сказаў, што яны «дасведчаныя», то вы павінны прыняць іх і пляскаць іх. На самай справе, ісці наперад і рабіць гэта ў любым выпадку. GetLine павінен ісці ў строгіх цыклу. StackOverflow .com/пытанні/5605125/& hellip;
дададзена аўтар Lightness Races in Orbit, крыніца
(Вы таксама павінны навучыцца C ++ з рэцэнзаванай кнігі, а не нейкі чувак на вуліцы!)
дададзена аўтар Lightness Races in Orbit, крыніца
(Вы таксама павінны навучыцца C ++ з рэцэнзаванай кнігі, а не нейкі чувак на вуліцы!)
дададзена аўтар Lightness Races in Orbit, крыніца
@ User1981855: Калі «праграміст» вам сказаў, што яны «дасведчаныя», то вы павінны прыняць іх і пляскаць іх. На самай справе, ісці наперад і рабіць гэта ў любым выпадку. GetLine павінен ісці ў строгіх цыклу. StackOverflow .com/пытанні/5605125/& hellip;
дададзена аўтар Lightness Races in Orbit, крыніца
<�Код> у той час як (file.eof() == хлусня) няправільна. Які рэсурс даручыў вам зрабіць гэта?
дададзена аўтар Lightness Races in Orbit, крыніца
<�Код> у той час як (file.eof() == хлусня) няправільна. Які рэсурс даручыў вам зрабіць гэта?
дададзена аўтар Lightness Races in Orbit, крыніца
Вы, мабыць, абазнаны ў выкарыстанні зОго :: GetLine() (і добра, што, дарэчы). Ці ёсць што-то не так з наступным вашу кропку праверкі з трыа станд :: GetLine() Выклікі, а затым шляхам падачы ліній (па адным за раз) у istringstream </код > і здабываючы пазнаку і значэнне, засяленне кропку картэжа, і штурхаючы яго ў вектар? (І заўвага: вы збіраецеся знайсці, выкарыстоўваючы file.eof() як тэрмінатар цыкл не будзе працаваць, як вы думаеце, што будзе).
дададзена аўтар WhozCraig, крыніца
Вы можаце выкарыстоўваць AWK? Гэта спрасціла б усю праблему
дададзена аўтар Nebril, крыніца
@LightnessRacesinOrbit мне параілі выкарыстоўваць гэты метад больш «дасведчаным» праграмістам, то, што вы маглі б прапанаваць у якасці альтэрнатывы?
дададзена аўтар user1981855, крыніца
@LightnessRacesinOrbit мне параілі выкарыстоўваць гэты метад больш «дасведчаным» праграмістам, то, што вы маглі б прапанаваць у якасці альтэрнатывы?
дададзена аўтар user1981855, крыніца
@Nebril не магу :(
дададзена аўтар user1981855, крыніца
@Nebril не магу :(
дададзена аўтар user1981855, крыніца

7 адказы

Вам трэба апрацоўваць кожную з ліній дадзеных кропкі ў асобнасці і захоўваць іх у пэўны тып структуры дадзеных, так што яны могуць быць апрацаваны пасля загрузкі X, Y і Z. Вы павінны таксама ўключаць у сябе дадатковы код праверкі ў адваротным выпадку вы, верагодна, увесці нявызначаны паводзіны. Ёсць некалькі спосабаў зрабіць гэта, некаторыя прымусяць вас дубляваць код іншыя засяродзіцца на прызначэнне дадзеных пасля таго, як ён быў апрацаваны.

Рашэнне ніжэй ўлічвае як пацверджанне і той факт, што дадзеныя павінны быць прачытаныя з 3-х асобных ліній. Гэта не ідэальна, і чакае, што файл «myfile.txt», каб быць у дакладнай фармаце. Ён выкарыстоўвае выключэнні для апрацоўкі памылак у фармаце дадзеных і дадае структуру дадзеных для захавання дадзеных, пакуль яна загружаецца.

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

int main()
{
    const char FileName[] = "myfile.txt";
    string line;
    ifstream file;
    file.open (FileName);

    for(;;)
    {
        getline(file, line);
        if( file.eof() ) {
            break;
        } 

        if (line.size() && line[0]=='P')
        {
           //Change "int" to "double" if necessary.
            struct { int x, y, z; } data;

            for(int i = 0; i < 3; i++)
            {
                getline(file, line);
                if(line.size() > 3 && line[0] == '<' && line[2] == '>')
                {
                    string::value_type pointElement = line[1];

                   //skip spaces and process data here to get the value
                    string::size_type offset = line.find(' ');
                    if(string::npos == offset)
                    {
                        throw invalid_argument("Invalid data format");
                    }

                    stringstream sline(line.substr(offset));
                    int value;
                    if(!(sline >> value))
                    {
                        throw invalid_argument("invalid data format");
                    }


                    switch(pointElement)
                    {
                    case 'X':   data.x = value; break;
                    case 'Y':   data.y = value; break;
                    case 'Z':   data.z = value; break;
                    default:
                       //error in data format
                        throw invalid_argument("invalid data format");
                    }
                }
                else
                {
                   //error in data format
                    throw invalid_argument("invalid data format");
                }
            }

           //Do something with the values in data
            cout
                << "point[x=" << data.x
                << ", y=" << data.y
                << ", z=" << data.z
                << "]" << endl;
        }
    }
    file.close();

    return 0;
}

Пры запуску супраць «myfile.txt» вырабляе наступную выснову

<�Р> кропка [х = 2, у = 5, г = 6]
  кропка [х = 4, у = 2, г = 0]
  кропка [х = 4, у = 1, г = 2] </р>
2
дададзена
адзіная праблема, я бачу з гэтым, што не будзе выкарыстоўвацца любыя колькасці больш за 1 лічбы. пераключэнне на stringstream было б значна лепш ідэя
дададзена аўтар S Grimminck, крыніца
@SGrimminck На самай справе гэта правяраецца толькі першы знак, каб пераканацца, што ён быў разрад .. Рэальная праблема не будзе працаваць з адмоўнымі лікамі. Я абнавіў выкарыстоўваць радковы струмень і правільна праверыць EOF.
дададзена аўтар Captain Obvlious, крыніца
@ User1981855 Змена структуры дадзеных для STRUCT {двайны х, у, г; } Дадзеных; . Я абнавіў свой адказ, каб уключыць гэта і для паўнаты
дададзена аўтар Captain Obvlious, крыніца
@CaptainObvlious Гэта рашэнне, здаецца, працуе, я дадаў #include для працы з invalid_argument. Акрамя таго, як бы вы адаптаваць яго да працы з двайнікамі замест цэлых лікаў?
дададзена аўтар user1981855, крыніца

ўнутры час цыклу, вы заўсёды можаце дадаць нешта накшталт гэтага:

if(line.size() > 3){
  if(line[0] == '<' && line[1] == 'X' && line[2] == '>'){
    //enter code here
  } else if(line[0] == '<' && line[1] == 'Y' && line[2] == '>'){
    //enter code here
  } else if(line[0] == '<' && line[1] == 'Z' && line[2] == '>'){
    //enter code here
  }
}

then do something like substring the line and remove < X >/< Y >/< Z > and any spaces or special characters.

пасля таго, што вы можаце кінуць астатнюю радок усё, што вам трэба

рэдагаванне: трохі лепшы спосаб

  if(line.find("< X> ") != string::npos){
     //enter code here
  } else if(line.find("< Y> ") != string::npos){
     //enter code here
  } else if(line.find("< Z> ") != string::npos){
     //enter code here
  } 
1
дададзена
Добра, я забыўся, што.
дададзена аўтар S Grimminck, крыніца
Проста пераканайцеся, што вы праверыць даўжыню радка першай.
дададзена аўтар Captain Obvlious, крыніца

ўнутры час цыклу, вы заўсёды можаце дадаць нешта накшталт гэтага:

if(line.size() > 3){
  if(line[0] == '<' && line[1] == 'X' && line[2] == '>'){
    //enter code here
  } else if(line[0] == '<' && line[1] == 'Y' && line[2] == '>'){
    //enter code here
  } else if(line[0] == '<' && line[1] == 'Z' && line[2] == '>'){
    //enter code here
  }
}

then do something like substring the line and remove < X >/< Y >/< Z > and any spaces or special characters.

пасля таго, што вы можаце кінуць астатнюю радок усё, што вам трэба

рэдагаванне: трохі лепшы спосаб

  if(line.find("< X> ") != string::npos){
     //enter code here
  } else if(line.find("< Y> ") != string::npos){
     //enter code here
  } else if(line.find("< Z> ") != string::npos){
     //enter code here
  } 
1
дададзена
Добра, я забыўся, што.
дададзена аўтар S Grimminck, крыніца
Проста пераканайцеся, што вы праверыць даўжыню радка першай.
дададзена аўтар Captain Obvlious, крыніца

Можа быць, вы хочаце, каб разгледзець пытанне аб выкарыстанні ifstream/stringstreams, каб зрабіць вашу жыццё прасцей, хоць гэта не было б самым хуткім спосабам ...

int pt[3];
string line,dummy;

... //to where you were
  if (line[0]=='P')
    {
        num++;
        for (int i =0; i<3; ++i)
        {
            getline(file,line);
            stringstream ss(line);
            ss>>dummy;
            ss>>pt[i];
            std::cout<<"got "<<

Вы павінны таксама ўключаць у сябе sstream і fstream

1
дададзена

Вам сапраўды трэба падлічыць колькасць кропак загадзя? Чаму б проста не зрабіць адзін праход над уваходным файлам?

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

struct Point {
    Point() {}
    Point(int x_, int y_, int z_) : x(x_), y(y_), z(z_) {}

    int x, y, z;
};

istream& operator>>(istream& is, Point& p) {
    is >> ws;

    if (is.peek() != 'P') {
        is.setstate(ios::failbit);
        return is;
    }

    string pointStr;
    is >> pointStr;
    if (pointStr != "Point") {
        is.setstate(ios::failbit);
        return is;
    }

    int pointIdx;
    is >> pointIdx;

    string coordStr;
    int x, y, z;

    is >> coordStr;
    if (coordStr != "") {
        is.setstate(ios::failbit);
        return is;
    }
    is >> x;

    is >> coordStr;
    if (coordStr != "") {
        is.setstate(ios::failbit);
        return is;
    }
    is >> y;

    is >> coordStr;
    if (coordStr != "") {
        is.setstate(ios::failbit);
        return is;
    }
    is >> z;

    p = Point(x, y, z);

    return is;
}

int main() {
    ifstream fileStream("data.txt");

    string diamStr;
    fileStream >> diamStr;
    if (diamStr != "Diam")
        throw istream::failure("Badly formatted file");

    string dStr;
    fileStream >> dStr;
    if (dStr != "")
        throw istream::failure("Badly formatted file");
    double diam;
    fileStream >> diam;

    string time, date;
    fileStream >> time >> date;

    istream_iterator pointIt(fileStream);
    vector points;
    copy(pointIt, istream_iterator(), back_inserter(points));

    cout << points.size() << " points:\n";
    for_each(begin(points), end(points), [](const Point& p) {
        cout << "(" << p.x << ", " << p.y << ", " << p.z << ")\n";
    });
}
0
дададзена
у залежнасці ад прымянення, ён, магчыма, неабходна ведаць, што пазначыць гэта. самая вялікая карысць гэтага, што я магу думаць пра зачапленні. Вы павінны ведаць, што кропкі складаюць трохкутнік, як гэта, верагодна, не паслядоўна.
дададзена аўтар S Grimminck, крыніца
Калі паказчыкі не былі гарантаваныя быць паслядоўнымі вы маглі прачытаць іх і захоўваць іх, але вы ўсё роўна трэба толькі адзін праход над файлам, калі фармат дазволіў іншых дадзеных неточечными ня перамяжоўвацца з кропкамі.
дададзена аўтар mattnewport, крыніца

You could create a coordinates array like this: int coords[num*3];

Затым, захоўваць нумары каардынатаў ў адпаведнай пазіцыі, выкарыстоўваючы функцыю модуля пругкасці і знайсці становішча з паставамі модамі 3 = 0 пры х-каардынатах, паставы модамі 3 = 1 для у-каардынатаў і поз Mod 3 = 2 для Z-каардынатаў.

0
дададзена

Гэта вельмі падобна адказ S Grimminck ст.

#include 
#include 
using namespace std;
int main()
{
const char FileName[] = "myfile.txt";

int num = 0;
int x = 0;
int y = 0;
int z = 0;
string line;
std::stringstream str_parse(line);
ifstream file;
file.open (FileName);

while(file.eof() == false)
{
    getline(file, line);

    if (line[0]=='P')  
        num++;
    if( line.size() > 3 )
    {
    if( (line[0] == '<') && (line[1] == 'X') && (line[2] == '>'))
    {
       line = line.substr(3,line.size());
       str_parse>>x;//Gets the x-coordinate
    } 
    else if((line[0] == '<') && (line[1] == 'Y') && (line[2] == '>'))
    {
       line = line.substr(3,line.size());
       str_parse>>y; //Gets the y-coordinate
    } 
    else if((line[0] == '<') && (line[1] == 'Z') && (line[2] == '>'))
    {
       line = line.substr(3,line.size());
       str_parse>>z; //Gets the z-coordinate
    }
    }
}
file.close();

return 0;
}    

Гэта першы раз я выкарыстоўваю stringstream . Такім чынам, я магу памыляцца. Вы можаце выправіць мяне. :)

0
дададзена
ім будзе працытаваць капітана Obvlious тут, не забудзьцеся праверыць даўжыню радка перад выкананнем усіх праверак.
дададзена аўтар S Grimminck, крыніца
sscanf ня C ++ шлях :) Пачытайце Int з stringstream
дададзена аўтар Jerome, крыніца
@SGrimminck: Я згодны. Забыўшыся пра гэта. :)
дададзена аўтар Josh, крыніца
@Jerome Ой .. добра. На жаль! Didnt разумеюць, што! Дзякуючы. :)
дададзена аўтар Josh, крыніца