0

I am trying to write a small code at the beginning of my program that runs different functions depending on the file extension of the files that are passed when calling the program from the command line.

I want to convert argv[2] into a string (called st) that I can compare with ".png", ".txt", etc. using strccmp.

I found similar solutions around SO, but none of them addressed the issue of saving any argument into a string variable. Whenever I try to use something like argv[1] or argv[2], the debugger complains that the subscript is out of range, and I am at a loss about how to get around this.

int main(int argc, char** argv)
{
    // First and simplest attempt
    sd::string st = argv[2];

    // Second attempt that also fails
    std::vector<std::string> all_arg;

    if (argc > 1) {
        all_arg.assign(argv + 1, argv + argc);
    }

    std::string st = all_arg[2];


    // Comparison
    st = st.substr(st.size() - 4, st.size() - 1);
    if (strcmp(st.c_str(), ".png")) { ... }
    else {...}      

}

2 Answers2

1

Corrected for obvious problems, your code compiles and runs just fine.

#include <iostream>
#include <vector>
#include <string>

int main( int argc, char ** argv )
{
    std::vector< std::string > all_arg;
    if ( argc > 1 )
    {
        all_arg.assign( argv + 1, argv + argc );
    }

    for ( auto str : all_arg )
    {
        std::cout << str << "\n";
    }
}

As for your comparison, that looks fishy in more than one way...

st = st.substr(check.size() - 4, check.size() - 1);

Aside from check not being defined, what happens if your string is shorter than 4 characters...?

if (strcmp(st.c_str(), ".png")) { ... }

Err... degrading string to char array through c_str() and then going through the C function strcmp()? What is that for?

Try something like this:

for ( auto str : all_arg )
{
    std::string extension;
    std::string::size_type length = str.length();

    if ( length >= 4 )
    {
         extension = str.substr( size - 4 );
    }

    if ( extension == ".png" )
    {
        std::cout << str << "is PNG!\n";
    }
}

And then think about the above being case-sensitive, and once you think about converting str to lowercase prior to comparing, consider locale, which might include Unicode. ;-)

Community
  • 1
  • 1
DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • Sorry, some mistakes came up as a result of simplifying the code to make it easy to follow in my question. I just edited it. –  Jul 23 '15 at 15:59
  • @fez55: And, considering my answer, do any problems persist? (You're still using an unchecked, hardcoded `[2]` in two places, and are using dodgy and C-style string handling on C++ strings.) – DevSolar Jul 23 '15 at 16:05
  • Yes, the code works, thank you! -- But how can I access one of the arguments at any given time? In other words, what's wrong with `std::string word = all_arg[2];` (which doesn't work outside of the `for` loop). I might be missing something very elementary, please forgive my ignorance. –  Jul 23 '15 at 16:50
  • @fez55: Your question dos not make sense. That statement should work, provided a) `all_arg` does have an element at index 2 (i.e. you passend at least *three* parameters - indices are zero-based, remember?), and b) `all_arg` is in scope, which it should be from its declaration to the end of `main`. Perhaps post another question? – DevSolar Jul 24 '15 at 05:15
  • @fez55: Is anything still unclear? If yes, do ask. If not, you might want to consider accepting the answer. (Clicking the checkmark.) – DevSolar Jul 28 '15 at 08:25
  • Done, sorry! (My company's internet settings are so that I can't post/comment on SE, I have to do so from a coffee shop, my apologies!) –  Jul 29 '15 at 10:34
1

std::vector is not needed here and first command line argument is used as argv[1] not argv[2]. Simply

int main(int argc, char ** argv) {
    if (argc == 2) {
        string st(argv[1]);
        string::size_type idx = st.rfind('.');
        if (idx != string::npos)
            st.erase(0, idx);    // Extract the extension
        . . .
    }
    . . .
}
Shreevardhan
  • 12,233
  • 3
  • 36
  • 50
  • You missed the fact that his `vector`-based solution catches *all* options, not just the first one. ;-) – DevSolar Jul 23 '15 at 13:23
  • @DevSolar I did according to his question. He initialized the vector but never used it, instead used the char buffer again. – Shreevardhan Jul 23 '15 at 13:40