-2

this is part of a function that takes input from terminal and sorts them depending on what the inputs are (sorting type, a version/variation of the sorting method to use, and the size of the array). This is what I have so far:

int main(int argc, char * argv[]) { //will have 3 arguments not including function name: sortingtype, version and arr size
    int * arr = make_arr(argv[2], argv[3]); //[2]

    if (strcmp(argv[1], "sortingtype1") == 0) {
        SortingType1(arr, argv[3]); //[2][3]
    }
    else if (strcmp(argv[1], "sortingtype2") == 0) {
        SortingType2(arr, argv[3]); //[2][3]
    }
    else {
        return 0;
    }
}

void test(){ //[1]
    main("sortingtype1", "a", 10); //sortingtype, version and arr size
}

[1] I have a function test() to simulate input from terminal but I don't know if it works that way. I get an error saying that there are too many arguments to main.

[2] Whether or not I remove that testing function, I still get warnings about "passing argument (the arguments with argv[X]) makes integer from pointer without a cast".

[3] These also need to be type int and not type char*, how do I change them?

Any suggestions on how to go about this? I have seen solutions using sscanf, but would prefer a more basic solution around my skill level first for understanding.

Edit: segmentation faults from

int * SortingType2(int * arr, int len) {
    for (int i=1; i < len; i++) {
        int x = arr[i];
        int j = i;
        while ((j > 0) && (x < arr[j-1])) {
            arr[j] = arr[j-1];
            j--;
        }
        arr[j] = x;
    }
    return arr;
}

