You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言topMatches函数输出非法随机浮点数问题排查求助

C语言topMatches()函数输出异常:scores数组出现超出[-1,1]的随机值

我是C语言初学者,学习时遇到问题:topMatches()函数输出的scores数组首尾出现超出[-1,1]范围的随机浮点数,示例输出如下:

Output #1
(-0.00000, Lisa Rose),(0.99124, Gene Seymour),(0.92447, Michael Phillips),(0.89341, Claudia Puig),(0.66285, Mick LaSalle),(0.38125, Jack Matthews),(-1.00000, Toby)
Output #2
(107185664961793568883398204719104.00000, Lisa Rose),(0.99124, Gene Seymour),(0.92447, Michael Phillips),(0.89341, Claudia Puig),(0.66285, Mick LaSalle),(0.38125, Jack Matthews),(-1.00000, Toby)
Output #3
(0.99124, Lisa Rose),(0.92447, Gene Seymour),(0.89341, Michael Phillips),(0.66285, Claudia Puig),(0.38125, Mick LaSalle),(-118195603315995709432961818167345152.00000, Jack Matthews),(-1.00000, Toby)
...

scores数组每个元素值应处于[-1,1]范围内,以下是我的代码:

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

//data types
struct mInfo
{
    char mName[20];
    float rating;
};
struct cInfo
{
    char name[20];
    struct mInfo movi[7];
};
//prototype fxns
typedef double (*sim_fp)(struct cInfo *, const char *, const char *);
double sim_D(struct cInfo *prefs, const char *person1, const char *person2);
void topMatches(sim_fp fp, struct cInfo *prefs, const char *person1, int num);
int cmpFxn (const void * a, const void * b);
void reverseFxn(float arr[], int num);

int main() 
{
    int num = 7;
    struct cInfo critics[num];
  
    critics[0] = (struct cInfo) {"Lisa Rose", {"Lady in the Water", 2.5, "Snakes on a Plane", 3.5, "Just My Luck", 3, "Superman Returns", 3.5, "The Night Listener", 3, "You, Me and Dupree", 2.5}};
    
    critics[1] = (struct cInfo) {"Gene Seymour",{"Lady in the Water", 3, "Snakes on a Plane", 3.5, "Just My Luck", 1.5, "Superman Returns", 5, "The Night Listener", 3, "You, Me and Dupree", 3.5}};
    
    critics[2] = (struct cInfo) {"Michael Phillips",{"Lady in the Water", 2.5, "Snakes on a Plane", 3, "Superman Returns", 3.5, "The Night Listener", 4}};
    
    critics[3] = (struct cInfo) {"Claudia Puig",{"Snakes on a Plane", 3.5, "Just My Luck", 3, "Superman Returns", 4, "The Night Listener", 4.5, "You, Me and Dupree", 2.5}};
    
    critics[4] = (struct cInfo) {"Mick LaSalle",{"Lady in the Water", 3, "Snakes on a Plane", 4, "Just My Luck", 2, "Superman Returns", 3, "The Night Listener", 3, "You, Me and Dupree", 2}};
    
    critics[5] = (struct cInfo) {"Jack Matthews",{"Lady in the Water", 3, "Snakes on a Plane", 4, "Superman Returns", 5, "You, Me and Dupree", 3.5}};
    
    critics[6] = (struct cInfo) {"Toby",{"Snakes on a Plane", 4.5, "Superman Returns", 4, "You, Me and Dupree",1}};
    
    topMatches(sim_D, critics, "Toby", 7);

    return 0;
}

double sim_D(struct cInfo *prefs, const char *person1, const char *person2)
{
    int i=0;
    int x=0;
    int next=0;
    int p1;
    int p2;
    float X = 0;
    float Y = 0;
    float sumSq1 = 0;
    float sumSq2 = 0;
    float pSum = 0;
    float num = 0;
    float den = 0;
    float Pscore = 0;
    int nElements =0;
    
    
    for (i=0;i<7;i++) {
        if(strcmp(prefs[i].name, person1) ==0)
        {
           p1 = i; 
        }
        else if(strcmp(prefs[i].name, person2) ==0)
        {
            p2 = i;
        }
    }
  
    for (x=0;x<7;x++) {
        for (next=0;next<7;next++) 
        {
            if (!prefs[p1].movi[x].rating && !prefs[p2].movi[next].rating);
            else if (strcmp(prefs[p1].movi[x].mName, prefs[p2].movi[next].mName) == 0)
            {
                  X += prefs[p1].movi[x].rating;
                  Y += prefs[p2].movi[next].rating;
                  sumSq1 += pow(prefs[p1].movi[x].rating,2);
                  sumSq2 += pow(prefs[p2].movi[next].rating,2);
                  pSum += (prefs[p1].movi[x].rating*prefs[p2].movi[next].rating); 
                  nElements++;
            }
        }
        next = 0;
    }
  
    num = pSum-(X*Y/nElements);

    den=sqrt((sumSq1-pow(X,2)/nElements)*(sumSq2-pow(Y,2)/nElements));
    if(den ==0) return -1;

    Pscore = num/den; 

    return Pscore;
}

