Author Topic: Need Help Processing Command Line Arguments for Program  (Read 1755 times)

0 Members and 1 Guest are viewing this topic.

Offline Recon

  • Serf
  • *
  • Posts: 46
  • Cookies: 23
  • Arguing with Computer
    • View Profile
Need Help Processing Command Line Arguments for Program
« on: January 11, 2014, 12:35:02 am »
Dear all,

I have a bunch of perfectly functional pieces of a program that work great when I call them from main and do exactly what I want, but I can't seem to get the program to determine which to call based on command line arguments. According to this the method I'm trying to use ought to work. Am I missing something?

NOTE: Realized I forgot to comment in the code what the arguments should be. If there is just one argument, the program parses it as the path of a text file to reverse or as a flag, and if there are two, the program parses the first as a flag and the second as the path of the text file. The single-argument version with the path only is working fine, but neither "flag" version is working correctly.

Code: [Select]
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>

using namespace std;

string readIn(string filename);
string reverseStringByLine(string input);
string reverseManualInput();
string reverseString(string input);
void displayUsage();
void displayUsagePossibleError();
void reverseTextFile(string filename);
void reverseTextFileByLine(string filename);
void writeOut(string filename, string buffer);

int main(int argc, char* argv[]) {
    switch (argc) {
    case 2:
        if (argv[1] == "-m" || argv[1] == "/m" || argv[1] == "-M" || argv[1] == "/M") {
            reverseManualInput();
            cin.get();
        } else {
            reverseTextFile(argv[1]);
        }
        break;
    case 3:
        if (argv[1] == "-l" || argv[1] == "/l" || argv[1] == "-L" || argv[1] == "/L") {
            reverseTextFileByLine(argv[2]);
        } else displayUsage();
        break;
    default:
        displayUsage();
        break;
    }
}

string readIn(string filename) {
    ifstream in (filename);
    string buffer;
    if (in.is_open()) {
        in.seekg(0, std::ios::end);
        buffer.resize(in.tellg());
        in.seekg(0, std::ios::beg);
        in.read(&buffer[0], buffer.size());
        in.close();
        return buffer;
    } else {
        displayUsagePossibleError();
    }
}

string reverseManualInput() {
    string input;
    string output;
    getline(cin, input);
    output = reverseString(input);
    return output;
}

string reverseStringByLine(string input) {
    string buffer1;
    string buffer2;
    string output;
    int newLineCounter = 0;
    for(int i = 0; i < input.length(); i++) {
        if (input[i] == '\n') {
            buffer1 = input.substr(0, i);
            buffer2 = reverseString(buffer1) + '\n';
            output.append(buffer2);
            input.erase(0, i + 1);
            i = 0;
            newLineCounter++;
        }
    }
    string lastLine = input.substr(0, input.length() - newLineCounter);
    output.append(reverseString(lastLine));
    return output;
}

string reverseString(string input) {
    string output;
    for (int i = input.length() - 1; i >= 0; i--) {
        output.push_back(input.at(i));
    }
    return output;
}

void displayUsage() {
    cout << "\nProper Usage: Reverse-Text.exe [-m] [-l] fullpath.txt\n\n"
        << "Only one of the flags may be used at once, and either /m and /l or -m and -l will work. "
        << "-m allows the program to accept a single line of manual input, while -l tells the program "
        << "to reverse each line of the text file individually, preserving the order of the lines.";
    return;
}

void displayUsagePossibleError() {
    cout << "\nAn error was encountered. Please double-check the proper usage.\n";
    displayUsage();
}

void reverseTextFile(string filename) {
    string buffer1 = readIn(filename);
    string buffer2 = reverseString(buffer1);
    for(int i = 0; i < buffer2.length(); i++) {
        if (buffer2[i] == '\n') {
            buffer2.erase(0, 1);
        }
    }
    writeOut(filename, buffer2);
}

void reverseTextFileByLine(string filename) {
    string buffer1 = readIn(filename);
    string buffer2 = reverseStringByLine(buffer1);
    writeOut(filename, buffer2);
}

void writeOut(string filename, string buffer) {
    ofstream out(filename);
    if (out.is_open()) {
        out << buffer;
        out.close();
    } else {
        displayUsagePossibleError();
    }
}
« Last Edit: January 11, 2014, 12:39:14 am by Recon »

Offline Matriplex

  • Knight
  • **
  • Posts: 323
  • Cookies: 66
  • Java
    • View Profile
Re: Need Help Processing Command Line Arguments for Program
« Reply #1 on: January 11, 2014, 01:21:26 am »
According that article you can embed Python. I would use Python's OptionParser, but that's just me and I am strange and do things terribly inefficiently. Have you tried just printing out argv to make sure you're getting the positioning in the array correct? I know that in Python the first arg is actually the .py file but that is somewhat different from other languages.
\x64\x6F\x75\x65\x76\x65\x6E\x00

Offline vezzy

  • Royal Highness
  • ****
  • Posts: 771
  • Cookies: 172
    • View Profile
Re: Need Help Processing Command Line Arguments for Program
« Reply #2 on: January 11, 2014, 01:46:21 am »
According that article you can embed Python. I would use Python's OptionParser, but that's just me and I am strange and do things terribly inefficiently. Have you tried just printing out argv to make sure you're getting the positioning in the array correct? I know that in Python the first arg is actually the .py file but that is somewhat different from other languages.

You're seriously suggesting he use Python's C API to process fucking command line arguments?

