C语言 我应该如何修复这些垃圾值?

63lcw9qa  于 2023-01-20  发布在  其他
关注(0)|答案(2)|浏览(129)

我是一个C语言的学徒,试图在这里学习一些东西。我遇到了一个问题,我希望我能自己解决它。但是,我是一个短 Package 器和相当容易拖延,所以我需要你的良好支持。正如标题明确地说,我不知道为什么我的topMatches()函数输出一些随机浮点值,在scores[]数组的开头和结尾打印出来。

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)
...

该值应在-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 );
}

scores[]数组中每个元素的值必须在-1到1的范围内。

zujrkrfu

zujrkrfu1#

至少这些问题:

    • 比较函数错误**

qsort()是用floatcmpFxn的数组调用的,但是cmpFxn()比较的是int。* 1
需要转换为float。* 2

// return (*(int*)a - *(int*)b )
return (*(float*)a > *(float*)b ) - (*(float*)a < *(float*)b );

使用return (*(float*)a - *(float*)b ),因为float差值可能会溢出int范围或截断为0。

    • 代码风险sqrt(some_negative)**

注意轻微的浮点伪像,它会导致从数学上讲永远不应小于0的负数。

// den=sqrt((sumSq1-pow(X,2)/nElements)*(sumSq2-pow(Y,2)/nElements));
t = (sumSq1-pow(X,2)/nElements)*(sumSq2-pow(Y,2)/nElements);
den = t >= 0.0 ? sqrt(t) : 0;
    • x1米10纳米1 x与x1米11纳米1 x的对比**

代码对于混合floatdouble对象和函数是随意的。建议仅使用double
出于 * 调试 * 目的,使用#define float double临时执行此操作非常简单。

  • 1个

cmpFxn()对于int也是弱比较函数,因为它有int溢出的风险。

// return ( *(int*)a - *(int*)b );
return (*(int*)a > *(int*)b ) - (*(int*)a < *(int*)b );

如果涉及到非数字,那么比较就会更加复杂,现在让我们假设情况并非如此。

7uhlpewt

7uhlpewt2#

1.意外的变量输出提示正在使用未初始化的数据。在struct cInfo中,您有一个成员struct mInfo movi[7];,但在main()中分配了其中的3到6个成员。通过从分配切换到初始化,那些未显式设置的记录将初始化为零。这似乎足以获得一致的输出。

int main() {
    struct cInfo critics[] = {
        {"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}
        }},
        {"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}
        }},
        {"Michael Phillips", {
            {"Lady in the Water", 2.5},
            {"Snakes on a Plane", 3},
            {"Superman Returns", 3.5},
            {"The Night Listener", 4}
        }},
        {"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}
        }},
        {"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}
        }},
        {"Jack Matthews", {
            {"Lady in the Water", 3},
            {"Snakes on a Plane", 4},
            {"Superman Returns", 5},
            {"You, Me and Dupree", 3.5}
        }},
        {"Toby", {
            {"Snakes on a Plane", 4.5},
            {"Superman Returns", 4},
            {"You, Me and Dupree",1}
        }}
    };
    topMatches(sim_D, critics, "Toby", sizeof critics / sizeof *critics);
}

下面是示例输出:

(0.99124, Lisa Rose),(0.92447, Gene Seymour),(0.89341, Michael Phillips),(0.66285, Claudia Puig),(0.38125, Mick LaSalle),(0.00000, Jack Matthews),(-1.00000, Toby)

1.(未修复)考虑使用空主体重写不常见的if表达式:

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) {

致:

if (
   (prefs[p1].movi[x].rating || prefs[p2].movi[next].rating) && 
   !strcmp(prefs[p1].movi[x].mName, prefs[p2].movi[next].mName)
) {

如果你引入一些虚变量,它可以写得更简洁。
1.将float替换为double并修复排序函数:

int cmpFxn (const void * a, const void * b) {
    double a2 = *(double *) a;
    double b2 = *(double *) b;
    if(a2 < b2) return -1;
    if(a2 > b2) return 1;
    return 0;
}
  1. valgrind报告topMatches中使用了未初始化的数据,特别是double scores[8];,您只迭代了num,即7,并且没有为person1对应的条目设置scores [i],因此我建议您这样做:
double scores[num];
    memset(scores, 0, sizeof(scores));

1.(未修复)审核代码中是否存在幻值,如7和20。如果需要数组的大小,请使用常量、传入参数或sizeof a / sizeof *a(当作为参数传递时,请小心数组降级为指针)。

相关问题