1

I'm trying to make a dictionary in C++ but am having trouble splitting a text file on an '=' delimiter. Ideally it would be in an array of two. I want to take the left side of the '=' of the line into array[0] and the right side into array[1] and then use array[0] as the key and array[1] as the value through a premade insert function eg. dictionary.insert(array[0], array[1]). I've already built the dictionary logic but am having trouble splitting the lines.

Here's my (terrible) code that is not using the equal sign as the delimiter and therefore putting the '=' into array[1]:

int main() {

    Dictionary englishToEsperanto;

    ifstream infile("Dictionary.txt");

    string line;
    string arr[2];

    if (infile.is_open())
    {
        while (getline(infile, line))
        {
            int i = 0;
            stringstream ssin(line);
            while (ssin.good() && i < 2) {
                ssin >> arr[i];
                ++i;
            }
            for (i = 0; i < 2; i++) {
                cout << arr[i] << ' ';
            }
                cout << endl;
        }

        infile.close();
    }
    else
    {
        cout << "Error opening file";
    }


    return 0;
}

Here's the first few lines of the text file:

aback, to take = surprizi.
abaft = posta parto.
abandon = forlasi.
abase = humiligi. [error in book: humilgi]
abash = hontigi.
abate (lower) = mallevi.
abate (speed) = malakceli.
abbey = abatejo.
abbot = abato.
abbreviate = mallongigi.
abdicate = demeti la reĝecon.
abdomen = ventro.

Thanks for looking.

i_am_so_stupid
  • 305
  • 3
  • 11
  • 3
    You can use `std::getline(infile, word, '=')` to read the key and `std::getline(infile, word);` to get the remainder of the line. – Thomas Matthews Nov 11 '16 at 16:27

3 Answers3

2

As suggested by @Thomas in comment, set '=' as delimiter for first getline, and default delimiter newline for second getline. Demo.

string before_equal, after_equal;
string arr[2];
while (getline(cin, before_equal, '=') && getline(cin, after_equal))
{
    stringstream ssin1(before_equal);
    stringstream ssin2(after_equal);
    if (ssin1.good() && ssin2.good()) {
        ssin1 >> arr[0];
        ssin2 >> arr[1];
    }
    else continue;
    cout << arr[0] << ' ' << arr[1];
    cout << endl;
}
Saurav Sahu
  • 13,038
  • 6
  • 64
  • 79
1

You can use standard data member functions of the class std::string to perform the task. Result pairs can be stored in the standard class std::vector

Here is a demonstrative program

#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <cstring>

std::string & trim( std::string &s )
{
    std::string::size_type n = 0;

    while ( n < s.size() && std::isspace( ( unsigned char )s[n] ) ) n++;

    s.erase( 0, n );

    n = s.size();

    while ( n != 0 && std::isspace( ( unsigned char )s[n-1] ) ) n--;

    s.erase( n );
}   

int main() 
{
    const char * s[] =
    {
        "aback, to take = surprizi.",
        "abaft = posta parto.",
        "abandon = forlasi.",
        "abase = humiligi. [error in book: humilgi]",
        "abash = hontigi.",
        "abate (lower) = mallevi.",
        "abate (speed) = malakceli.",
        "abbey = abatejo.",
        "abbot = abato.",
        "abbreviate = mallongigi.",
        "abdicate = demeti la reĝecon.",
        "abdomen = ventro.",
    };


    std::vector< std::pair<std::string, std::string>> dictionary;

    for ( std::string line : s )
    {
        auto n = line.find( '=' );

        std::string key, description;

        if ( n == std::string::npos )
        {
            key = line;
        }
        else
        {
            key = line.substr( 0, n );
            description = line.substr( n + 1 );
        }

        trim( key ); trim( description );

        dictionary.push_back( { key, description } );
    }


    for ( const auto &p : dictionary )
    {
        std::cout << p.first << '\t' << p.second << std::endl;
    }

    return 0;
}

Its output is

aback, to take  surprizi.
abaft   posta parto.
abandon forlasi.
abase   humiligi. [error in book: humilgi]
abash   hontigi.
abate (lower)   mallevi.
abate (speed)   malakceli.
abbey   abatejo.
abbot   abato.
abbreviate  mallongigi.
abdicate    demeti la reĝecon.
abdomen ventro.
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

If you have access to Boost, Boost.Tokenizer is what you are looking for. You can find an example here. That will return a vector of string.

Otherwise, you can use std::string::find, and implement something along these lines:

int indOfDelimiter=line.find('=');
std::string Key = line.substr(0,indOfDelimiter);
std::string Value = line.substr(indOfDelimiter+1);

In your example, there are spaces before and after '='. You might want to get rid of those by changing the delimiter in the code above with:

const char *delimiter = " = ";
int indOfDelimiter=line.find(delimiter);
std::string Key = line.substr(0,indOfDelimiter);
std::string Value = line.substr(indOfDelimiter+3);
Community
  • 1
  • 1
Jean-Emmanuel
  • 688
  • 8
  • 18