parsing commands from an external file as commands to a datastructure

Hello everyone,

This thread is an addition to the previous ones, because i've altered the functions i was asking about, and my question is regarding implementing the program functions. my main problems are:

1)Taking input from a txt file, reading line by line, where each line becomes a vector of words, where the first word is the command( and the second and third are parameters.

2)making sure the program does what it's intended to do.

however, i cannot get it to compile and work and i've spent a lot of hours today on adding that feature and making the program work, sadly with no success. would appreciate your assistance with it:

link to the program: https://onlinegdb.com/H1_YYWxre (fixed a lot of issues as told and additional ones, but still doesn't work).
thank you so much for your help,
Last edited on
Something along these lines, perhaps:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <iostream>
#include <string>
#include <cctype>
#include <sstream>
#include <vector>
#include <fstream>

enum operation { INSERT, REMOVE, SUCCESSOR, /* ... */ INVALID = -1 };

operation string_to_op( std::string str )
{
    for( char& c : str ) c = std::tolower(c) ;
    if( str == "insert" ) return INSERT ;
    else if( str == "remove" ) return REMOVE ;
    else if( str == "successor" ) return SUCCESSOR ;
    // ...
    else return INVALID ;
}

struct command
{
    operation oper = INVALID ;
    std::string first_argument ; // may be empty if there are no arguments
    std::string second_argument ; // may be empty if there is only one argument
};

command line_to_cmd( const std::string& line )
{
    std::istringstream stm(line) ;

    command cmd ;

    std::string str ;
    if( stm >> str )
    {
        cmd.oper = string_to_op(str) ;
        switch(cmd.oper)
        {
            case INSERT:
                if( stm >> cmd.first_argument >> cmd.second_argument ) return cmd ;
                
            case REMOVE:
                if( stm >> cmd.first_argument ) return cmd ;

            case SUCCESSOR:
                if( stm >> cmd.first_argument ) return cmd ;

            // ...

            case INVALID: ;

        }
    }

    cmd.oper = INVALID ;
    return cmd ;
}

std::vector<command> get_commands( std::istream& file )
{
    std::vector<command> result ;

    std::string line ;
    while( std::getline( file, line ) ) result.push_back( line_to_cmd(line) ) ;

    return result ;
}

int main()
{
    // for testing
    std::istringstream file( "insert kkkk 341234\n remove 423423\n successor 423423\n blah blah\n" ) ;

    const auto file_cmds = get_commands(file) ;

    for( const command& cmd : file_cmds )
    {
        switch(cmd.oper)
        {
            case INSERT:
                std::cout << "INSERT " << cmd.first_argument << ' '  << cmd.second_argument << '\n' ;
                break ;

            case REMOVE:
                std::cout << "REMOVE " << cmd.first_argument << " <empty>\n" ;
                break ;

            case SUCCESSOR:
                std::cout << "SUCCESSOR " << cmd.first_argument << " <empty>\n" ;
                break ;

            case INVALID:
                std::cout << "INVALID <empty> <empty>\n" ;
        }
    }
}

http://coliru.stacked-crooked.com/a/2aca0a6019adae9c
Seems you are desperate at your program, I can feel with you from my own experience. If you worked at this long hours it could be that you are yet overwrought, and from own experience I know that such state it's bad working further on. Maybe It would help taking a break, taking a walk and letting dangling your mind.

About detecting errors at your program: If you still have segmentation fault, It would help if you could detect at which piece of code it happens. I have good experience detecting such with a technique that I name 'successive approximation'. That is writing an output message withing a piece of code and looking if it will get printed out. If not, then the segmentation fault will happen before this piece, if not, it happens after. With this technique you could narrow down the code segment till you found the erroneous chunk.

I hope that helps you somewhat, I wish you good luck at hunting ;)
it's not segmentation fault now, i've specified the errors i don't know how to resolve.

thank you very much for your reply, i'm stuck :(
I thought this looked familiar http://www.cplusplus.com/forum/beginner/244659/ and it still has the same problems as the first.

