首页 > 解决方案 > 检查结构元素并将其与 C 中的用户输入进行比较

问题描述

我正在尝试在 C 中创建一个函数,该函数在包含客户信息的数据库中进行搜索,其与某些用户输入进行比较,并最终根据依赖于 Livenshtein 距离百分比的条件打印出良好的结果。

typedef struct Person_t
{
    char Name[32];
    char Email[64];
    char City[96];
    char Country[64];
} Person;  

问题来了,要求用户输入结构成员所代表的每个信息,但他只能输入他想要的,例如:姓名:Emily,电子邮件:(没有用户输入,也就是留空),城市: (留空),国家:法国。

这里的目标是仅将这些属性(Emily,Country)与数据库中的相应属性进行比较,因为:正如我所说,比较算法基于与 Livenshtein 距离相关的条件,如果该条件不通过说 50,它不会将搜索验证为“好结果”,这可能会排除好的情况,比如:

姓名:杰克,电子邮件:jack.jack@gmail.com,城市:伯明翰,国家:美国

这个客户存在于我们的“大”数据库中(假设我们有很多 Jacks 和很多来自 Birmingham 的人),并且 smbd 正在搜索对 Jack 知之甚少的信息,因此他输入:

姓名:Jackk,电子邮件:(空),城市:(空),国家:美国

(我故意弄乱拼写以显示 LD 如何有用,它的百分比仍然很高,所以不用担心)

使用 LD 的百分比条件:百分比 = (1 - LD/max(string1, string2)) * 100,我们将截止设置为 50%。

这里的问题是,如果我们将每个结构成员与其对应的结构成员(与用户输入的内容相关的结构成员)进行比较,我们就会降低它获得高百分比的可能性,因为将空字符串与“现有”字符串进行比较将使 Livenshtein 距离很大,因此百分比很低,这将带走很多好的结果。

重要的是要注意,我不想使用OR。我不知道如果他得到正确的“杰克”,它将通过(百分比= 100),由于存在太多杰克(我们正在谈论一个大数据库),这将不会有效,所以我肯定会使用AND,以确保所有用户输入尽可能接近他想要的,同时尽量减少结果的数量。

请记住,除此之外,搜索后的结果将根据百分比进行排序,因此需要彻底按照该百分比处理空白字符串。

标签: cstringsearchstructure

解决方案


这是我的评论的一个例子。

compare_field如果存在有效匹配,则该函数返回 1 并填充percentageout 参数;如果该字段无关紧要,则返回 0。

compare_record函数调用该函数 4 次,每个字段一次,并平均字段比较函数返回的百分比。

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

typedef struct Person_t {
  char Name[32];
  char Email[64];
  char City[96];
  char Country[64];
} Person;

static Person database[] = {
    {.Name = "Emily",
     .Email = "emi@x.ly",
     .City = "Paris",
     .Country = "France"},
    {.Name = "Jack",
     .Email = "jack.jack@gmail.com",
     .City = "Birmingham",
     .Country = "United States"},
    {.Name = "Jank",
     .Email = "jankjank@gmail.com",
     .City = "London",
     .Country = "United Kingdom"},
};

static int compare_field(const char *record, const char *query,
                         float *percentage) {
  if (strlen(record) == 0 || strlen(query) == 0) {
    return 0; // Ignore this field in the search
  }
  // TODO: implement real levenshtein distance here
  int distance = 0;
  for (int i = 0;; i++) {
    if (record[i] == 0 || query[i] == 0)
      break;
    if (record[i] != query[i])
      distance++;
  }
  *percentage = (1.0f - distance / (float)strlen(record)) * 100.0f;
  return 1;
}

static float compare_record(const Person *record, const Person *query) {
  float total_match_percentage = 0, temp_percentage;
  int total_match_fields = 0;


  #define COMPARE_FIELD(field)  if (compare_field(record->field, query->field, &temp_percentage)) { total_match_percentage += temp_percentage; total_match_fields++; }

  COMPARE_FIELD(Name);
  COMPARE_FIELD(Email);
  COMPARE_FIELD(City);
  COMPARE_FIELD(Country);

  #undef COMPARE_FIELD

  return total_match_percentage / (float)total_match_fields;
}

int main() {
  int n_database = sizeof(database) / sizeof(Person);
  Person query = {.Name = "Jamk", .City = "Pondon", .Country = "United K"};
  for (int i = 0; i < n_database; i++) {
    float match = compare_record(&database[i], &query);
    printf("%s: %.2f\n", database[i].Name, match);
  }
}

query源代码中,这会打印出来(因为 Emily 仍然匹配Paris 并且我没有实现完整的 Levenshtein 距离算法)......

Emily: 13.33
Jack: 72.44
Jank: 86.11

推荐阅读