-1

I wrote a word sorting program so that if the -r argument is present at the command line then the sorting will be done in reverse order (reverse sorting option)

I tried to store all the arguments from the command line in an array, then display them in reverse order, because I noticed that if I try to create a "for" loop for iteration (for example: for (opting = count; choosing> 0; choosing--) ), the program does not finish its execution and displays all my arguments continuously. I set the variable "opterr = 0" so that I don't get any more errors like "invalid option -m"

The program executes -r correctly, only when it is added several times it is considered as text, and when adding an unknown parameter next to the others the program executes further and does not stop. How can I fix this?

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

int main(int argc,char *argv[])
{
    int i, j, m, n, option;
    char *temp;
        
    int count = argc - 1;
    int re_count = 0;
    int y = -1;
    char* ptrr[count];


    for(i=0;i<argc;i++)
    {
        for(j=1;j<(argc-1-i);j++)
        {
            if(strcmp(argv[j],argv[j+1])>0)
                {
                    temp=argv[j];
                    argv[j]=argv[j+1];
                    argv[j+1]=temp;
                    
                }
        }
    }

    opterr = 0;
    while ((option = getopt(argc,argv,"r"))!=-1)    {

        switch(option){

                   case'r':
                                           
                       for(;optind<argc;optind++){
                          y++;  
                          m = strlen(argv[optind]);
                          ptrr[y] = (char *)calloc(count, sizeof(char)*(m+1));
                              strcpy(ptrr[y], argv[optind]);
                          re_count++;
                       }
                
                       int num = sizeof(ptrr) / sizeof(ptrr[0]) - (count - re_count);

                       for(i = num - 1; i > -1; i--) {
                        
                           printf("%s ", ptrr[i]);
                    }

                   break;

                       case'?':
                     if(optopt != NULL) {
                    fprintf(stderr, "You have entered an unknown optional argument: -%c", optopt);
                 }
                
                   break;

                      }
        printf("\n");

    }

    for(;optind<argc;optind++)  {
    
        printf("%s ",argv[optind]);

                                        }

    printf("\n");

    return 0;
}
Lorand
  • 29
  • 4
  • Did you try stepping through the code with a debugger? – Quimby May 30 '22 at 17:01
  • Have you tried running your code line by line in a debugger while monitoring the values of all variables, in order to determine in which line your program stops behaving as intended? If you did not try this, then you may want to read this: [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/q/25385173/12149471) You may also want to read this: [How to debug small programs?](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) – Andreas Wenzel May 30 '22 at 17:04
  • Aside: to reverse the sorting order you usually don't change the core sorting algorithm itself, just the comparison. So if your working ascending sort compare is something like `strcmp(x, y)>0`, changing it to `strcmp(x, y)<0` will reverse the result. – 500 - Internal Server Error May 30 '22 at 17:11
  • There are many better options that `getopt`. But if you're going to use it, don't parse the arguments in main. Factor it out into a function, and do something like `int main(int argc, char **argv) { struct args A; parse_args(&A, argc, argv); ... }`. That cruft does not belong in `main`. – William Pursell May 31 '22 at 01:59

1 Answers1

0

If I am interpreting your desired outcome correctly, you want to indicate to the user an error condition if they enter a command option other than "-r" (e.g. "-u"). And, if for some reason, the user enters in the "-r" command option more than once, the additional entries should be ignored and not treated as text and included in the sorted text. Using that as the basis of refining your code, I revised the "while" block where the command option is parsed and evaluated.

while ((option = getopt(argc,argv,"stuvxyz:"))!=-1)
{
    switch(option)
    {
        case's':
        case't':
        case'u':
        case'v':
        case'w':
        case'x':
        case'y':
        case'z':

            fprintf(stderr, "You have entered an unknown optional argument: -%c\n", option);
            return -1;
            
            break;

        case'?':
            if(optopt != 'r') /* Covers A-Z and a - q */
            {
                fprintf(stderr, "You have entered an unknown optional argument: -%c\n", optopt);
                return -1;
            }
            else
            {
                for(; optind<argc; optind++)
                {
                    if ((strcmp(argv[optind], "-r") != 0)) /* Filters out any duplicate "-r" entries */
                    {
                        y++;
                        m = strlen(argv[optind]);
                        ptrr[y] = (char *)calloc(count, sizeof(char)*(m+1));
                        strcpy(ptrr[y], argv[optind]);
                        re_count++;
                    }
                }

                int num = sizeof(ptrr) / sizeof(ptrr[0]) - (count - re_count);
                
                for(i = num - 1; i > -1; i--)
                {
                    printf("%s ", ptrr[i]);
                }
            }

            break;

        }
        
    }

To summarize what I revised, I extended the ending character check in the "getopt" function to the letter "z". In testing out that function, I found that it stops checking for command options when it reaches the entered letter code. In your original code iteration, your validation would pick up the letters "a" through "q" as invalid, but would not pick up on the letters "s" through "z". Those were just being treated as text in the sorting. So I back into allowing the proper command option of "r" by stopping the process if any other command options were accidently entered. To make sure the process ends if an incorrect command entry is made, a "return -1;" statement was added to drop out of the program and not perform any sorting.

In the sorting block, I added one additional "strcmp" check to filter out any extraneous "-r" entries.

if ((strcmp(argv[optind], "-r") != 0))

With all of that, I believe this provides you with the process you were wanting to perform in your conditional sorting. I hope that helps.

Regards.

NoDakker
  • 3,390
  • 1
  • 10
  • 11