Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading a string and integers

Tags:

c++

What I want to do is read a line from text file which contains a two word string which has a length <= 20 and two integers, for example it may look something like this:

Name Surname 1 14

I know that if I read string, the string will be all characters until the white space, however getline() reads the whole line as a string. So how do I read a line like this ? Is there any easy way or I will have to use regular expressions ?

like image 547
Marijus Avatar asked Dec 29 '22 00:12

Marijus


2 Answers

Maybe...

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main()
{
    ifstream file( "/home/facu/text.txt", ios::in );
    string part1, part2;
    int num1, num2;

    if( !file )
        cerr << "Cant open " << endl;

    while( file >> part1 >> part2 >> num1 >> num2 )
    {
        cout << part1 << " " << part2 << " " << num1
        << " " << num2 << endl;
    }

    file.close();
    return 0;
}

Where text.txt:

JONES JONES 12 14 
MICHAEL MICHAEL 12 100
DOE DOE 15 20
like image 120
fpointbin Avatar answered Dec 30 '22 14:12

fpointbin


std::getline() is probably the best function for this. Then create some form of parser which delimits each field by whitespace. From there, you can use std::stringstream to convert the fields (in this case 2 and 3 if starting at 0) to integer values. You will obviously want to do some sort of error handling for any sort of I/O operation.

EDIT: Here is an example which my help you get started

// Example

#include <iostream>
#include <sstream>
#include <string>
#include <fstream>

#define FIELD_SIZE 4 // How many fields per line

// This is just a custom data structure to hold the data you want
struct myInfo
{
    myInfo(){} // Default ctor
    myInfo(std::string name1,std::string name2,int n1,int n2) // Ctor accepting all data
        : first(name1), last(name2), num1(n1), num2(n2) {}
    std::string first, last;
    int num1,num2;
};

// Get the initial size of what your array should be
// This is based on how many '\n's are found
int getNumLines(const std::string& input)
{
    int retval = 0;
    for(unsigned int i=0;i<input.length();++i)
        if(input[i] == '\n')
            retval++;
    return retval;
}

// Convert string to int
int convertStringToInt(const std::string& input)
{
    std::stringstream ss(input);
    int retval;
    ss >> retval;
    return retval;
}

// Parse input and store it in our structure
// Not really efficient if you have large datasets to work with
void parseAndStore(std::string input, myInfo *& myArray, int size)
{
    size_t pos = 0, pos2 = 0; // Temporary position holder
    std::string first, last, tmp1, tmp2;
    std::stringstream tmp;
    int num1, num2;
    // This is not efficient - it's merely an example
    for(int i=0;i<size;++i) // How many items to insert
        for(int j=0;j<FIELD_SIZE;++j) // How many fields
        {
            if(j < FIELD_SIZE-1)
            {
                pos2 = input.find(" ",pos+1);
                if(pos2 == std::string::npos || pos2 > input.find('\n',pos)) // Don't run over the next line
                {
                    pos = input.find('\n',pos); // Next line
                    break; // Error - invalid line format
                }
                // Relatively hacky, but this is just an example to give you an idea
                switch(j)
                {
                case 1:
                    last  = input.substr(pos,pos2-pos);
                break;
                case 2:
                    tmp1  = input.substr(pos,pos2-pos);
                break;
                default:
                    first = input.substr(pos,pos2-pos);
                break;
                }
                pos = pos2+1;
            } else { // All data collected - parse our ints and store it in our structure
                pos2 = input.find('\n',pos); // End of line
                tmp2 = input.substr(pos,pos2);

                // Convert
                num1 = convertStringToInt(tmp1);
                num2 = convertStringToInt(tmp2);

                // Insert it into our array
                myArray[i] = myInfo(first,last,num1,num2);

                pos = pos2+1; // Advance position
            }
        }
}

int main()
{
    // Read your input file - this is just an example
    std::string input("Joe Serma 1 30\nGeorge Hola 2 17\n");

    int size = getNumLines(input); // Parse the number of lines in your input
    myInfo * myArray = new myInfo[size]; // Allocate a dynamic array to store your data
    parseAndStore(input,myArray,size); // Parse this string - leave the original in tact though

    // Print contents of the array
    for(int i=0;i<size;++i)
    {
        std::cout<< std::endl << "=== Person "<< i+1 << "===" << std::endl
        << "First: "<< myArray[i].first << std::endl
        << "Last: "<< myArray[i].last << std::endl
        << "Num1: "<< myArray[i].num1 << std::endl
        << "Num2: "<< myArray[i].num2 << std::endl
        << "Num1+Num2 (For confidence of true int): "<< myArray[i].num1+myArray[i].num2 << std::endl;
    }

    delete [] myArray; // Cleanup

    return 0;
}

Regards,
Dennis M.

like image 25
RageD Avatar answered Dec 30 '22 14:12

RageD