int main(int argc, char * argv[]) {
    int size;
    if (argc > 3) size = atoi(argv[3]);

    int * arr = make_arr(argv[2][0], size);

    if (strcmp(argv[1], "sortingtype1") == 0) {
        SortingType1(arr, size);
    }
    else if (strcmp(argv[1], "sortingtype2") == 0) {
        SortingType2(arr, size);
    }
    else {
        return 0;
    }
}
userrandomnums
  • 255
  • 1
  • 2
  • 13
  • 1
    You are not supposed to call `main` directly. That is basic C that is taught in the first lesson of any tutorial or text book. Please consult those. – kaylum Oct 18 '16 at 04:32
  • `sscanf` is a good choice for converting a string to an `int`. The other options are `strtol` and `atoi`. `strtol` is a little obtuse in the way it handles error checking. `atoi` simply doesn't bother. `sscanf` is the middle ground, with decent error checking that's easy to use. – user3386109 Oct 18 '16 at 04:43
  • 1
    @kaylum-- a small quibble. The C standard certainly allows recursive calls to `main()`. – ad absurdum Oct 18 '16 at 04:56
  • @kaylum: Are you confused between C++ and C? In C++, it is not allowed to call `main()` (see [What should `main()` return in C and C++](http://stackoverflow.com/questions/204476/what-should-main-return-in-c-and-c) for the details). In C, there is no prohibition against calling `main()` — it is a normal function that can be called by the user's code, and the only thing special about it is that in a hosted environment, it is the function called by the startup code. – Jonathan Leffler Oct 18 '16 at 05:39
  • 1
    @JonathanLeffler I knew someone would make that point :-) I was just too lazy to go into the details. I really meant to say there is no need to explicitly call `main` like that and that the `test` function will never be called as it is shown anyway. – kaylum Oct 18 '16 at 05:44
  • @kaylum: I'm glad I helped meet your expectations :D You're right that the code shown won't call `test()` — but the `make_arr()` and `sortingType1()` and `sortingType2()` functions could, in theory (but probably not in practice) do so. – Jonathan Leffler Oct 18 '16 at 05:46
  • What are you passing in `argv[2]`, and what is the function `make_arr()` doing? – ad absurdum Oct 19 '16 at 03:46
  • @DavidBowling `argv[2]` is a version of the sorting type (given from `argv[1]`) to use. So if `argv[2]` is "a", for example, that might mean a given array sorted already. "b" might mean it's a scrambled array. `make_arr()` makes the array for the sorted array. – userrandomnums Oct 19 '16 at 03:52
  • First, move the `return` statement out of the `else` clause and to the end of `main()`. You will get segfaults if you don't pass enough arguments, so you should have something like: `if (argc < 4) { printf("Usage:...."); exit(EXIT_FAILURE);}`, so that the program bails instead of segfaulting.Try this, and we'll go from there. – ad absurdum Oct 19 '16 at 04:03
  • I made the suggested changes to your code and put it at the end of my answer below so that you can see what I am talking about. – ad absurdum Oct 19 '16 at 04:14

2 Answers2

1

If you want to call main() from a function, then you have to pass an argument count and a pointer to an array of strings that is null terminated (see What should main() return in C and C++? for the details).

Thus, you might write:

void test(void)
{
    char *argv[] = { "sortingtype", "a", "10", 0 };
    main(3, argv);
}

It is not common to do this. There is no evidence in your code of the test() function being called.

Note that the arguments are not modifiable strings in the code shown above; normally, the arguments are modifiable. If that's going to matter, you have to work a bit harder:

void test(void)
{
    char arg0[] = "sortingtype";
    char arg1[] = "a";
    char arg2[] = "10";
    char *argv[] = { arg0, arg1, arg2, 0 };
    main(3, argv);
}

Note too that all the arguments in argv should be strings. Your original code seemed to try to pass 10 rather than "10" but that is not allowed in the argument vector (though 10 could be valid as the argument count, of course).


Please note that calling main() recursively is an eccentric thing to do at best. It is seldom actually necessary, or desirable. It is, however, legal in C — but it is not legal in C++.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • To be complete, this answer needs to provide the solution to this simple conundrum: since the startup code calls `main`, the only way that `test` can call `main` is if `main` calls `test`. But if `test` is calling a `main` that calls `test`, then you're necessarily not testing the `main` that you intended to test. – user3386109 Oct 18 '16 at 06:13
  • You said: _The only way that `test` can call `main` is if `main` calls `test`._ That statement is incomplete; the full statement should be: _The only way that `test()` can call `main()` is if `main()` calls `test()`, or a function called by (a function called by …) `main()` in turn calls `test()`._ You need conditional code somewhere to prevent infinite recursion, of course. I've used a recursive call to `main()` once, in a test program. It isn't an every day usage. – Jonathan Leffler Oct 18 '16 at 06:18
  • Please note that calling main from the application itself is very bad practice. As is recursion, most of the time. – Lundin Oct 18 '16 at 06:24
  • @Lundin: fair comment — I've added a more or less suitable note. – Jonathan Leffler Oct 18 '16 at 06:26
1

argv[] is an array of strings, so you need to convert them if you want integers. The simplest way to do this is with atoi() or sscanf(). atoi() is in stdlib.h, and sscanf() is in stdio.h. With atoi(), you just give it a string, and it returns an int. With sscanf(), you provide a string, conversion specifiers, and addresses of variables, just as in the scanf() function, the difference being that here you are scanning a string instead of stdin. Here is an example:

#include <stdio.h>   // needed for atoi()
#include <stdlib.h>  // needed for sscanf()

int main(int argc, char *argv[])
{
    int i = 0;
    int j = 0;

    /* if argv[1] exists, convert to int */
    if (argc > 1)
        i = atoi(argv[1]);

    /* if argv[2] exists, convert to int */
    if (argc > 2)
        sscanf(argv[2], "%d", &j);

    printf("%d -- %d\n", i, j);

    return 0;
}

If you compile this code and execute it you get, for example:

david scratch λ> ./a.out 123 456
123 -- 456

Working with your code:

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

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

    if (argc < 4) {
        printf("Usage: %s sortingType state size\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    size = atoi(argv[3]);

    int * arr = make_arr(argv[2], size);

    if (strcmp(argv[1], "sortingtype1") == 0) {
        SortingType1(arr, size);
    }
    else if (strcmp(argv[1], "sortingtype2") == 0) {
        SortingType2(arr, size);
    }

    return 0;
}
ad absurdum
  • 19,498
  • 5
  • 37
  • 60
  • Thanks, I used atoi but am getting segmentation fault when executing now. Tried declaring variables and using them in place of argv[X] and tried simply wrapping them inside atoi(). – userrandomnums Oct 19 '16 at 03:21
  • Can you update your question with a good example of the code that is failing for you? – ad absurdum Oct 19 '16 at 03:34
  • Okay it seems to be an issue with the arguments then (I used Jonathan Leffer's first code): `Usage: sortingtype sortingType state size` – userrandomnums Oct 19 '16 at 04:18
  • If I comment out your function calls to `make_arr()`, `SortingType1()`, and `SortingType2()` in the code I just showed above, no problems. I think that your trouble is in one of these functions. I would first look at `make_arr()`. – ad absurdum Oct 19 '16 at 04:24
  • Hmm that is so strange! I actually did that earlier to make sure it's not involving those functions, and commented them out again, and am still getting the seg fault. I will take a good look again in the morning when I'm not so tired. Thanks. – userrandomnums Oct 19 '16 at 04:30
  • I think it was a problem with Jonathan's code. I changed `main(3, argv);` to `main(4, argv);` and `char *argv[] = { "sortingtype", "a", "10", 0 };` to `char *argv[] = { 0, "sortingtype", "a", "10" };` and no seg fault now. – userrandomnums Oct 19 '16 at 04:36
  • I didn't realize that you were trying to use the `test()` function, calling `main()`. If you pass 3 arguments, then `argc` will be 4, but the way I have seen it, when you call `main()` you do `main(argc - 1, argv)`. This is what Jonathan had. Are you null-terminating the `argv` array? – ad absurdum Oct 19 '16 at 04:48
  • I'm no longer using the test function, just testing from terminal now. You were right about seg faults from calling functions too. Updated with an example. – userrandomnums Oct 20 '16 at 04:14