0

I was trying to swap the elements in the array (which is extremely basic, but when I try to change the index of the array, it mess up the whole array)

#include <string.h>
#include <stdio.h>
int     main(int argc, char **argv)
{
    int swap;
    int position;
    char temp[1000];
    char *i;
    swap = 1;

    while (swap == 1)
    {
        swap = 0;
        position = 1;
        while (position < (argc - 1))
        {
            if (strcmp(argv[position], argv[position + 1]) > 0)
            {
                strcpy(temp, argv[position + 1]);
                strcpy(argv[position], argv[position + 1]);
                strcpy(argv[position + 1], temp);
            }
            position++;
        }
    }
    return (0);
}

from the code above, if I put "hi" and "hello", instead of printing "hello" "hi", it brings "hello" "lo" which is super bizarre.

However, when I just simply use pointer (the code below), it works flawlessly.

#include <string.h>
#include <stdio.h>
int     main(int argc, char **argv)
{
    int swap;
    int position;
    char temp[1000];
    char *i;
    swap = 1;

    while (swap == 1)
    {
        swap = 0;
        position = 1;
        while (position < (argc - 1))
        {
            if (strcmp(*(argv + position), *(argv +position + 1)) > 0 )
            {
                i = *(argv + position);
                *(argv + position) = *(argv + (position + 1));
                *(argv + position + 1) = i;
                swap = 1;
            }
            position++;
        }
    }
    return (0);
}

could you tell me what is wrong with the first way of doing?

Gerhardh
  • 11,688
  • 4
  • 17
  • 39

2 Answers2

2

The arguments, to which the argv vector points, is usually structured like this:

"foo\0barbaz\0quux\0"

with argv[1] pointing to the "f", argv[2] pointing to "b" and argv[3] pointing to "q".

Now you can easily see, that you mess up the arguments and the pointers to them if you swap these naively; for example, if you swap "foo" and "barbaz", it looks like this:

"barbaz\0foo\0quux\0".

Fine, but now argv[2] still points to the same location, which is the second "a" in barbaz!

Your first method is even more flawed since you use the pointers from the argv vector as destinations. First, you copy foo to argv[2]:

"foo\0foo\0az\0quux\0"

and then barbaz to argv[1]

"barbaz\0\0az\0quux\0"

You see, this is completely messed up.

This is why your method doesn't work without also adjusting the pointers in the argv-vector.

Your second proposed method should indeed work flawlessly.

Ctx
  • 18,090
  • 24
  • 36
  • 51
1

In addition to @Ctx's answer regarding the layout of *argv[]you have an additional problem with your array index:

Wrong index:

        {
            strcpy(temp, argv[position + 1]);  // You store from index +1
            strcpy(argv[position], argv[position + 1]);
            strcpy(argv[position + 1], temp);  // Restore into same index.
        }

As you store and restore the same index, the copying to temp does not have any effect here. You end up with two copies of the same string.

Correct index:

        if (strcmp(*(argv + position), *(argv +position + 1)) > 0 )
        {
            i = *(argv + position);  // <<== Store from pos
            *(argv + position) = *(argv + (position + 1));
            *(argv + position + 1) = i; // <<== Restore into pos+1
            swap = 1;
        }

You store position and restore into position + 1. This is how swapping works.

Gerhardh
  • 11,688
  • 4
  • 17
  • 39