如何在溢出时停止双重自动转换?
我有一个代码,其中使用 getenv 从环境中提取字符串,使用 strtod 将它们解析为数字。 如果用户输入,213.123。然后 213 和 123 将分别馈送到 long 类型。
长a1 = 213; long a2 = 123
我面临的问题是,如果用户输入一个很长的数字,例如:123456789123.45678,它会自动四舍五入,这是我不想要的,而是抛出错误,但是ERANGE不工作。
9 static volatile int flag; /* flag variable to indicate when the measurement should start */
10 static time_t ef_errtrack_start_sec; /* error track start time in seconds */
11 static long ef_errtrack_start_nsec; /* error track start time in nanoseconds */
12 static time_t ef_errtrack_end_sec; /* error track end time in seconds */
13 static long ef_errtrack_end_nsec; /* error track end time in nanoseconds */
21 int main(int argc, char **argv)
22 {
23 extractTime(1); /* Extracting start time */
24 extractTime(0); /* Extracting end time */
25
26 printf("start: %12d, %12d\n", ef_errtrack_start_sec, ef_errtrack_start_nsec);
27 printf("end: %12d, %12d\n", ef_errtrack_end_sec, ef_errtrack_end_nsec);
28
29 return 0;
30 }
35 void extractTime(int extractStartTime)
36 {
37 char * charPtr, * numberFormatErr;
38 regex_t re;
39
40 ( extractStartTime == 1 ) ? ( charPtr = getenv("EF_ERRTRACK_START") ) :
41 ( charPtr = getenv("EF_ERRTRACK_END") );
42
43 if ( charPtr == NULL )
44 return;
45
46 double envVal = strtod(charPtr, &numberFormatErr);
47
48 if ( (numberFormatErr == charPtr) || (*numberFormatErr != '\0') ) {
49 ( extractStartTime == 1 ) ? printf("eFence exited: EF_ERRTRACK_START is not a number\n") :
50 printf("eFence exited: EF_ERRTRACK_END is not a number\n");
51 exit(1);
52 }
53 if ( errno == ERANGE )
54 {
55 ( extractStartTime == 1 ) ? EF_Print("eFence exited: EF_ERRTRACK_START is out of range\n") :
56 EF_Print("eFence exited: EF_ERRTRACK_END is out of range\n");
57 exit(1);
58 }
59 else if ( envVal < 0 ) {
60 ( extractStartTime == 1 ) ? printf("eFence exited: EF_ERRTRACK_START a negative number\n") :
61 printf("eFence exited: EF_ERRTRACK_END is a negative number\n");
62 exit(1);
63 }
64
65 if ( extractStartTime ) {
66 ef_errtrack_start_sec = envVal;
67 double nsec = (envVal) - (double)(ef_errtrack_start_sec);
68 ef_errtrack_start_nsec = (long)(nsec * 1000000000);
69 }
70 else {
71 ef_errtrack_end_sec = envVal;
72 double nsec = (envVal) - (double)(ef_errtrack_end_sec);
73 ef_errtrack_end_nsec = (long) (nsec * 1000000000);
74 }
75 }
这是输出:
Output:
/tmp # export EF_ERRTRACK_START=1234567891234.123456789123
/tmp # export EF_ERRTRACK_END=10e2
/tmp/time_related # ./a.out
start: 2147483647, 2147483647
end: 1000, 0
I have a code in which i am extracting strings from environment using getenv, parsing them into numbers using strtod.
If user enters, 213.123. Then 213 and 123 will be individually fed to a long type.
long a1 = 213; long a2 = 123
The problem i am facing is, if user enters a very long number like: 123456789123.45678, it is automatically getting rounded off, which i don't want and instead throw an error, however ERANGE isn't working.
9 static volatile int flag; /* flag variable to indicate when the measurement should start */
10 static time_t ef_errtrack_start_sec; /* error track start time in seconds */
11 static long ef_errtrack_start_nsec; /* error track start time in nanoseconds */
12 static time_t ef_errtrack_end_sec; /* error track end time in seconds */
13 static long ef_errtrack_end_nsec; /* error track end time in nanoseconds */
21 int main(int argc, char **argv)
22 {
23 extractTime(1); /* Extracting start time */
24 extractTime(0); /* Extracting end time */
25
26 printf("start: %12d, %12d\n", ef_errtrack_start_sec, ef_errtrack_start_nsec);
27 printf("end: %12d, %12d\n", ef_errtrack_end_sec, ef_errtrack_end_nsec);
28
29 return 0;
30 }
35 void extractTime(int extractStartTime)
36 {
37 char * charPtr, * numberFormatErr;
38 regex_t re;
39
40 ( extractStartTime == 1 ) ? ( charPtr = getenv("EF_ERRTRACK_START") ) :
41 ( charPtr = getenv("EF_ERRTRACK_END") );
42
43 if ( charPtr == NULL )
44 return;
45
46 double envVal = strtod(charPtr, &numberFormatErr);
47
48 if ( (numberFormatErr == charPtr) || (*numberFormatErr != '\0') ) {
49 ( extractStartTime == 1 ) ? printf("eFence exited: EF_ERRTRACK_START is not a number\n") :
50 printf("eFence exited: EF_ERRTRACK_END is not a number\n");
51 exit(1);
52 }
53 if ( errno == ERANGE )
54 {
55 ( extractStartTime == 1 ) ? EF_Print("eFence exited: EF_ERRTRACK_START is out of range\n") :
56 EF_Print("eFence exited: EF_ERRTRACK_END is out of range\n");
57 exit(1);
58 }
59 else if ( envVal < 0 ) {
60 ( extractStartTime == 1 ) ? printf("eFence exited: EF_ERRTRACK_START a negative number\n") :
61 printf("eFence exited: EF_ERRTRACK_END is a negative number\n");
62 exit(1);
63 }
64
65 if ( extractStartTime ) {
66 ef_errtrack_start_sec = envVal;
67 double nsec = (envVal) - (double)(ef_errtrack_start_sec);
68 ef_errtrack_start_nsec = (long)(nsec * 1000000000);
69 }
70 else {
71 ef_errtrack_end_sec = envVal;
72 double nsec = (envVal) - (double)(ef_errtrack_end_sec);
73 ef_errtrack_end_nsec = (long) (nsec * 1000000000);
74 }
75 }
Here is the output:
Output:
/tmp # export EF_ERRTRACK_START=1234567891234.123456789123
/tmp # export EF_ERRTRACK_END=10e2
/tmp/time_related # ./a.out
start: 2147483647, 2147483647
end: 1000, 0
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
“超出可表示值的范围”意味着大于
DBL_MAX
。您的输入在范围内,它只是不能完全表示为双精度。就此而言,
0.1
也在范围内,并且也不能完全表示。这也应该是一个错误吗?如果不是,有什么区别?我不知道该建议你做什么,因为我不知道为什么你认为你的情况是错误的。一种选择是,一旦获得双精度数,就使用
snprintf
将其转换回字符串,并与原始输入进行比较,看看它们是否至少在小数点上相等。不过,这忽略了科学记数法,因此可能需要做更多的工作来识别您不喜欢的数字。编辑:啊,最初我并没有真正理解这一点:“如果用户输入 213.123。那么 213 和 123 将被单独输入到一个 long 类型。”
听起来您正在读取的不是双精度值,而是由句点字符分隔的两个整数值。因此,不要使用
strtod
,找到.
,然后在其每一侧调用strtol
。"Outside the range of representable values" means bigger than
DBL_MAX
. Your input is in range, it just isn't exactly representable as a double.For that matter,
0.1
is also in range, and also isn't exactly representable. Should that also be an error, and if not, what's the difference?I'm not sure what to advise you to do, because I'm not sure why you consider your case an error. One option would be that once you have your double, convert it back to string with
snprintf
and compare to the original input, see whether they are equal at least as far as the decimal point. That ignores scientific notation, though, so there may be more work required to identify the numbers you don't like.Edit: ah, initially I didn't really assimilate this: "If user enters, 213.123. Then 213 and 123 will be individually fed to a long type."
Sounds like what you are reading is not a double value, it's two integer values separated by a period character. So don't use
strtod
, find the.
and then callstrtol
on each side of it.我认为你必须解析输入,识别可能的类型(和错误)并采取相应的行动(不需要
double
)I think you have to parse the input, identify the possible types (and errors) and act accordingly (no
double
necessary)