【问题标题】:Checking and comparing structure elements to a user input in C检查结构元素并将其与 C 中的用户输入进行比较
【发布时间】:2021-02-16 14:55:42
【问题描述】:

我正在尝试在 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 的百分比条件:percentage = (1 - LD/max(string1, string2)) * 100,我们将截止设置为 50%。

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

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

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

【问题讨论】:

  • 您不能轻松地检查一个空白字符串并忽略它,或者将其视为完美匹配吗?
  • 这是我的最后一张卡片。我仍然对是否需要在比较函数之前或内部检查空白字符串感到困惑..
  • 除此之外,我真的很想以某种方式仅比较用户输入的组件,但我可能必须添加一个开关盒并询问用户他对这个人的基本了解是什么组件,并且之后重新安排比较,你觉得这有多现实?
  • 编写一个比较函数,当要比较的任一字符串为空时返回 0%(或某个不可能的值)。这样你会自动跳过糟糕的匹配。
  • 我认为这个问题可能缺乏细节,我无法提出具体建议。但是,如果检查是针对每个字段(即所有字段)percentage >= 50,则只需将用户侧的空白视为 100 即可。如果您要计算所有字段的总体百分比,则可以在计算中完全忽略这些空白。

标签: c string search structure


【解决方案1】:

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

如果存在有效匹配,compare_field 函数将返回 1 并填充 percentage 输出参数;如果该字段无关紧要,则返回 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

【讨论】:

  • 我想澄清一下,记录永远不会是空字符串,只有查询可以。很抱歉对上面的内容感到模糊,我稍后在评论中提到过,我需要根据分数对搜索后的结果进行排序,并且我不想完全丢弃空字符串,并且我同样不想为了通过最初的搜索而给他们一个高分,因为即使不是顶级结果,他们也可能表现得一样好。
  • 我会添加另一个结构 á la typedef SearchResult {Record *record; float percentage;} 你可以排序。
  • 换句话说,我会像你一样做检查(检查空白),但考虑到我需要稍后整理它,我无法继续只有当我知道我可以单独处理包含空格的数据时才使用这种方法,以免损害结果排序。
  • 查询(=过滤)是一回事,按相关性排序(可能在查询期间计算)是另一回事。
  • 感谢您的干预和所有澄清,最后一件事,只是好奇您所指的表达式的宏化效果如何(当涉及到 if 语句或一般长语句时,我从不使用宏, #define POGGERSIF (somefield) \ if (compare_field(record-&gt;somefield, query-&gt;somefield, &amp;temp_percentage)) ({ \ total_match_percentage += temp_percentage; \ total_match_fields++; \ }) 对吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多