0

I have made one program, where you enter a few characters (10 max). It makes you a list, count average length of surnames, tell about how much different names. But the problem is, when I enter the last number (10) - it sorts me it incorrectly (like 1, 10, 2, 3, 4, 5, 6, 7, 8, 9). Beneath I will present my code.

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

struct people {
        char num[2];
        char surname[20];
        char name[10];
    } peoples[10], c;
    
int main()
{
    int i, j, k = 0, l = 0, m = 0, n = 0;
    float  s = 0;
    char str[100];
    system("chcp 1251 > nul");
    
    for (i = 0, j = 0; i < 10; i++, j++)
    {
        printf("Enter number, surname, name %d of your human: ", i + 1);
        gets(str);
        
        while (str[n] != '\n')
        {
            
            if (str[n] != ' ')
            {
                peoples[j].num[k] = str[n];
            }
            else
                break;
                
            n++;
            k++;
        }
        n++;
        k = 0;
        while (str[n] != '\n')
        {
            
            if (str[n] != ' ')
            {
                peoples[j].surname[k] = str[n];
            }
            else
                break;
                
            n++;
            k++;
        }
        n++;
        k = 0;
        while (str[n] != '\n')
        {
            
            if (str[n] != '\0')
            {
                peoples[j].name[k] = str[n];
            }
            else
                break;
                
            n++;
            k++;
        }
        n = 0;
        k = 0;
    }
    
    for (i = 0; i < 10; i++)
    {
        for (j = i + 1; j < 10; j++)
        {
            if (!strcmp(peoples[i].name, peoples[j].name))
                m = 1;
        }
        if (m == 0)
            l++;
        
        m = 0;
        
        s = s + strlen(peoples[i].surname);
    }
    
    for (i = 0; i < 9; i++)
    
        for (j = 0; j < 9; j++)
        
            if (strcmp(peoples[j].num, peoples[j+1].num) > 0)
            {
                c = peoples[j+1];
                peoples[j+1] = peoples[j];
                peoples[j] = c;
            }
        
    for (i = 0; i < 10; i++)
    {
        printf("%s ", peoples[i].num);
        printf("%s ", peoples[i].name);
        printf("%s ", peoples[i].surname);
        printf("\n");
    }
    
    printf("\nYou have %d different names\n", l);
    printf("Avarege lenght of surname is = %f\n", s / 10);
}
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Morkovka
  • 5
  • 3
  • 1
    You compare string representation of the numbers, and according to it `"1" < "10" < "2"` (same as `"Ali" < "Alice" < "Bob"`). – bereal Nov 22 '22 at 11:40
  • 1
    Never ***ever*** use `gets`! It's so [dangerous](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used) that it was removed from the C language over 11 years ago. Whatever resource you use that have taught you that, it's not a very good one. – Some programmer dude Nov 22 '22 at 11:42
  • It is only for test, I don't have any intentions to make a big program, just want to find out where is my mistake – Morkovka Nov 22 '22 at 11:51
  • 1
    Habits, good and bad, tend to stay. Please use good habits always, even for quick "test" code. – Some programmer dude Nov 22 '22 at 11:52
  • Okey, thank you. But in spite of it, in this program where is my mistake :( I have no clue( – Morkovka Nov 22 '22 at 11:54
  • 1
    Did you read the comment by @bereal? You can't compare numbers as strings, that will make `"10"` *smaller* than e.g. `"2"` (as mentioned). Either zero-pad all numbers (`"02"` will be smaller than `"10"`), or convert to actual integers for comparisons (with e.g. [`strtol`](https://en.cppreference.com/w/c/string/byte/strtol)). – Some programmer dude Nov 22 '22 at 12:00
  • Yes, but I only start mastering C. I understand problem, but don't understand which line I have to fix (what to add) – Morkovka Nov 22 '22 at 12:27
  • `strcmp(peoples[j].num, peoples[j+1].num) > 0` – Some programmer dude Nov 22 '22 at 12:29
  • this is incorrect? – Morkovka Nov 22 '22 at 12:47

1 Answers1

2

If you want to give numeric input, then use actual numeric data.

Change the num field to become an int instead of a single-character string:

struct people {
    int num;
    char surname[20];
    char name[10];
};

Use fgets to read the line:

fgets(str, sizeof str, stdin);

[Error checking left as exercise for reader]

Then use e.g. sscanf for parse your string:

sscanf(str, "%d %s %s", &peoples[j].num, &peoples[j].name, &peoples[j].name);

[Error checking left as exercise for reader]

And finally, instead of doing your own sorting use the standard qsort function:

qsort(peoples, 10, sizeof(struct people), &compare_people_num);

With the comparison function being something like this:

int compare_people_num(const void *a, const void *b)
{
    const struct people *p1 = a;
    const struct people *p2 = b:

    return p1->num - p2->num;  // Change order to reverse sort
}

Using sscanf and qsort will make your code much simpler and easier to understand.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Thank you, but I have some problems with my new code. I have attached it beneath – Morkovka Nov 22 '22 at 14:35
  • @Morkovka I had a few minutes, so I [made the full program](https://godbolt.org/z/9rzv44PM6). Read and study it carefully, look at what it does (the comments should help). Read about the subjects you don't understand in your text-books. And don't blindly copy it. – Some programmer dude Nov 22 '22 at 16:30