Home > Mobile >  C Problem with counting elements in the list of names
C Problem with counting elements in the list of names

Time:11-23

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 39399349349, 3443993). Beneath I will present my code. I am newbie in C, so please don't shut on me) I am convinced that sorting function is incorrect, but don't know what exactly(

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

struct people {
        int num[10];
        char surname[20];
        char name[10];
    } peoples[10], c;
    
int compare_people_num(const void *a, const void *b);

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);
        fgets(str, sizeof str, stdin);
        sscanf(str, "%d %s %s", &peoples[j].num, &peoples[j].name, &peoples[j].name);
        
        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)
            {
              qsort(peoples, 10, sizeof(struct people), &compare_people_num);
            }
        
    for (i = 0; i < 10; i  )
    {
        printf("%d ", 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);
}

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
}

CodePudding user response:

I went through your code and removed things that weren't needed. In both your input and sorting, it seemed like you were doing things twice. I tried to document the changes I made and explain why they should be made.

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

// It's generally a good idea to use #define when you have some global constants
// I made some of the constants larger than what you showed to prevent issues
#define MAX_NAME_LEN 40
#define MAX_SURNAME_LEN 40
#define NUM_PEOPLE 10
#define BUFF_LEN 100

// Separate your struct...
struct person {
    int num;
    char name[MAX_NAME_LEN];
    char surname [MAX_SURNAME_LEN];
};

// ... and array decleration
static struct person people[NUM_PEOPLE];

// I added this function, to make it easier to display a person
void print_person (const struct person * p) {
    printf("Person %d %s %s\n", p->num, p->name, p->surname);
}

// This function will print out every person in the people array
void print_people (void) {
    for (int i=0; i<NUM_PEOPLE; i  ) {
        print_person(&people[i]);
    }
}

// Compares two people by number
int compare_people_num (const void * a, const void * b) {
    struct person * p0 = (struct person *) a;
    struct person * p1 = (struct person *) b;
    return p0->num - p1->num;
}

// Compares two people by name
int compare_people_name (const void * a, const void * b) {
    struct person * p0 = (struct person *) a;
    struct person * p1 = (struct person *) b;
    return strcmp(p0->name, p1->name);
}

int main (void) {
    int i;
    char buffer[BUFF_LEN];
    for (i=0; i<NUM_PEOPLE; i  ) {
        printf("Enter number, surname, and name of person %d: ", i 1);
        fflush(stdout); // fflush makes sure that our text is shown to the user

        fgets(buffer, BUFF_LEN, stdin); // Read user input in to buffer

        // It's unclear what you were doing here
        // This sscanf line takes a line of text, and splits it into a number and two words
        // It then stores that number in people[i].num, and stores the words in name and surname
        // However, right after this, you have several while loops that appear to be manually doing the same
        // thing all over again. If you want to read all of the input in, just the line below is enough
        sscanf(buffer, "%d %s %s", &people[i].num, people[i].name, people[i].surname);
    }

    // We've read all of the people in now
    // Uncomment the next line to check out the output at this state:
    // print_people();

    // To count names, we first need to sort the people by their name
    // We do this using a qsort call
    qsort(people, NUM_PEOPLE, sizeof(struct person), compare_people_name);
    // Once the names are sorted, we'll calculate how many different names there are
    // We start the count at 1, and start checking from the second person (index 1)
    // This is because the first person will always be unqiue, and we can't compare to
    // person negative 1
    int n_names = 1;
    for (i=1; i<NUM_PEOPLE; i  ) {
        char * current = people[i].name;
        char * previous = people[i-1].name;
        if (!strcmp(current, previous)) {
            n_names   ;
        }
    }

    // Now we have to sort the people based on their num field
    // Again, in your code, it looked like you were doing this more than nessecary
    // We just have to call qsort once, as such
    qsort(people, NUM_PEOPLE, sizeof(struct person), compare_people_num);

    // We will also do a loop through to calculate the average surname length
    float avg_surname_len = 0;
    for (i=0; i<NUM_PEOPLE; i  ) {
        avg_surname_len  = (float)strlen(people[i].surname);
    }
    avg_surname_len /= (float)NUM_PEOPLE;

    // We're all done! The people are sorted by number.
    print_people();
    printf("There are %d unique names\n", n_names);
    printf("The average surnames is %f characters\n", avg_surname_len);
}
  • Related