1

So I have an array of structures called conj_gms and what I want to find a specific jogo, given its nome.

Structure:

typedef struct jogo
{
    int id;
    char equipas[2][1024];
    int pont[2];
    char nome[MAX_CHARS];
} jogo;

For example i have jogo with

nome: ucl ,
equipas[0]: fcb,
equipas[1]: bvb,
pont[0]: 2,
pont[1]

at the index 1 of conj_jogs, if i search for the string UCL i want the id of the jogo with that name, after using bsearch, which is 1.

So to this i made a function that creates a jogo and atributted them to position in conj_jgs.

The problem is that when i use bsearch i get a segmentation faul

Program:

#include<stdlib.h> 
#include<stdio.h>
#include <string.h>
#define MAX_CHARS 1024

static int id = 0;

typedef struct jogo
{
    int id;
    char equipas[2][1024];
    int pont[2];
    char nome[MAX_CHARS];
} jogo;

jogo make_game(char nome_jg[],char team1[],char team2[],int score1,int score2)
{
    jogo novo_jogo = {0};
    novo_jogo.id = id;
    strcpy(novo_jogo.equipas[0],team1);
    strcpy(novo_jogo.equipas[1],team2);
    strcpy(novo_jogo.nome,nome_jg);
    novo_jogo.pont[0] = score1;
    novo_jogo.pont[1] = score2;
    return novo_jogo;
}

int compare(const void *s, const void *d) {
    return strncmp(s, ((const jogo *)d)->nome, sizeof(((jogo *)0)->nome));
}

int main()
{
    int i; jogo* result;
    jogo conj_gms[MAX_CHARS];
    conj_gms[0] = make_game("DK","fcb","bvb",2,1);
    id++;
    conj_gms[1] = make_game("Elc","barca","rma",1,2);
    id++;
    conj_gms[2] = make_game("Class","fcp","slb",1,3);
    id++;
    conj_gms[3] = make_game("derby","slb","scp",4,1);
    id++;
    result = bsearch("Elc",conj_gms, 4, sizeof(jogo),compare);
    printf("found at index: %d",result->id);
}
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
Martim Correia
  • 483
  • 5
  • 16
  • 2
    `sizeof(((jogo *)0)->nome)` is wrong, you should use `strlen` instread. – 500 - Internal Server Error May 19 '20 at 20:00
  • i still get a segmentation fault, so whats wrong? – Martim Correia May 19 '20 at 20:07
  • `bsearch` expects the array to be sorted. Your comparison function looks at the `nome` fields, and the `nome`s are not in order: "DK", "Elc", "Class", "derby". You want: "Class", "DK", "Elc", "derby". Note that "derby" is at the end because, with the default rules C uses, lowercase letters come after uppercase letters. – Adrian McCarthy May 19 '20 at 20:38

2 Answers2

2

For starters the array of structures shall be sorted by the value of the data member nome. Your array of structures is not sorted. Otherwise you have to use a linear search.

And secondly you have to check the returned pointer of the call of bsearch

result = bsearch( "Elc", conj_gms, 4, sizeof(jogo),compare);
if ( result ) printf("found at index: %d",result->id);

As the array is not sorted by the data member nome then the returned pointer is equal to NULL.

Within the comparison function it is enough to use the function strcmp instead of the function strncmp

return strcmp(s, ((const jogo *)d)->nome );

If to sort the array

#include<stdlib.h> 
#include<stdio.h>
#include <string.h>
#define MAX_CHARS 1024

static int id = 0;

typedef struct jogo
{
    int id;
    char equipas[2][1024];
    int pont[2];
    char nome[MAX_CHARS];
} jogo;

jogo make_game(char nome_jg[],char team1[],char team2[],int score1,int score2)
{
    jogo novo_jogo = {0};
    novo_jogo.id = id;
    strcpy(novo_jogo.equipas[0],team1);
    strcpy(novo_jogo.equipas[1],team2);
    strcpy(novo_jogo.nome,nome_jg);
    novo_jogo.pont[0] = score1;
    novo_jogo.pont[1] = score2;
    return novo_jogo;
}

int cmp(const void *s, const void *d) {
    return strcmp( ((const jogo *)s)->nome, ((const jogo *)d)->nome );
}

int compare(const void *s, const void *d) {
    return strcmp(s, ((const jogo *)d)->nome );
}

int main()
{
    jogo* result;
    jogo conj_gms[MAX_CHARS];
    conj_gms[0] = make_game("DK","fcb","bvb",2,1);
    id++;
    conj_gms[1] = make_game("Elc","barca","rma",1,2);
    id++;
    conj_gms[2] = make_game("Class","fcp","slb",1,3);
    id++;
    conj_gms[3] = make_game("derby","slb","scp",4,1);
    id++;

    qsort( conj_gms, 4, sizeof( jogo ), cmp );
    result = bsearch( "Elc", conj_gms, 4, sizeof(jogo),compare);
    if ( result ) printf("found at index: %d",result->id);
} 

then you will get the expected result

found at index: 1

If you want to find an element of the array by some prefix then the comparison function can look like

int compare(const void *s, const void *d) {
    return strncmp(s, ((const jogo *)d)->nome, strlen( s ) );
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

well you should change the line

result = bsearch("Elc",conj_gms, 4, sizeof(jogo),compare);

to

jogo const* result = bsearch("Elc",conj_gms, 4, sizeof(jogo),compare);