Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

C Problem with counting elements in the list of names

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
}

>Solution :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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);
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading