In C, sort array of strings by string length
Asked Answered
L

4

5

So I input strings into an array mydata[10][81]

while ((ct<=10) && gets(mydata[ct]) != NULL && (mydata[ct++][0] != '\0'))

I then use a for loop to create a second array of pointers

for (i=0;i<11;i++){
    ptstr[i] = mydata[i];
}

This is where I get stuck I know I need to use strlen somehow, but I can't even conceive of how to get the length of a pointer and then re-assign that pointer a new position based on a third additional value of length

Hopefully that makes sense, I'm so lost on how to do it or explain it, I'm just trying to sort strings by length using array positions (not using something like qsort)

I did some more work on it and came up with this: any idea why its not working?

void orderLength(char *ptstr[], int num){
int temp;
char *tempptr;
int lengthArray[10];
int length = num;
int step, i, j, u;
for (i=0; i<num;i++){
    lengthArray[i] = strlen(ptstr[i]);
}
for (step=0; step < length; step++){
    for(j = step+1; j < step; j++){
          if (lengthArray[j] < lengthArray[step]){
              temp = lengthArray[j];
              lengthArray[j] = lengthArray[step];
              lengthArray[step] =temp;
              tempptr=ptstr[j];
              ptstr[j]=ptstr[step];

              }
          }
    }
    for (u=0; u<num; u++){
        printf("%s \n", ptstr[u]);
        }    
} 
Lillianalillie answered 18/11, 2014 at 19:58 Comment(8)
Use qsort and a custom comparator based on strlen.Arteriole
You might want to read about the qsort library function. Or read more about sorting algorithms.Brindabrindell
How are you planning to do the sort? With quicksort (then follow the other comment's advice) or code your own? And that while loop is awful - easy to corrupt memory by reading too long a string AND by reading too many strings... And your for loop goes one off the end of the ct array as well! (assumiing you meant mydata, not mystrings)Lahey
Hint: if you were just sorting the strings, you'd call strcmp to compare the contents. If you're sorting them by length, you compare the lengths instead (compare the values returned by strlen)Lahey
OP declared mystrings[10][81] but then for (i=0;i<11;i++) ptstr[i] = mystrings[i]; which will exceed the array bounds. Change to for (i=0;i<10;i++). I strongly advise on the use of #define to set array and other sizes, i.e. don't "hard code" every individual statement. One upshot is you can alter the limit / size if necessary in one stroke.Deconsecrate
Don't use gets().Serialize
Okay so it sounds like ill use the strcmp incorperated in a sort algorithm, but how do i feed things into the strcmp would it be something like strcmp(strlen(*ptstr[i]),strlen(*ptstr[i+1])) where im getting the value that ptstr points to and comparing itLillianalillie
@Knell: No, no, no! strlen is for comparing strings. strlen yields numbers. There is no standard function for comparing numbers, but look at Nit's answer bbewlo, which implements a suitable comparison function.Lacteal
N
10

As suggested in the comments by Deduplicator, you can use qsort defined in stdlib.h.

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

#define ROWS 4
#define MAXLEN 20

int compare (const void * a, const void * b) {
    size_t fa = strlen((const char *)a);
    size_t fb = strlen((const char *)b);
    return (fa > fb) - (fa < fb);
}

int main(int argc, const char * argv[]) {
    char arr[ROWS][MAXLEN] = {
        "abcd",
        "ab",
        "abcdefgh",
        "abc"
    };
    qsort(arr, ROWS, MAXLEN, compare);
    return 0;
}

You can see it in action over here.

Newish answered 18/11, 2014 at 20:23 Comment(6)
I doubt I'd ever use that expression. The intent of it isn't clear.Aphasic
I believe I know one possible reason to use (fa > fb) - (fa < fb) rather than fa - fb, and that would be if the expression fa - fb were to result in a numeric underflow or overflow. So in a 32-bit world, suppose fa is 2^31 - 1 and fb is negative 2^31 - 1 Then fa - fb is 2^32 - 2 which is a negative result even though fa is greater than fb. So I may have to take back what I said about simplifying that return expression!Aphasic
I just learned something, hadn't seen a return like that before!Godforsaken
@Aphasic fa, fb cannot be negative. Their type is some unsigned integer. fa - fb is never negative as long as SIZE_MAX > INT_MAX.Depew
@Depew understood. I was thinking of other more general cases which may not be size_t based. Sorry for the confusion.Aphasic
@Aphasic As your "Minor tweak:" comment received 2 up-votes, you may want to delete it especially if it gets another up-vote.Depew
N
3

To avoid to call several time strlen() on the same strings, you can use a listed chain of structures like following :

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

typedef struct  t_elem
{
    char        data[81];
    int         length;
    t_elem      *next;
};

int     main(int ac, char **av)
{   
    t_elem      *head;
    t_elem      *recent;
    t_elem      *current;

    while (/* string have to be sorted */)
    {
        if (head == NULL) {
            head = (t_elem *)malloc(sizeof(t_elem));
            head->data = //readTheFirstString();
            head->length = strlen(head->data);
            head->next = NULL;
        }
        else {
            recent = (t_elem *)malloc(sizeof(t_elem));
            recent->data = //readTheNextString();
            recent->length = strlen(recent->data);
            recent->next = NULL;

            if (recent->length < head->length) {
                recent->next = head;
                head = recent;
            }
            else {
                current = head;
                while (current->next && current->next->length < recent->length) {
                    current = current->next;
                }
                recent->next = current->next;
                current->next = recent;
            }
        }
    }

    // print the sorted chained list
    current = head;
    while (current->next) {
        printf("%s\n", current->data);
        current = current->next;
    }

    // free the list
    current = head;
    while (current->next) {
        recent = current;
        current = current->next;
        free(recent);
    }
    return (0);
}
Nisbet answered 18/11, 2014 at 20:43 Comment(0)
G
2

A really simple version might look like this. It's a bubble sort which is pretty slow for any reasonable size data but it looks like you're only sorting 11 elements so it won't matter here.

The key is the 'if' statement which compares the lengths of the two array positions. The next three lines swap them if they were out of order.

char* temp;
int length = 11;
int step, i;
for(step = 0; step < length - 1; step++)
    for(i = 0; i < length - step - 1; i++)
    {
        if(strlen(ptstr[i]) > strlen(ptstr[i+1]))
        {
            temp = ptstr[i];
            ptstr[i] = ptstr[i + 1];
            ptstr[i + 1] = temp;
        }
    }

Edit: If you want to sort by the contents of the string not the length then change the if statement to:

if(strcmp(ptstr[i], ptstr[i + 1]) > 0)

(note: you're better off using strncmp where possible)

Godforsaken answered 18/11, 2014 at 20:16 Comment(1)
if(strcmp(ptstr[i], ptstr[i + 1])) would be a bit pointless: swapping strings every time the strings are not the same. Maybe you meant if(strcmp(ptstr[i], ptstr[i + 1]) > 0).Depew
G
1
//C program to sort string based on string length.
#include<stdio.h>
#include<string.h>
int main()
{
    char a[200][200],temp[20];
    int i,j,n;
    printf("Enter no. of strings to be input = ");scanf("%d",&n);
    printf("Enter %d strings:\n",n);
    for(i=0;i<n;i++)
    scanf("%s",&a[i]);
//Sorting string based on length
    for(i=0;i<n-1;i++)
    {
        for(j=0;j<n-i-1;j++)
        {
            if(strlen(a[j])>strlen(a[j+1]))
            {
                strcpy(temp,a[j]);
                strcpy(a[j],a[j+1]);
                strcpy(a[j+1],temp);
            }
        }
    }
    printf("After Sorting :\n");
    for(i=0;i<n;i++)
    printf("%s\n",a[i]);
    return 0;
}
//Made By Capricious Coder; Happy Coding :D
Garlicky answered 20/7, 2021 at 7:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.