What the fuck?

Anyway, OP, I'd recommend looking into getopt (honestly) or boost::program_options. Your code doesn't seem to compile on GNU/Linux.

You should look into refactoring your event loop though, something like this, perhaps?...

Code: (C) [Select]
int main(int argc, char *argv[]) {
      switch(argc) {
      case "-m":
             reverseManualInput();
             cin.get();
             // so on and so forth...

Having all these redundant command line styles is an antipattern, anyway. You should only stick to one well defined style (usually the typical hyphen), so as to maintain consistency and clarity.

getopt is still the standard for C/++, you can also try more basic if-else if blocks as documented here.
« Last Edit: January 11, 2014, 01:47:08 am by vezzy »
Quote from: Dippy hippy
Just brushing though. I will be semi active mainly came to find a HQ botnet, like THOR or just any p2p botnet

Offline Matriplex

  • Knight
  • **
  • Posts: 323
  • Cookies: 66
  • Java
    • View Profile
Re: Need Help Processing Command Line Arguments for Program
« Reply #3 on: January 11, 2014, 04:39:29 am »
I'm not suggesting it, I am simply stating that I would do it that way, because as I said, I am terribly inefficient and make silly decisions. No need to flip out man, just responding to a post.
\x64\x6F\x75\x65\x76\x65\x6E\x00

Offline bluechill

  • Cybermancer
  • Royal Highness
  • ****
  • Posts: 682
  • Cookies: 344
  • I am the existence in these walls
    • View Profile
Re: Need Help Processing Command Line Arguments for Program
« Reply #4 on: January 11, 2014, 06:25:24 am »
You're seriously suggesting he use Python's C API to process fucking command line arguments?

What the fuck?

Anyway, OP, I'd recommend looking into getopt (honestly) or boost::program_options. Your code doesn't seem to compile on GNU/Linux.

You should look into refactoring your event loop though, something like this, perhaps?...

Code: (C) [Select]
int main(int argc, char *argv[]) {
      switch(argc) {
      case "-m":
             reverseManualInput();
             cin.get();
             // so on and so forth...

Having all these redundant command line styles is an antipattern, anyway. You should only stick to one well defined style (usually the typical hyphen), so as to maintain consistency and clarity.

getopt is still the standard for C/++, you can also try more basic if-else if blocks as documented here.

*rolls his eyes*

You realize argc is the argument *count* not the arguments?

argc should not be equal to a string period and your code should NOT compile.  Furthermore, switch statements can ONLY use things which can be converted to numbers and a string "-m" cannot be.  This is why you never see double quotes, only single quotes in switch statements because single quotes specify a character which is an integer value.  If you want to use a switch statement you first have to parse out the '-' then you can compare the short hand but if you also want long hand (--example) then you need to use if statements or some combination.  Also if you're using C, don't fucking use python.  If you want to use python, use python but don't use a slow, interpreted, scripting language in something as fast as C.

argv[0] is the program name w/ execution path
argv[1] is the first argument etc.

argc == 1 means no arguments
argc == 2 means one argument, etc.

Code: [Select]
int main(int argc, char** argv)
{
    int i;
    for (i = 0;i < argc;i++)
    {
        if (strncmp(argv[i], "-m", 2) == 0)
            // has -m option
        // etc.
    }
}
I have dreamed a dream, but now that dream has gone from me.  In its place now exists my own reality, a reality which I have created for myself by myself.

Offline Stackprotector

  • Administrator
  • Titan
  • *
  • Posts: 2515
  • Cookies: 205
    • View Profile
Re: Need Help Processing Command Line Arguments for Program
« Reply #5 on: January 11, 2014, 12:21:57 pm »
What a terrible advices here :P Bluechill's advice is correct use strNcmp not strcmp to check if a string equals another. I can advise you to have a set of boolean values, maybe in a struct called 'options' or commandlinearguments and set the flags when you find the corresponding flags "-c". Be creative but when you write C keep it to C, if you can't handle C and revert to python libs, well go back to Python and get your basics straight:D
~Factionwars

Offline vezzy

  • Royal Highness
  • ****
  • Posts: 771
  • Cookies: 172
    • View Profile
Re: Need Help Processing Command Line Arguments for Program
« Reply #6 on: January 11, 2014, 02:42:44 pm »
Fuck. I just made a total fool of myself by responding to posts while in an inebriated state last night.

Thank you for being the voice of reason.
Quote from: Dippy hippy
Just brushing though. I will be semi active mainly came to find a HQ botnet, like THOR or just any p2p botnet

Offline Recon

  • Serf
  • *
  • Posts: 46
  • Cookies: 23
  • Arguing with Computer
    • View Profile
Re: Need Help Processing Command Line Arguments for Program
« Reply #7 on: January 12, 2014, 03:29:44 am »
What a terrible advices here :P Bluechill's advice is correct use strNcmp not strcmp to check if a string equals another. I can advise you to have a set of boolean values, maybe in a struct called 'options' or commandlinearguments and set the flags when you find the corresponding flags "-c". Be creative but when you write C keep it to C, if you can't handle C and revert to python libs, well go back to Python and get your basics straight:D

Advice taken.

Code: [Select]
int main(int argc, char** argv)
{
    int i;
    for (i = 0;i < argc;i++)
    {
        if (strncmp(argv[i], "-m", 2) == 0)
            // has -m option
        // etc.
    }
}

Thanks mightily. I've recoded to use strncmp and an iterator.