vendredi 25 mars 2016

Command line arguments using if/else statements in C [on hold]

I am new to programming and this one has me baffled.

I am writing a function to be called by main that takes the command line arguments and stores them in a struct to use later. This specific example is for use with image editing, but can be used anywhere.

Desired performance: Function takes arguments from the command line. Three specific arguments are identified and checked for: -h, -o and -t. If present they will alter the struct values. Arguments -o and -t store the arguments immediately following them into their respective struct fields. Any argument that is not -h or does not have -o or -t preceding it is assumed to be the input file name and stored in flag->inputFile. If all arguments are accounted for, then flag->inputFile should remain NULL and can be tested for in the main function and program terminated if this is true.

Problem: When there is no input file specified (using the above parameters) flag->inputFile keeps getting set to -o when it is included as an argument.

Solution: Thanks to Scott this question has been answered by replacing several if statements with else if has now seemed to fix the problem, and the function appears to be working as desired. My understanding of what was happening is that the else statement was being run in every iteration of i unless the -t argument was included, since it was the statement immediately before the else

The compiler I'm using is gcc and this is my code. (I know my struct is not packed, I'm still trying to get my head around this and can't see how it would result in what I'm seeing. Segmentation fault, yes, but not this?)

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

struct PROMPTFLAGS {
    int help;    // Change from NULL if -h argument present
    char * outputFile;    // Store argument after -o as the output file
    char * inputFile;    // Argument not paired with a flag stored here as input file
    float threshold;    // Stores a value to use in image manipulation in main
};

struct PROMPTFLAGS * parsargs(int argc, char * argv[]) {
    struct PROMPTFLAGS* flag = malloc(sizeof(struct PROMPTFLAGS));
    int i;
    printf("argc: %d\n",argc);
    for (i = 1; i < argc; i++) {
        char * arg = argv[i];
        int str_aft = i+1;    // Allows the next string to be used in this iteration of the loop
        if (strcmp(arg,"-h") == 0) {
            flag->help = 1;
        }
        if (strcmp(arg,"-o") == 0) {    // Changing this to 'else if' seems to be a fix
            flag->outputFile = argv[str_aft];
            i++;        // Skips over next arg since already read by argv[str_aft]
        }
        if (strcmp(arg,"-t") == 0) {    // Changing this to 'else if' seems to be a fix
            flag->threshold = strtod(argv[str_aft],NULL);
            i++;        // Skips over next arg since already read by argv[str_aft]
        }
        else {
            flag->inputFile = arg;
        }
    }
    return flag;
}

int main(int argc, char* argv[]) {

    struct PROMPTFLAGS * flags;
    flags = parsargs(argc, argv);
    printf("Help = %d\n",flags.help);
    printf("Output = %s\n",flags.outputFile);
    printf("Input = %s\n",flags.inputFile);
    printf("Threshold = %s\n",flags.threshold);

return 0;
}

I apologise for the poor format of the first version of this question and hope that this edit is better. I have made the functions' desired outcomes and the problem I encountered clearer and removed most of the test prints I had through the code and added some comments. I have also included the solution to my problem (provided by another user) and my understanding of what was happening in the broken code.

If people still think this is a poor question or of no use to anyone else then I'm happy to take it down, but have edited and left it up hoping it can help someone else.

This is my first post on stack overflow and I thank everyone for their help and patience while I learn to code and the best manner to post questions.

Aucun commentaire:

Enregistrer un commentaire