1

I have the following code, and it is currently working. However I am trying to read the tokens in three separate ways. The first token or number is to select, the second token, is to select an operation (insert or delete), and the rest of the tokens in the string should be the values to be used. The program is currently able to complete step one and two, but I don't know how to select the rest of the tokens in the string as values to be used to create a binary tree. Please help.

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include<sstream>

using namespace std;

struct trees {
   string typet;
   string nodes;
   string tree;
   trees *rec;
};

struct trees lines;
char line[50];
char* token;

int main()
{

   ifstream infile;
   infile.open("numbers.txt");
   if (!infile)
   {
      // If file doesn't exist.
      cout <<"File does not exist... \n\nPlease";
      cout <<" verify the file name and try again\n\n"<< endl;
   }

   while (infile.getline(line, 450))
   {
      string tree1, operation, data;
      istringstream liness(line);
      getline( liness, tree1,  ',' );
      getline( liness, operation, ',' );
      getline( liness, data,   ',' );
      //cout << linea  << endl;
      cout << "Type of tree: " << tree1 << " Operation to do: " << operation << " Data to use: " << data<< ".\n";
      //cout << line  << endl;

      if (tree1 == "1")
         cout<<"It is a binary tree \n\n";
   }

   infile.close();
   system ("pause");
}

This is what it is inside of the text file.

1, 1, 10, 11, 15
1, 1, 13, 20, 14
1, 1, 3, 39. 18
1, 1, 3, 3, 16

First number is to select binary tree, second number means that it will insert in the tree numbers 11 and 15 (using the first line). However my code only reads the first three numbers in every line, I understand that it is because of how it was programmed, but I don't know how to select the rest of the numbers or tokens, excluding the first two numbers that were already used, and then create a binary tree, not using boost libraries.

CrisAlfie
  • 111
  • 13
  • `while (infile)` is redundant. Also you should better use `std::string` as for the `struct trees`fields. – πάντα ῥεῖ Apr 03 '15 at 18:10
  • yes you are correct, `while (infile)` was redundant I have fixed that now thanks. I have updated the code, please check it. – CrisAlfie Apr 03 '15 at 18:18
  • _`string typet [5];`_ Nonono!!! `string typet;;` And could you please be a bit more specific about your actual problems with this code, please. – πάντα ῥεῖ Apr 03 '15 at 18:20
  • It has been fixed, the problem is, how to exclude the first two numbers or tokens already used, and use the rest of the numbers in the line or string, as you can see in my code, I have been able to read the first three numbers, but I need to read the first two numbers, and then read the rest of the string separately. – CrisAlfie Apr 03 '15 at 18:25

2 Answers2

1

Take a look at boost::split:

while (infile.getline(line, 450))
{
    std::vector<std::string> tokens;
    boost::split(tokens, line, boost::is_any_of(","), boost::token_compress_on );

    // now just use the tokens
    if (tokens[0] == "1") {
        cout<<"It is a binary tree \n\n";
    }
}

Once you have it split, you can do any number of operations you want. If you're constructing a binary tree from the 3rd through the last elements, that's the great thing about iterator pairs:

assert(tokens.size() >= 3);
construct_binary_tree(tokens.begin() + 2, tokens.end());
Barry
  • 286,269
  • 29
  • 621
  • 977
  • I am not able to use the boost libraries, altough this solution is not currently working, when I used the code, it showed me an error, `'is_any_of' is not a member of 'boost'`. Thanks. Any other solution will be welcomed. – CrisAlfie Apr 04 '15 at 01:36
  • @CrisAlfie Did you include everything? You need `` and ``. – Barry Apr 04 '15 at 12:54
  • Yes, I have fixed that now, and it is working. I have added the next two lines as well, and the second line `construct_binary_tree(tokens.begin() + 2, tokens.end());` is not working, it says that `construct_binary_tree` was not declared in this scope. – CrisAlfie Apr 05 '15 at 17:15
  • @CrisAlfie That's just an example - fill that in with whatever it is you're actually going to use the tokens for. – Barry Apr 05 '15 at 17:59
  • how can this line be used? `(tokens.begin() + 2, tokens.end());`?? how do I start using the tokens using iterator pairs? – CrisAlfie Apr 06 '15 at 04:45
1

I would suggest you to make minor modifications in your code and it should work. Instead of declaring as string, declare tree1, operation as integer and data as array of int size 3.

