0
#include <stdio.h>

int main()
{
int N, i, j, k, z, v, x, c;

printf("Determine the number of your words: \n");
scanf("%d", &N);
char dict[N][50];
char tmp[50];
for(i=0; i<N; i++)
{
    printf("Determine your %d. word: \n", i+1);
    scanf("%49s", &dict[i]);
}




for(j=1; j<N; j++)
{
    k=j;
    z=0;
    while(dict[j][z]!= '\0')
    {
        tmp[z]=dict[j][z];
        z=z+1;
    }

    
    while((dict[j][1]<dict[k-1][1]) && (k>0))
    {
        v=0;
        while(dict[k][v]!= '\0')
        {
            dict[k][v] = dict[k-1][v];
            v= v+1;
        }
        k=k-1;
    }
    x=0;
    while(dict[k][x]!= '\0')
    {
        dict[k][x]=tmp[x];
        x=x+1;
    }
    
}


for(c=0; c<N; c++)
{
    
    printf("%s \n", dict[c]);
    
}



return 0;

}

So as a junior CE student our task is to write a C code that sort the strings in a 2D array according to their first characters position in the alphabet by only using the <stdio.h> library and this is the result I get is below(I know the variables are not really bearable but I'm in a little bit of a hurry):

Determine the number of your words:
5
Determine your 1. word:
LION
Determine your 2. word:
FISH
Determine your 3. word:
TIGER
Determine your 4. word:
SNAKE
Determine your 5. word:
SEALION
LION
FISH
TIGER
SEALI
SNAKE

I get no errors just the result is faulty and I do not wish any answers. But I would be glad to be enlightened about the reasons I get this results

8
  • If not allowed to use strcmp() and strcpy(), I'd probably write my own functions for those tasks. Commented Dec 16, 2020 at 19:58
  • I tried to do that by swapping(changing the places of the second and the firs string) Commented Dec 16, 2020 at 20:00
  • Why rewrite subtle variations of the code in multiple places? And it's easier to understand the code if you are calling well-named functions instead of having to figure out what each while loop does. Commented Dec 16, 2020 at 20:03
  • Again, it's my first semestr in college and we haven't really procceded on the terms of coding(which is the subject of the second semestr) so we don't create our own functions yet Commented Dec 16, 2020 at 20:06
  • try to explain in english how are you trying to sort (what you think the could should do) Commented Dec 16, 2020 at 20:08

2 Answers 2

1

Limited to stdio.h

If you are limited to using what is provided in stdio.h, then you simply have to write similar string handling functionality to what you would require from string.h. For sorting, unless you want to use a partitioning sort like quicksort or mergesort, you would be limited to a nested loop sort -- which are simpler to write -- but much much slower. (but for a 1000 or so strings, it doesn't matter, 100,000 - then there will be a perceivable difference)

To compare strings, you can write a simple strcmp() like function that requires no additional header, e.g.

/** string compare without string.h */
int strcmp_nohdr (const char *a, const char *b)
{
    if (!a && !b) return 0;
    if ( a && !b) return 1;
    if (!a &&  b) return -1;

    for (; *a && *a == *b; a++, b++) {}

    return (*a > *b) - (*a < *b);
}

If you are not declaring an additional set of pointers to sort, then you will need to copy strings between the rows (1D arrays) in your 2D array. You can write a simple strcpy() like function that needs no header as:

/** string copy wihout string.h */
char *strcpy_nohdr (char *dest, const char *src)
{
    char *p = dest;
    
    do {
        *p++ = *src;
    } while (*src++);
    
    return dest;
}

Finally, the only other thing you need is a sort function. (you will not be able to write a quick qsort() replacement) The meager Bubblesort will do. You can write a function to sort your 2D array of strings as:

#define NCHR 50

/** bubble sort of strings in 'a' (highly inefficient) */
void bubblesort2D (char (*a)[NCHR], size_t n)
{
    size_t i, j;
    for (i = 0; i < n; i++) {
        for (j = 0; j < (n-1); j++) {
            if (strcmp_nohdr(a[j], a[j + 1]) > 0) {
                char temp[NCHR];
                strcpy_nohdr (temp, a[j + 1]);
                strcpy_nohdr  (a[j + 1], a[j]);
                strcpy_nohdr  (a[j], temp);
            }
        }
    }
}

If you put those altogether in a short example (the same used before with qsort(), you would have:

#include <stdio.h>

#define NCHR 50

/** string compare without string.h */
int strcmp_nohdr (const char *a, const char *b)
{
    if (!a && !b) return 0;
    if ( a && !b) return 1;
    if (!a &&  b) return -1;

    for (; *a && *a == *b; a++, b++) {}

    return (*a > *b) - (*a < *b);
}

/** string copy wihout string.h */
char *strcpy_nohdr (char *dest, const char *src)
{
    char *p = dest;
    
    do {
        *p++ = *src;
    } while (*src++);
    
    return dest;
}

/** bubble sort of strings in 'a' (highly inefficient) */
void bubblesort2D (char (*a)[NCHR], size_t n)
{
    size_t i, j;
    for (i = 0; i < n; i++) {
        for (j = 0; j < (n-1); j++) {
            if (strcmp_nohdr(a[j], a[j + 1]) > 0) {
                char temp[NCHR];
                strcpy_nohdr (temp, a[j + 1]);
                strcpy_nohdr  (a[j + 1], a[j]);
                strcpy_nohdr  (a[j], temp);
            }
        }
    }
}

int main (void) {
    
    char strings[][NCHR] = { "zebra", "alligators", "frogs", "racoons", "opossums" };
    size_t n = sizeof strings / sizeof *strings;
    
    bubblesort2D (strings, n);
    
    for (size_t i = 0; i < n; i++)
        puts (strings[i]);
}

Example Use/Output

The results are the same as before:

$ ./bin/sort_2d_strings_stdio
alligators
frogs
opossums
racoons
zebra

Since I originally wrote the qsort() answer, I'll leave it below as the way you would want to handle sorting (whatever array you are sorting) in practice.

In Practice Use qsort()

C provides qsort() that will sort arrays of any object based on the compare function you write to tell qsort() how elements of the array are to be compares. With strings, you just want to return the result of strcmp(). Each argument to the compare function ia a Pointers to an element of your array. Since it is a void* pointer, you must cast the pointer back to the correct type.

Recall in C that a 2D array is simply an array of 1D arrays. In your case it is a array of 50-character arrays. A pointer to an array of 50-chars has the type char (*)[50], so your qsort() compare function can be written as follows:

int cmpstr50 (const void *a, const void *b)
{
    const char  *pa = *(char (*)[50])a,
                *pb = *(char (*)[50])b;
    
    return strcmp (pa, pb);
}

Where each of the parameters is a pointer to an array of char [50]. Nothing could be easier. Moreover the algorithm used by qsort() will be orders of magnitude faster than what you write with nested loops.

A complete example for your case would be:

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

int cmpstr50 (const void *a, const void *b)
{
    const char  *pa = *(char (*)[50])a,
                *pb = *(char (*)[50])b;
    
    return strcmp (pa, pb);
}

int main (void) {
    
    char strings[][50] = { "zebra", "alligators", "frogs", "racoons", "opossums" };
    size_t n = sizeof strings / sizeof *strings;
    
    qsort (strings, n, sizeof *strings, cmpstr50);
    
    for (size_t i = 0; i < n; i++)
        puts (strings[i]);
}

Where after writing your compare function, all it takes to sort the array of strings (or array of anything) is a single call to qsort():

    qsort (strings, n, sizeof *strings, cmpstr50);

Much simpler than trying to reinvent the wheel.

Example Use/Output

$ ./bin/qsort_2d_strings
alligators
frogs
opossums
racoons
zebra

Let me know if you have further questions.

Sign up to request clarification or add additional context in comments.

2 Comments

I appriciate your answer but the problem is I cannot use almost any of this because the only library I'm permitted to use is <stdio.h> :D. I also cannot use any additional functions like int main void. I'm allowed to write code under only int main
OP is limited to using <stdio.h>. qsort() requires <stdlib.h> and sometimes <search.h>
0

This comparison is incorrect:

while((dict[j][1]<dict[k-1][1]) && (k>0))

First, if you want to compare the first character of each word, use [0] instead of [1]. This is because array indexes are zero-based in C. Second, put the k>0 comparison first, before you use k-1 as an index to the array. This will take advantage of "short circuiting" to make sure you're not using an invalid index to the array. Result:

while(k > 0 && dict[j][0] < dict[k-1][0])

Another issue is that you are not making sure your strings are null terminated when you copy them. I believe this is the reason your "SEALION" is coming out "SEALI". For example, this loop:

x=0;
while(dict[k][x]!= '\0')
{
    dict[k][x]=tmp[x];
    x=x+1;
}

You're checking for null on the destination instead of the source. Also, you stop copying at the null character, but you actually need to copy that too, or at least tack a null at the end:

x=0;
while(tmp[x]!= '\0')
{
    dict[k][x]=tmp[x];
    x=x+1;
}
dict[k][x] = '\0';

Take a close look at each of your string copy loops for such errors.

5 Comments

that is the answer I was looking for. It hurts that such mistakes can ruin the whole code. Thanks you.
Such is the nature of programming. If this answer solved your problem, please accept it by clicking the gray check mark under the answer score.
With this input it did solve my problem but a new problem occured that when I gave more input with mix order the result was not fully solved such as: Determine the number of your words: 10 Determine your 1. word: FISH Determine your 2. word: LION Determine your 3. word: SNAKE Determine your 4. word: LOPRICON Determine your 5. word: TIGER Determine your 6. word: SEALION Determine your 7. word: FRAG Determine your 8. word: GRENADE Determine your 9. word: SUPERMAN Determine your 10. word: MAGICIAN FISH LION LOPRICON SNAKE SEALION FRAG GRENADE SUPERMAN MAGICIAN TIGE
There are flaws in your sort algorithm. Try studying the bubble sort algorithm to see where it goes astray.
I've posted a new question with the same topic but I used bubblesort this time. I would be glad if you could take a peak at it. link:stackoverflow.com/questions/65344720/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.