0

我遇到了麻烦,返回我定义的结构,我的函数 scan_sci 假设从输入源获取一个以科学计数法表示正数的字符串,并将其分解为组件以存储在 scinot_t 结构中。示例输入为 0.25000e4

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

    typedef struct{
        double mantissa;
        int exp;
    }sci_not_t;

    int scan_sci (sci_not_t *c);

    int main(void){

        sci_not_t inp1, inp2;

        printf("Enter the mantissa in the range [0.1, 1.0) then its exponent: ");
        scan_sci(&inp1);
        printf("Enter second number with same specifications as above: ");
        scan_sci(&inp2);






      system("PAUSE");  
      return 0;
    }

    int scan_sci (sci_not_t *c){

        int status;
        double a;
        int b;

        status = scanf("%lf %d", &c->mantissa, &c->exp);

        a = c->mantissa;
        b = c->exp;
        *c = pow(a,b);

        if (status == 2 && (c->mantissa >= 0.1 && c->mantissa < 1.0) ){
            status = 1;
        }else{
            printf("You did not enter the mantissa in the correct range \n");
            status = 0;
        }


        return (status);
    }

    sci_not_t sum(sci_not_t c1, sci_not_t c2){

        return c1 + c2;
    }

    sci_not_t product(sci_not_t c1, sci_not_t c2){

        return c1 * c2;
    }
4

4 回答 4

1

这里有很多错误。首先,您的参数对于scan_sci. 您没有传递指向您声明的结构的指针,而是传递了一个字符数组。您的声明应如下所示:

scinot_t scan_sci( scinot_t *collection );

为了符合将指针传递给结构的要求,您需要将声明更改为以下内容。请注意,返回指向在堆栈上声明的变量的指针是非常糟糕的做法并且容易出错,因此我们在scan_sci.

void scan_sci( scinot_t *collection );

现在,您需要在调用函数并使用&运算符传递其内存地址之前创建结构。

于 2013-08-09T21:33:38.743 回答
0

您遇到了一些问题,这应该可以解决它们。首先,scan_sci现在需要一个指针来返回值,并在成功时返回 0 或在失败时返回非 0(不捕获所有失败模式)。除此之外,它scanf是贪婪的,并且e是浮点字符串表示的合法部分,因此,您的原始版本仅解析 1 个参数,而双精度正在吃掉整个输入字符串,例如“123e123”全部进入双精度。为了解决这个问题,基于e.

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

typedef struct {
    double mantissa;
    int exp;
}scinot_t;

int scan_sci(scinot_t * tl){
    char buf[80]; 
    fgets(buf, 80, stdin);
    char * e = strchr(buf, 'e');
    if (!e) { return -1; }
    // Split buf up to act like 2 strings
    // e.g. 123.01e321 becomes:
    // 123.01 and 321 with e pointing to 321
    *e = '\0';
    e++;
    // Not checking any errors
    tl->mantissa = strtod(buf, NULL);
    tl->exp = strtol(e, NULL, 10);
    return 0;
}

int main(void){
    printf("Enter a value\n");
    // Init to 0 
    scinot_t sav = {0};
    int ret = scan_sci(&sav);
    if (ret) {
        printf("error, 'e' expected\n");
    }
    else {
        printf("%lfe%d", sav.mantissa, sav.exp);
    }

    return 0;
}
于 2013-08-09T22:32:30.913 回答
0

这是从控制台读取的一些代码,并将值放入scinot_t There's no validation 中。

它使用 scanf 将整个字符串读取为两部分。第一部分%[^e]读取任何char不是“e”的内容。然后它读取“e”,最后读取指数。

尾数首先作为字符串读取,然后使用 sscanf 重新解析。

#include <stdlib.h>

typedef struct {
    double mantissa;
    int exp;
}scinot_t;

void scan_sci(scinot_t* s);

int main(void){
  scinot_t d;

  printf("Enter a value: ");
  scan_sci(&d);

  printf("Mantissa is %lf Exponent is %d\n", d.mantissa, d.exp);
  return 0;
}

void scan_sci (scinot_t *sn){
  char inp1[20];
  scanf("%[^e]e%d", inp1, &sn->exp);
  sscanf(inp1, "%lf", &sn->mantissa);
  return;
}

要测试尾数范围更新主要是这样的:

int main(void){
  scinot_t d;

  printf("Enter a value: ");
  for (;;) {
    scan_sci(&d);
    if (d.mantissa>=0.1 && d.mantissa<=1.0)
      break;
    printf("You did not enter the mantissa in the correct range\nEnter a value: ");
  }

  printf("Mantissa is %lf Exponent is %d\n", d.mantissa, d.exp);
  return 0;
}
于 2013-08-09T22:32:37.533 回答
0

我看到的代码中的一个问题是:

printf("%lfe%d", inp1);

这不能可靠地工作(尽管它有可能会工作);您需要分别传递以下两个元素inp1

printf("%lfe%d\n", inp1.mantissa, inp1.exponent);

另一个问题是在扫描功能中:

void scan_sci(scinot_t *value)
{
    *value= scanf("%lfe%d", &value->mantissa, &value->exp);
}

这完全是错误的,因为它试图将一个整数值(从 的返回scanf())分配给一个结构。我认为你应该使用更多类似的东西:

int scan_sci(scinot_t *value)
{
    if (scanf("%lfe%d", &value->mantissa, &value->exp) != 2)
        return EOF;
    return 0;
}

返回值现在指示它是成功 (0) 还是失败 (EOF)。您仍然会遇到使用转换规范%lf愉快地阅读的问题,而留下和无法匹配的问题。使用 解决这个问题没有简单的方法,除非您要求该值以.0.25000e4%lfe%dscanf()0.

int scan_sci(scinot_t *value)
{
    int fraction;
    if (scanf("0.%de%d", &fraction, &value->exp) != 2)
        return EOF;
    value->mantissa = ...calculation...
    return 0;
}

但是,那里的麻烦在于,第一个%d从数字中去除了前导零(因此0.0025e4会被误解),因此您仍然会遇到问题。您最好扫描一串数字:

int scan_sci(scinot_t *value)
{
    char digits[1024];
    if (scanf("0.%1023[0-9]e%d", digits, &value->exp) != 2)
        return EOF;
    value->mantissa = ...calculation using the digits string...
    return 0;
}

您可以决定 1024 是否太大并相应地调整数字。

于 2013-08-09T22:43:22.537 回答