0

I am trying to figure out how to edit my code to store 2 integers in separate int variables using strtol(). So far the code I've been given is:

while (getline(input, command)) 
{
    com = strdup(command.c_str()); 
    op = strtok(com, " \t"); 

    valstr = strtok(NULL, " \t"); 
    if (valstr != NULL) {
        val = strtol(valstr, &dummy, 10);
    }

    if (strcmp(op,"i") == 0) // insert into list
    {
        cout << "Insert " + to_string(val) << endl;
        myBST.insert(val);
    }

I understand that op = strtok(com, " \t") takes the first token of the string as the operator, such as i to insert, and stores it into the char op.

I am only confused on the val = strtol(valstr, &dummy, 10); and valstr = strtok(NULL, " \t"); code. How would I use strtol() to store a second integer into val2?

Say, for example, I have the command i 10 20. From what I understand, i would be stored into op and 10 would be stored into val. How would I store the second integer 20 into a new variable, say val2?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 1
    Side note: In C++, it is more common to use [`std::stoi`](https://en.cppreference.com/w/cpp/string/basic_string/stol) instead of [`std::strtol`](https://en.cppreference.com/w/cpp/string/byte/strtol). The function `std::strtol` is intended for backward compatibility with C. – Andreas Wenzel Nov 08 '22 at 23:55
  • Related: [How do I iterate over the words of a string?](https://stackoverflow.com/q/236129/509868) – anatolyg Nov 08 '22 at 23:55
  • 3
    I's use a `stringstream` and `>>`. – Retired Ninja Nov 08 '22 at 23:55
  • 1
    if this is c++ you need to using std::string , never strdup etc since that requires manual memory management – pm100 Nov 08 '22 at 23:58
  • Almost exactly the same as `valstr = strtok(NULL, " \t"); if(valstr != NULL) { val = strtol(valstr, &dummy, 10); }`. Only difference is you store into `val2` at the very end. Side note: When you find yourself with sequentially named or numbered variables like `val1` and `val2`, you'll often find life easier if you use an array or [array-like library container](https://en.cppreference.com/w/cpp/container/vector) and a loop. – user4581301 Nov 08 '22 at 23:59
  • 1
    Where did you get this code, by the way? If it's from an instructor, I strongly recommend supplementing your education with a some self-directed learning and a few [good books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) because they don't know C++. If you found it on the internet, don't go back to that site for programming help. – user4581301 Nov 09 '22 at 00:04
  • So within the 'if(valstr != NULL)' statement i would write another statement 'val2 = strtol(valstr, dummy, 10)'? I think i am just confused on the (valstr, &dummy, 10). – Shamil Magomedov Nov 09 '22 at 00:08
  • Yes the code was given to me by an instructor. I have to implement a couple functions for my binary search tree but to do that i am trying to figure out how I can edit the wrapper to consider multiple integer arguments from the input file. – Shamil Magomedov Nov 09 '22 at 00:10
  • 1
    amazingly enoughh command is already a std::string.. you rewally should be using canonical c++, strstream etc – pm100 Nov 09 '22 at 00:19
  • @ShamilMagomedov "*the code I've been given is*" - whoever gavee you thi code clearly does not understand C++. They are teaching you C-isms in a C++ environment instead. Not a good way to learn C++. – Remy Lebeau Nov 09 '22 at 00:20

1 Answers1

2

To answer your specific question, you would simply call strtok(NULL) and strtol() a 2nd time, eg:

string command;
char *op, *valstr;
int val, val2;
...
while (getline(input, command)) 
{
    op = strtok(&command[0], " \t"); // or command.data() in C++17 and later...

    if (strcmp(op, "i") == 0)
    {
        valstr = strtok(NULL, " \t"); 
        val = strtol(valstr, NULL, 10);

        valstr = strtok(NULL, " \t"); 
        val2 = strtol(valstr, NULL, 10);

        cout << "Insert " << val << " and " << val2 << endl;
        myBST.insert(val);
        myBST.insert(val2);
    }

That being said, you can simplify the code by using sscanf() instead of strtok()/strtol(), eg:

string command;
char op;
int val, val2, numScanned;
...
while (getline(input, command)) 
{
    numScanned = sscanf(command.c_str(), "%c %d %d", &op, &val, &val2);
    if (numScanned > 0)
    {
        if ((op == 'i') && (numScanned > 2))
        {
            cout << "Insert " << val << " and " << val2 << endl;
            myBST.insert(val);
            myBST.insert(val2);
        }
    }

Alternatively, a more C++ approach (rather than a C approach) would be to use std::istringstream instead, eg:

string command;
char op;
int val, val2;
...
while (getline(input, command)) 
{
    istringstream iss(command);
    if (iss >> op)
    {
        if ((op == 'i') && (iss >> val >> val2))
        {
            cout << "Insert " << val << " and " << val2 << endl;
            myBST.insert(val);
            myBST.insert(val2);
        }
    }
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thank you, this helped a lot. Quick question though, why would using a stringstream be a more c++ appropriate way to do this? – Shamil Magomedov Nov 09 '22 at 00:33
  • @ShamilMagomedov C and C++ follow different guiding principles and idioms. They look the same, but the way they are used has evolved in radically different directions over the last 30-something years. One good example is C++ tends toward much tighter type safety. Downside, the code can be more complicated to get compiling. Upside, you've got better odds of the code working as expected once it compiles. – user4581301 Nov 09 '22 at 00:40