You may have changed the order of some of the functions, but you still have the sane problems.

With the changes I talked about,and one that I did not say much about, I did manage to get the program working to a point until I found other problems.

The function "insertElement" worked like this:
1
2
3
4
5
6
void insertElement(int id, std::vector<std::string> args, TBST* tree) //to verify
{
	int id1 = std::stoi(args[args.size() - 1]);
	std::string name = join(args, 0);  // <--- Changed to zero.
	tree->insert(id1, name);
}

In your original code the subscript was 1. This accesses the second element of a three element vector. In my testing element 1 is the last name. Element 2 is the ID number. Accepting that the ID number is the last element of the vector this will change the last element of the vector into an "int" using the "stoi" function. And it removes the "segmentation fault" you had in your other post.

The other change I made is in the call to "join". Using 2 here through the function off and returns the wrong information. Accepting that the ID number is the last element of the vector then the first and second elements of the vector would be the first and last name that need to be joined together.

If you are going to send 2 to the join function then in the function definition change begin to end and set up the for loop as: for (unsigned int i = 0; i < end; i++). You could also use "end" in the ternary condition.

BTW, posting the same code in different topics will not get you more help, but likely turn some people off. You have a complicated hard to follow program and not everyone will take the time to go through it. At one point I had to step through the program starting in main just to see where it went to find problems.

Hope that helps,

Andy
Lets look at one:
 In function ‘void actByInput(TBST*, std::vector<std::basic_string<char> >)’:
functionality.cpp:224:16: error: no match for ‘operator=’ (operand types are ‘std::string {aka std::basic_string}’ and ‘void’)
fileChoice = toLowerCase( setArgsFromFile[0] );

What is with the operator=’? Operand types.

Does your code really have std::string = void?

I trust that fileChoice is a std::string.
The other operand is void toLowerCase(std::string& str);

When you evaluate toLowerCase( setArgsFromFile[0] ), you will get the value that that function returns.
void
The void is no value.


How to resolve that? What do you want to achieve?
Do you want to change the setArgsFromFile[0] to lower case (if your function does that)?

Or perhaps you want just the fileChoice to be lower case?

1
2
3
4
5
toLowerCase( setArgsFromFile[0] );
fileChoice = setArgsFromFile[0];
// or
fileChoice = setArgsFromFile[0];
toLowerCase( fileChoice );
@Andy: thank you very much for your assistance and help. i am still trying to get the program to compile before i could check the functionality. regarding the order of name and id, i changed it few hours ago because it would make more sense to have an input of #name #id rather than the opposite. but i mistakenly forgot to adapt the code as well. you indeed showed me some errors i did not catch before, thank you very much. when i'll be able to compile it, i'll walk it one by one to fix them. i thought the program would be more logical the way i wrote it, but i guess i've done too many mistakes there.

@keskiverto i indeed wanted to make setArgsFromFile[0]; become lower case. the way i approached was wrong. thank you for showing me the correct way to do that. the reason i've chose to make it lowercase is if someone wrote INSERT or insert, and i wanted both to be acceptable and dealt with correctly.

anyone has any idea how can i fix the issue with ifstream? it is declared and i don't understand what i've done wrong with it.


thank you guys for helping me with such a difficult program. i'm in a non-stop learning process and i've learnt a lot from building this program.
3)functionality.cpp:298:40: error: ‘input’ was not declared in this scope
for(std::string line; std::getline(input, line, '\n'); ) ---->>> input is declared!!!
At line 295, do you forgot the std:: at ifstream? Also, if you want to use std::ifstrem you have to include <fstream> at your header file.
Last edited on
can i use std::string_view to overcome 1)functionality.cpp:233:28: error: cannot convert ‘std::string {aka std::basic_string}’ to ‘const char*’ for argument ‘1’ to ‘constexpr uint64_t hash(const char*)’
switch (hash(fileChoice))? it expects a char * m, but the input is of std::string. how can i overcome this?
Topic archived. No new replies allowed.