0

Iv'e looked around but couldn't find a case similar to mine. I am trying to swap 2 string pointers to sort a char*** so I am trying to start by "sorting" only one string to see if I am right.

#include <stdio.h>

void printAllStrings(const char *** all)
{
    int i;
    int j;
    int k;

    for (i = 0; all[i] != NULL; i++)
    {
        for (j = 0; all[i][j] != NULL; j++)
        {
            for (k = 0; all[i][j][k] != NULL; k++)
            {
                printf("%c", all[i][j][k]);
            }
            printf(" ");
        }
        printf("\n");
    }
}



void swap(char **a, char **b)
{
    char *c = *a;
    *a = *b;
    *b = c;
}



void sort(const char *** all)
{
    int i;
    int j;
    char * minString = all[0][0];


    for (i = 0; all[i] != NULL; i++)
    {
        for (j = 0; all[i][j] != NULL; j++)
        {
            if (strcmp(minString, all[i][j])>0)
            {
                minString = all[i][j];
            }
        }
    }
    swap(&all[0][0], &minString);
}



void main()
{
    char * arrP1[] = { "father", "mother", NULL };
    char * arrP2[] = { "sister", "brother", "grandfather", NULL };
    char * arrP3[] = { "grandmother", NULL };
    char * arrP4[] = { "uncle","aunt", NULL };
    char ** arrPP[] = { arrP1, arrP2, arrP3, arrP4 , NULL };
    printAllStrings(arrPP);
    sort(arrPP);
    printAllStrings(arrPP);

}

The first "printAllStrings" prints normally, unsorted:

father mother
sister brother grandfather
grandmother
uncle aunt

The second "printAllStrings" prints:

aunt mother
sister brother grandfather
grandmother
uncle aunt

So it moved the first pointer over to "aunt" but the second pointer still pointed on "aunt" as well. The weird part is that I debugged and actually saw them swapping like you would expect, but when I print I see that they didn't. I can't get whats wrong here.


I was expecting the 2 strings (father,aunt) to swap (not actually swap in the memory just swap pointers) and then to be printed like so:

   aunt mother
   sister brother grandfather
   grandmother
   uncle father

Iv'e tried both answers and they both gave me something like this:

      -gibrish- mother
      sister brother grandfather
      grandmother
      uncle aunt

And no guys, I haven't gotten any warning / errors from the compiler. I still don't get it.

When I try to swap within the "sort" function by saving the "minString" indexes it works just fine, I'm just not sure if the 2 strings actually change addresses or just the pointers:

    char * tmp = all[0][0];
    all[0][0] = minString;
    all[indexI][indexJ] = tmp; 

    Output:
     aunt mother
     sister brother grandfather
     grandmother
     uncle father

Also a part of the question is to ONLY swap pointers, and not the actual strings.

Samuel Liew
  • 76,741
  • 107
  • 159
  • 260
keke
  • 53
  • 1
  • 8

2 Answers2

2

Let me start from the first obvious mistake, and make a list of the others

  1. The signature of main() MUST be one of

    • int main(void)
    • int main(int argc, char *argv[])
  2. You are comparing a character to NULL in

    for (k = 0; all[i][j][k] != NULL; k++)
    

    when trying to print the string, the correct way is

    for (k = 0; all[i][j][k] != '\0'; k++)
    
  3. The sort() function takes a const pointer and it will change the data, so I can't figure out why you thought it had to be const, it doesn't have to and in fact it SHALL NOT be.

  4. You really need to modify the pointer at the position where you need to swap the pointers, therefore you need a ** pointer holding the pointer to the string like this

    char **minString = all[0];
    

    and

    minString = &all[i][j];
    

    this way, you store the address of the pointer to the string instead of the address of the string (or the pointer, but there are too many levels of indirection so you can see how confusing it becomes).

    You then swap like this

    swap(&all[0][0], minString); 
    

    and it will probably do what you want.

When I tried to compile your code without modifying it, the list of warnings was so long that I wrote a comment saying that there were TOO many errors in your code. The real error is that you probably ignored these warnings.

Never ignore a warning unless you expected it before compiling the code, in that case it would mean that you intentionally did something that you know the compiler will issue a warning for.

If you fix these, your code will probably do what you wrote it for.

Also, try to avoid *** pointers because they make everything difficult and error prone. If you HAVE to use a *** pointer then perhaps you need a struct or something else.

I am not saying that you should NEVER use a *** pointer but at least it should be because you want to pass a ** pointer's address.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • Actually `int main(int argc, char **argv)` is also accepted ([this answer](http://stackoverflow.com/questions/2108192/what-are-the-valid-signatures-for-cs-main-function)) – Déjà vu Jan 06 '17 at 16:02
  • @ringø It's basically the same as `int main(int argc, char *argv[])`, the reason for this style is that it's clear that the argument is an array and not the a pointer to a `char` pointer. – Iharob Al Asimi Jan 06 '17 at 17:18
0

define as

char ** minString = &all[0][0];

change test and memorize min

        if (strcmp(*minString, all[i][j])>0)
        {
            *minString = &all[i][j];
        }

change swap to

swap(&all[0][0], minString);
oreubens
  • 329
  • 1
  • 9
  • 3
    It is nicer on SO to explain the error, the way to fix and then show fixed code. It looks like you have forgotten the initial steps... – Serge Ballesta Jan 06 '17 at 14:08
  • @IharobAlAsimi: Even if that I agree that there is still a lot to say on that code, this answer points to OP's current problem - but lack some useful explaination and comments... – Serge Ballesta Jan 06 '17 at 14:09