我遇到麻烦,返回我定义的结构,我的函数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;
}
答案 0 :(得分:1)
这里有很多错误。首先,scan_sci
的参数错误。您没有传递指向您声明的结构的指针,而是传递一个字符数组。您的声明应如下:
scinot_t scan_sci( scinot_t *collection );
为了符合将指针传递给结构,您需要将声明更改为以下内容。注意,非常糟糕的做法,并且容易返回指向堆栈上声明的变量的指针,因此我们为什么要在scan_sci
内改变结构。
void scan_sci( scinot_t *collection );
现在,您需要在调用函数之前创建结构,并使用&
运算符传递其内存地址。
答案 1 :(得分:0)
你有一些问题,这应该解决它们。首先,scan_sci
现在接受一个返回值的指针,并在成功时返回0或在失败时返回非0(不捕获所有失败模式)。除此之外,scanf
是贪婪的,e
是浮点字符串表示的合法部分,因此,您的原始版本只解析1个参数,而double正在吃掉整个输入字符串,例如“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;
}
答案 2 :(得分:0)
这是从控制台读取并将值放在scinot_t
中的一些代码
没有任何验证。
它使用scanf将整个字符串分成两部分。第一部分%[^e]
读取任何不是'e'的char
。然后它读取'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;
}
答案 3 :(得分: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
转化规范高兴阅读%lf
的问题,导致e
和%d
无法匹配。除非您要求使用scanf()
启动该值,否则使用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是否太大并相应地调整数字。