void topMatches(sim_fp fp, struct cInfo *prefs, const char *person1, int num)
{
    float scores[8];
    char *buf;
    int i=0;

    for (i=0;i<num;i++)
    {
        if(strcmp(person1, prefs[i].name)==0)
        {
          continue;
        }
        scores[i] = fp(prefs, person1, prefs[i].name);
    }
  
  qsort(scores, num, sizeof(float), (*cmpFxn));
  reverseFxn(scores, num);
   printf("\n\n");
        for(i=0;i<num;i++)
        {
          if (i == num-1)
          {
            printf("(%.5f, %s)", scores[num-1], prefs[num-1].name);
          }
          else
          {
            printf("(%.5f, %s),", scores[i], prefs[i].name);
          }
        }
}
void reverseFxn(float arr[], int num)
{
  float scoresTmp[num];
  int j;
        
    for(j=0;j<num;j++)
    {
      scoresTmp[num-1-j] = arr[j];
    }
      for(j=0;j<num;j++)
      {
        arr[j]=scoresTmp[j];
      }
}
int cmpFxn (const void * a, const void * b) 
{
   return ( *(int*)a - *(int*)b );
}

问题排查与修复

1. scores数组存在未初始化的元素

在topMatches()的循环中,当遇到和person1同名的元素时,用continue跳过赋值,导致对应索引的scores[i]保留栈上的随机垃圾值。比如查询"Toby"时,i=6被跳过,scores[6]未初始化,后续排序后这个随机值会出现在数组中。

修复:跳过前给对应位置赋值,比如设为-1(自身相似度无需计算):

for (i=0;i<num;i++)
{
    if(strcmp(person1, prefs[i].name)==0)
    {
      scores[i] = -1; // 明确赋值,避免随机值
      continue;
    }
    scores[i] = fp(prefs, person1, prefs[i].name);
}

2. qsort比较函数类型错误

cmpFxn错误地将float指针转为int指针取值比较,导致浮点数被截断,排序逻辑完全错误,还可能引发未定义行为。

修复:正确处理float类型比较:

int cmpFxn(const void *a, const void *b) {
    const float *fa = (const float*)a;
    const float *fb = (const float*)b;
    if (*fa < *fb) return -1;
    if (*fa > *fb) return 1;
    return 0;
}

3. 排序后分数与人名对应关系断裂

直接对scores数组排序,但未同步排序对应的人名,导致输出时分数和人名错位。比如排序后scores[0]是最高相似度,但prefs[0].name还是原来的Lisa Rose,两者不再匹配。

修复:创建结构体绑定分数和索引,排序后按索引输出:

// 新增结构体用于绑定分数和索引
struct ScoreIndex {
    float score;
    int index;
};

// 修改topMatches函数
void topMatches(sim_fp fp, struct cInfo *prefs, const char *person1, int num)
{
    struct ScoreIndex scoreIndices[num];
    int i=0;

    for (i=0;i<num;i++)
    {
        scoreIndices[i].index = i;
        if(strcmp(person1, prefs[i].name)==0)
        {
          scoreIndices[i].score = -1;
          continue;
        }
        scoreIndices[i].score = fp(prefs, person1, prefs[i].name);
    }
  
    // 修改比较函数适配ScoreIndex
    qsort(scoreIndices, num, sizeof(struct ScoreIndex), 
          (int (*)(const void*, const void*))compareScoreIndex);
          
    printf("\n\n");
    for(i=0;i<num;i++)
    {
        int idx = scoreIndices[i].index;
        if (i == num-1)
        {
            printf("(%.5f, %s)", scoreIndices[i].score, prefs[idx].name);
        }
        else
        {
            printf("(%.5f, %s),", scoreIndices[i].score, prefs[idx].name);
        }
    }
}

// 新增ScoreIndex的比较函数
int compareScoreIndex(const void *a, const void *b) {
    const struct ScoreIndex *sa = (const struct ScoreIndex*)a;
    const struct ScoreIndex *sb = (const struct ScoreIndex*)b;
    if (sa->score < sb->score) return -1;
    if (sa->score > sb->score) return 1;
    return 0;
}

4. sim_D函数中p1、p2未初始化风险

如果循环中未找到指定的person1或person2,p1和p2会是随机值,导致后续数组访问越界。

修复:初始化p1、p2为-1,循环后检查是否找到:

int p1 = -1, p2 = -1;
for (i=0;i<7;i++) {
    if(strcmp(prefs[i].name, person1) ==0)
    {
        p1 = i; 
    }
    if(strcmp(prefs[i].name, person2) ==0)
    {
        p2 = i;
    }
}
if (p1 == -1 || p2 == -1) {
    return -1; // 未找到指定人物,返回默认值
}

内容的提问来源于stack exchange,提问作者Saucdp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 05:15:22