数组中两个值的除法总是 return 0

Division of two values from array always return 0

我有这个函数支持 return 一个应该是 1 或 2 或 4 的数字,但是当除法发生时,变量 duracion 总是结果得到值 0。我尝试了很多更改,但没有一个是解决方案。

// Converts a fraction formatted as X/Y to eighths
int duration(char* fraction)
{
    // TODO
    if (strlen(fraction) == 3)
    {
        // Asignacion de los caracteres de la fraccion a un array para 
           convertirlos en numeros despues.
        int a = atoi(&fraction[0]);
        int b = atoi(&fraction[2]);
        // Busqueda de errores --------------------------------------- 
        if ((fraction[0] != '1') && (fraction[0] != '3'))
        {
            fprintf(stderr, "octave most be formated as X/Y, where X 
                    can't be greater than 8\n");
            return 1;
        }
        else if (fraction[1] != '/')
        {
            fprintf(stderr, "octave most be formated as X/Y\n");
            return 1;
        }
        else if ((fraction[2] % 2 != 0) || (fraction[2] < 0))
        {
            fprintf(stderr, "octave most be formated as X/Y, where Y 
                    most be a positive pair number\n");
            return 1;
        }
        // Fin de busqueda de errores -------------------------------

        float duracion = (a / b) * 8;
        return duracion;
    }
    else
    {
        fprintf(stderr, "Note lenght most be formated as X/Y\n");
        return 1;
    }
}

问题是a和b都是int。所以它正在执行整数除法。

尝试将浮动转换为 (float)a/b * 8

或者您可以使用 atof 代替 atoi 并将 a 和 b 声明为 float

就是这样: 浮动持续时间 = (a / b) * 8;

修改: 浮动持续时间 = (a * 1.0 / b) * 8;

试一试

虽然这段代码存在一些问题,但我会首先回答您的直接问题。 你的问题出在行

float duracion = (a / b) * 8;

从您的代码中我可以看出您假设 a < b。这意味着:a / b < 1。 由于 abint,您正在执行整数除法,这意味着您的除法整数结果总是 被截断归零。

这是一种可能的解决方案(但不确定这是您真正想要的):

return (8.0 * a / b);

这是另一个(也许这是您真正需要的?):

return b / a;

现在是一些一般性的评论(假设您使用的是 C99)。

你的问题标题说 "Division of two values from array always return 0" 实际上,这些是来自字符串的值。 但这无关紧要,因为如果你只说 "Division of two integer values always return 0" 那么你会 Google 为你找到答案。

如果您假设分数的两部分始终是单个 ASCII 字符,您可以只写:

int a = fraction[0] - '0';
int b = fraction[2] - '0';

如果这不是假设,那么最好使用 "sscanf",因为它可以处理大多数用例,甚至是像“-16/8”这样的分数。

int a,b;
int ret = sscanf(fraction,"%d / %d", &a, &b);

另请注意,这一行是错误的,不会按您想要的方式工作:

else if ((fraction[2] % 2 != 0) || (fraction[2] < 0))

一般来说,您应该对字符串的值 "a" 和 "b" 以及 而不是 执行所有检查。

此外,习惯上尝试接受任何看起来有效的输入,而不是将您的用户限制在某些 over-specified 模式。所以你不应该限制字符串的长度为3,你应该允许元素之间有空格。

此外,除非这是你的意图,并且应该清楚地标记,否则你应该 return有效回复,在您的情况下为“1”,当检测到错误时。 Select 一个像“-1”这样的数字,或者更好的是,定义一个负值的枚举和 return 特定的错误,而不是在函数内部打印它。

P.S。 音符持续时间超过基数在音乐中是完全合法的。所以像 16/8 这样的东西通常是可以的。但这是一个音乐理论,而不是一个编程问题。