-5

Is there a way to count how many times a name appears in the struct?

This is basically what i am trying to make: Create a program that will determine the number of times a name occurs in a list.

The user will enter a name that appears then the output is the number on how many times the name entered appear in the list.

#include<stdio.h>

typedef struct Person {
    char name[50];
} Person;

void print_people(const Person *people) {
    for (size_t i = 0; people[i].name[0]; ++i)
        printf("%-20s \n", people[i].name);
}

int main() {

    Person people[] = { {"Alan"}, {"Bob"}, {"Alan"}, {"Carol"}, {"Bob"}, {"Alan"} };
    print_people(people);
    char name;

    return 0;

}
karel
  • 5,489
  • 46
  • 45
  • 50
Yuno
  • 1
  • 4
  • 1
    Create a counter variable, initialize it to zero. Iterate through your array of people and anytime one matches the name you're looking for, increment the counter. – Chris Dec 29 '21 at 02:23
  • @Chris: if u don't mind, can u show me how i'll do that? – Yuno Dec 29 '21 at 02:41
  • 1
    From `print_people` you seem to know how to do the iteration part. If you need to know how to compare strings in C... [How do I properly compare strings in C?](https://stackoverflow.com/questions/8004237/how-do-i-properly-compare-strings-in-c) – Chris Dec 29 '21 at 02:45

2 Answers2

-1

First of all, your function print_people has a bug. The line

for (size_t i = 0; people[i].name[0]; ++i)

is wrong. It will read from the array out of bounds, because the loop condition people[i].name[0] is wrong. This loop condition would only be correct if the array were terminated by an element which has name[0] set to '\0'. This was the case in the original version of your question, but not in your current version.

Therefore, you should change the line to the following:

for (size_t i = 0; i < 6; ++i)

In order to count the number of people with a certain name, all you have to do is traverse the array in the same way as you are doing it in the function print_people and count the number of times you encounter the name you are searching for:

int count_person( const Person *people, const char *target ) {

    int count = 0;

    for ( int i = 0; i < 6; i++ )
        if ( strcmp( people[i].name, target ) == 0 )
            count++;

    return count;
}

Your entire program would then look like this:

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

typedef struct Person {
    char name[50];
} Person;

void print_people(const Person *people) {
    for (size_t i = 0; i < 6; ++i)
        printf("%-20s \n", people[i].name);
}

int count_person( const Person *people, const char *target ) {

    int count = 0;

    for ( int i = 0; i < 6; i++ )
        if ( strcmp( people[i].name, target ) == 0 )
            count++;

    return count;
}

int main() {

    Person people[] = { {"Alan"}, {"Bob"}, {"Alan"}, {"Carol"}, {"Bob"}, {"Alan"} };

    printf( "Number of occurances of \"Alan\": %d\n", count_person( people, "Alan" ) );

    return 0;
}

This program has the following output:

Number of occurances of "Alan": 3
Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • How can i change the name that the program will count according to the input of the user? For example `printf("\nEnter a name to count: "); scanf("%c", &what will i use here?);` also what would be the printf code at the end? – Yuno Dec 29 '21 at 04:56
  • @Yuno: You can simply read one line of input with the function `fgets`, remove the newline character, and then call the function `count_person` with that input. I have changed the code accordingly [here](https://onlinegdb.com/AqYsgKXKA). Just hit the "Run" button. – Andreas Wenzel Dec 29 '21 at 05:06
  • Thank you so much. I don't understand some of the codes but i'll probably just research. Thanks again! – Yuno Dec 29 '21 at 05:10
  • @Yuno: The following links may help: Here is the documentation of the functions [`fgets`](https://en.cppreference.com/w/c/io/fgets) and [`strcspn`](https://en.cppreference.com/w/c/string/byte/strcspn). Also, this may be worth reading: [Removing trailing newline character from fgets() input](https://stackoverflow.com/q/2693776/12149471) – Andreas Wenzel Dec 29 '21 at 05:12
  • Thanks again. I'll give them a read. – Yuno Dec 29 '21 at 05:19
-2

You might want a function like this:

int count_person(const Person *people,const Person who) {
    int whocount = 0;

    for (size_t i = 0; people[i].name[0]; ++i)
        if (strcmp(people[i].name,who.name) == 0)
            whocount++;
    return whocount;
}
SGeorgiades
  • 1,771
  • 1
  • 11
  • 11
  • The loop conditon `people[i].name[0]` will not work, as the array is not null-terminated. It will read from the array out of bounds. You can write `i < 6` instead, as the array consists of 6 elements, or you can write `i < sizeof people / sizeof *people`, if you don't want to hard-code the length of the array in several places in your program. – Andreas Wenzel Dec 29 '21 at 03:06
  • @AndreasWenzel: literally almost have no clue what i'm doing, I've only been learning C for 4 months. – Yuno Dec 29 '21 at 03:51
  • @Yuno: In C, functions must be defined at file scope, which means they are not allowed to be inside any braces (`{}`). You can call the function `count_person` from `main`. You already did this correctly with the function `print_people`, so you just have to do the same with `count_person`. – Andreas Wenzel Dec 29 '21 at 04:02
  • How do i input a name in that function? – Yuno Dec 29 '21 at 04:05
  • @Yuno: In constrast to the function `print_people`, which takes 1 parameter, the function `count_person` takes 2 parameters. The first parameter is simply a pointer to the first element of the array (as with the function `print_people`), but the second parameter is a pointer to a string containing the name to count. So you can call the function like this from `main`: `count_person( people, "Alan" );`, and the function should return `3`. – Andreas Wenzel Dec 29 '21 at 04:14
  • @AndreasWenzel ahh i get what u mean now. Next problem is how do i use `count_person`? I apologize for my questions that might be infuriating. – Yuno Dec 29 '21 at 04:14
  • @Yuno: f you want to print the number of occurances of `"Alan"`, you can use the following line in `main`: `printf( "Number of occurances of \"Alan\": %d\n", count_person( people, "Alan" ) );` – Andreas Wenzel Dec 29 '21 at 04:17
  • @AndreasWenzel: it gave me this error `error: incompatible type for argument 2 of 'count_person' note: expected 'Person' {aka 'const struct Person'} but argument is of type 'char *'` – Yuno Dec 29 '21 at 04:21
  • @Yuno: Ah, yes, I am getting the same error. I was able to solve the problem by using a compound literal, but this is not the ideal solution: `printf( "Number of occurances of \"Alan\": %d\n", count_person( people, (Person){"Alan"} ) );` It would be better to change the function `count_person`. – Andreas Wenzel Dec 29 '21 at 04:27
  • @Yuno: I am now wrting my own answer to the question, because I think I can provide a better solution and the poster of this answer is not responding. – Andreas Wenzel Dec 29 '21 at 04:35
  • @AndreasWenzel: I dunno how u fixed it and how i can fix that. More importantly, how can i print what the user input? So it will show the occurrences of the other names on the list. – Yuno Dec 29 '21 at 04:36
  • @AndreasWenzel: Alright, better solutions are more than welcome. – Yuno Dec 29 '21 at 04:38
  • @Yuno: I have now posted my own version of the function `count_person`. The main differences are that (1) the bug is fixed, and (2) the second parameter is simply a pointer to a string, so you no longer need a compound literal when calling the function (a string literal is sufficient). – Andreas Wenzel Dec 29 '21 at 04:51
  • I downvoted your answer because it contains a bug, as mentioned in my first comment to your answer. However, I just noticed that this bug does not apply to the [original version](https://stackoverflow.com/revisions/70514490/1) of the question. OP changed the code 6 minutes before you posted your answer. Therefore, it was maybe not appropriate to downvote your answer because of this. I cannot remove my downvote now though, because it is automatically locked until the answer is edited. I will remove my downvote if you fix the bug, which, as pointed out in my first comment, is a simple fix. – Andreas Wenzel Dec 29 '21 at 05:21
  • You may want to consider changing the second parameter of `count_person`. As demonstrated in my answer, it is sufficient to pass a pointer to a string. Requiring all 50 bytes of a `struct Person` to be passed by value is rather inefficient, and also makes calling the function unnecessarily complex. For example, as pointed out in one of my comments above to OP, I was forced to use a compound literal to call your function. This is why I decided to write my own answer, in order to provide OP with an alternative. – Andreas Wenzel Dec 29 '21 at 05:41