char ch;      //use this for comma
while (sampleFile.getline(line, 450))
{
    int tree1, operation, data[3];
    istringstream liness(line);
    //getline( liness, tree1,  ',' );
    //getline( liness, operation, ',' );
    //getline( liness, data,   ',' );
    //cout << linea  << endl;

    liness >> tree1 >> ch >> operation >> ch >> data[0] >> ch >> data[1] >> ch >> data[2];
    cout << "Type of tree: " << tree1 << " Operation to do: " << operation << " Data to use: " << data[0] << "," << data[1] << "," << data[2] << ".\n";

    if (tree1 == 1)    // remove quotes as comparing to integer
        cout<<"It is a binary tree \n\n";
}

EDIT: Since the number of tokens are not fixed and assuming that the numbers in file are comma separated, you can use vector to insert numbers into it.

  vector<int> data;
  string token;

  istringstream liness(lines);

  while(getline(liness,token,','))
  {
      int temp = stoi(token);       //convert string to int
      data.push_back(temp);         //insert into vector
  }
sam
  • 2,033
  • 2
  • 10
  • 13
  • It works, and yes it does what I am requesting, thanks, however it is still limited, and for that reason I can not apply it yet. let's say I have an unknow amount of numbers per line to use as tokens, I would need to use all of them, therefore I think a cicle would be required to use your method. – CrisAlfie Apr 04 '15 at 06:00
  • @CrisAlfie you can use an vector instead of fixed size array. – sam Apr 04 '15 at 06:10
  • Can you please give an example of that, using a vector instead of a fixed size array? – CrisAlfie Apr 04 '15 at 06:45
  • Thanks for the help. I have a big problem at the moment with the C++11 commands, and I have been searching for 3 hours, on how to update my gcc compiler so I can use the `stoi` command, but nothing has worked so far. I tried with the solutions [here](http://stackoverflow.com/questions/23063125/stoi-codeblocks-not-working) and [here](http://tehsausage.com/mingw-to-string) but I still get the error `'stoi' was not declared in this scope`, any workaround that can be made with that?. I am using codeblocks and MinGW 4.8.1. – CrisAlfie Apr 05 '15 at 18:44
  • Also, I don't know how to join both `while` loops. How to join the code provided in the first part, with the edit that you added. – CrisAlfie Apr 05 '15 at 18:47
  • I am not familiar with CodeBlocks. I found these links which might help you: [here](http://tehsausage.com/mingw-to-string) [here](http://forums.codeblocks.org/index.php?topic=19049.0) [here](http://www.cplusplus.com/forum/beginner/120836/). If these do not solve your issue, there are numerous different methods for conversion – sam Apr 05 '15 at 19:16
  • Just create [nested while loop](http://www.tutorialspoint.com/cplusplus/cpp_nested_loops.htm) – sam Apr 05 '15 at 19:20
  • This stoi error has been present since 2008, and I was not able to fix it haha!. I have used `int temp = atoi(token.c_str());` to make it work, and now it is working. If required I will update the code with these updates, however, this new edit is not skipping the first two numbers of the line, not like I arranged the code. Any further help is appreciated. – CrisAlfie Apr 06 '15 at 05:26
  • This code is working on my machine. It would be better if you update yours to see whats wrong with it. – sam Apr 06 '15 at 12:53
  • This code is skipping the first two tokens in your machine and converting to integers the rest of the tokens?. If yes, I will try to rearrange the code to make it do the same and then update it here. – CrisAlfie Apr 06 '15 at 13:11
  • Oh, why don't you want to convert all the tokens into numbers? You are only performing condition whether it is a tree or not for the first token and I believe something similar for the second one – sam Apr 06 '15 at 13:17
  • Yes that is correct, and is not a problem to convert them to integers, as long as the first two can still be used as conditions, but they must not be used when using the tokens to create the tree. The first token is to select binary tree (let's say number 1), the second token is to select wheter to insert (number 1) or to delete (number 2), but that is something I think I can implement. – CrisAlfie Apr 06 '15 at 13:29
  • You are inserting into vector. Just go to the element where you want to start using the tokens to create the tree. [Here](http://www.cplusplus.com/reference/vector/vector/?kw=vector) is details on vector. If you do something like `data.begin() + n` where n is the number of tokens you want to skip, it will work – sam Apr 06 '15 at 13:35
  • oh, that means these 2 lines `liness >> tree1 >> ch >> operation >> ch >> data[0] >> ch >> data[1] >> ch >> data[2];` and `cout << "Type of tree: " << tree1 << " Operation to do: " << operation << " Data to use: " << data[0] << "," << data[1] << "," << data[2] << ".\n";` are no longer useful on the new code, working with a vector. – CrisAlfie Apr 06 '15 at 13:49
  • You can still use those if you format is like `tree1, operation, data1, data2, data3` but if you variable number of data, use `vector` to print using `iterator` – sam Apr 06 '15 at 14:11