获取字符串并转换为双精度
fetching string and converting to double
我正在尝试创建一个函数,它可以确定输入是否可以完美转换为双精度,然后能够将其存储到双精度数组中。例如,输入“12.3a”是无效的。据我所知,strtod 仍然可以将其转换为 12.3,其余部分将存储到指针中。在我的函数 doubleable 中,它过滤输入字符串是否仅由数字组成。但是,我知道 double 有“。”就像在“12.3”中一样,我的函数将 return 'X' (无效)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char doubleable (char unsure[], int length){
int i;
int flag;
for (i=0; i<length; i++ ){
if(isdigit(unsure[i]==0)){
printf("You have invalid input.\n");
flag=1;
break;
}
}
//check for '.' (?)
if(flag==1)
return 'X';
else
return 'A';
}
int main(){
char input [10];
double converted[5];
char *ptr;
int i;
for(i=0; i<5; i++){
fgets(input, 10, stdin);
//some code here to replace '\n' to '[=10=]' in input
if(doubleable(input, strlen(input))=='X'){
break;
}
converted[i]=strtod(input, &ptr);
//printf("%lf", converted[i]);
}
return 0;
}
我正在考虑检查“.”的出现。在输入中,以及多少(对于像 12.3.12 这样的输入,可以认为是无效的)。我在正确的轨道上吗?还是有更简单的方法来解决这个问题?我还阅读了 strtok 函数,它在这里有帮助吗?不过,这个功能对我来说仍然很模糊。
编辑:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
double HUGE_VAL= 1000000;
void string_cleaner (char *dirty){
int i=0;
while(1){
if (dirty[i]=='\n'){
dirty[i]='[=11=]';
break;
}
i++;
}
}
int doubleable2(const char *str)
{
char *end_ptr;
double result;
result = strtod(str, &end_ptr);
if (result == HUGE_VAL || result == 0 && end_ptr == str)
return 0; // Could not be converted
if (end_ptr < str + strlen(str))
return 0; // Other input in the string after the number
return 1; // All of the string is part of the number
}
int main(){
char input [10];
double converted[10];
char *ptr;
int i;
for(i=0; i<5; i++){
while (1){
printf("Please enter:");
fgets(input, 10, stdin);
string_cleaner(input);
if (doubleable2(input)==0)
continue;
else if (doubleable2(input)==1)
break;
}
converted[i]=strtod(input, &ptr);
printf("%lf\n", converted[i]);
}
return 0;
}
谢谢!它工作得很好!我有一个后续问题。如果我输入的字符串太长,程序就会中断。如果我要限制输入,比方说,input[] 中最多 9 个字符,我该怎么做?
据我对fgets(xx, size, stdin)的了解,它只获取size个字符(包括\n,\0),然后存储到xx。在我的程序中,我想如果我把它设置为 10,那么超过 10 的任何东西都不会被考虑。但是,如果我输入的字符串太长,我的程序就会中断。
您确实可以使用 strtod
并检查返回值和作为第二个参数给出的指针:
int doubleable(const char *str)
{
const char *end_ptr;
double result;
result = strtod(str, &end_ptr);
if (result == HUGE_VAL || result == 0 && end_ptr == str)
return 0; // Could not be converted
if (end_ptr < str + strlen(str))
return 0; // Other input in the string after the number
return 1; // All of the string is part of the number
}
请注意,在调用此函数之前,您需要删除 fgets
大多数情况下添加到字符串中的换行符。
From what I know, strtod can still convert it to 12.3 and the remaining will be stored to the pointer.
这是正确的——见其 man
page:
If endptr is not NULL, a pointer to the character after the last character used in the conversion is stored in the location referenced by endptr.
所以请使用该信息!
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
bool doable (const char *buf)
{
char *endptr;
errno = 0;
if (!buf || (strtod (buf, &endptr) == 0 && errno))
return 0;
if (*endptr)
return 0;
return 1;
}
int main (void)
{
printf ("doable: %d\n", doable ("12.3"));
printf ("doable: %d\n", doable ("12.3a"));
printf ("doable: %d\n", doable ("abc"));
printf ("doable: %d\n", doable (NULL));
return 0;
}
结果
doable: 1
doable: 0
doable: 0
doable: 0
接受答案后
使用 strtod()
是正确的方法,但它有一些挑战
#include <ctype.h>
#include <stdlib.h>
int doubleable3(const char *str) {
if (str == NULL) {
return 0; // Test against NULL if desired.
}
char *end_ptr; // const char *end_ptr here is a problem in C for strtod()
double result = strtod(str, &end_ptr);
if (str == end_ptr) {
return 0; // No conversion
}
// Add this if code should accept trailing white-space like a \n
while (isspace((unsigned char) *endptr)) {
endptr++;
}
if (*end_ptr) {
return 0; // Text after the last converted character
}
// Result overflowed or maybe underflowed
// The underflow case is not defined to set errno - implementation defined.
// So let code accept all underflow cases
if (errno) {
if (fabs(result) == HUGE_VAL) {
return 0; // value too large
}
}
return 1; // Success
}
OP 的代码
result == 0 && end_ptr == str
中的 result == 0
没有值。简化为 end_ptr == str
.
而不是 if (end_ptr < str + strlen(str))
,一个简单的 if (*end_ptr)
就足够了。
if (result == HUGE_VAL ...
是一个问题,原因有两个。 1)当result == HUGE_VAL
有两种情况:合法转换和溢出转换。需要测试 errno
来区分。 2) 测试应该if (fabs(result) == HUGE_VAL ...
来处理负数。
我正在尝试创建一个函数,它可以确定输入是否可以完美转换为双精度,然后能够将其存储到双精度数组中。例如,输入“12.3a”是无效的。据我所知,strtod 仍然可以将其转换为 12.3,其余部分将存储到指针中。在我的函数 doubleable 中,它过滤输入字符串是否仅由数字组成。但是,我知道 double 有“。”就像在“12.3”中一样,我的函数将 return 'X' (无效)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char doubleable (char unsure[], int length){
int i;
int flag;
for (i=0; i<length; i++ ){
if(isdigit(unsure[i]==0)){
printf("You have invalid input.\n");
flag=1;
break;
}
}
//check for '.' (?)
if(flag==1)
return 'X';
else
return 'A';
}
int main(){
char input [10];
double converted[5];
char *ptr;
int i;
for(i=0; i<5; i++){
fgets(input, 10, stdin);
//some code here to replace '\n' to '[=10=]' in input
if(doubleable(input, strlen(input))=='X'){
break;
}
converted[i]=strtod(input, &ptr);
//printf("%lf", converted[i]);
}
return 0;
}
我正在考虑检查“.”的出现。在输入中,以及多少(对于像 12.3.12 这样的输入,可以认为是无效的)。我在正确的轨道上吗?还是有更简单的方法来解决这个问题?我还阅读了 strtok 函数,它在这里有帮助吗?不过,这个功能对我来说仍然很模糊。
编辑:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
double HUGE_VAL= 1000000;
void string_cleaner (char *dirty){
int i=0;
while(1){
if (dirty[i]=='\n'){
dirty[i]='[=11=]';
break;
}
i++;
}
}
int doubleable2(const char *str)
{
char *end_ptr;
double result;
result = strtod(str, &end_ptr);
if (result == HUGE_VAL || result == 0 && end_ptr == str)
return 0; // Could not be converted
if (end_ptr < str + strlen(str))
return 0; // Other input in the string after the number
return 1; // All of the string is part of the number
}
int main(){
char input [10];
double converted[10];
char *ptr;
int i;
for(i=0; i<5; i++){
while (1){
printf("Please enter:");
fgets(input, 10, stdin);
string_cleaner(input);
if (doubleable2(input)==0)
continue;
else if (doubleable2(input)==1)
break;
}
converted[i]=strtod(input, &ptr);
printf("%lf\n", converted[i]);
}
return 0;
}
谢谢!它工作得很好!我有一个后续问题。如果我输入的字符串太长,程序就会中断。如果我要限制输入,比方说,input[] 中最多 9 个字符,我该怎么做?
据我对fgets(xx, size, stdin)的了解,它只获取size个字符(包括\n,\0),然后存储到xx。在我的程序中,我想如果我把它设置为 10,那么超过 10 的任何东西都不会被考虑。但是,如果我输入的字符串太长,我的程序就会中断。
您确实可以使用 strtod
并检查返回值和作为第二个参数给出的指针:
int doubleable(const char *str)
{
const char *end_ptr;
double result;
result = strtod(str, &end_ptr);
if (result == HUGE_VAL || result == 0 && end_ptr == str)
return 0; // Could not be converted
if (end_ptr < str + strlen(str))
return 0; // Other input in the string after the number
return 1; // All of the string is part of the number
}
请注意,在调用此函数之前,您需要删除 fgets
大多数情况下添加到字符串中的换行符。
From what I know, strtod can still convert it to 12.3 and the remaining will be stored to the pointer.
这是正确的——见其 man
page:
If endptr is not NULL, a pointer to the character after the last character used in the conversion is stored in the location referenced by endptr.
所以请使用该信息!
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
bool doable (const char *buf)
{
char *endptr;
errno = 0;
if (!buf || (strtod (buf, &endptr) == 0 && errno))
return 0;
if (*endptr)
return 0;
return 1;
}
int main (void)
{
printf ("doable: %d\n", doable ("12.3"));
printf ("doable: %d\n", doable ("12.3a"));
printf ("doable: %d\n", doable ("abc"));
printf ("doable: %d\n", doable (NULL));
return 0;
}
结果
doable: 1
doable: 0
doable: 0
doable: 0
接受答案后
使用 strtod()
是正确的方法,但它有一些挑战
#include <ctype.h>
#include <stdlib.h>
int doubleable3(const char *str) {
if (str == NULL) {
return 0; // Test against NULL if desired.
}
char *end_ptr; // const char *end_ptr here is a problem in C for strtod()
double result = strtod(str, &end_ptr);
if (str == end_ptr) {
return 0; // No conversion
}
// Add this if code should accept trailing white-space like a \n
while (isspace((unsigned char) *endptr)) {
endptr++;
}
if (*end_ptr) {
return 0; // Text after the last converted character
}
// Result overflowed or maybe underflowed
// The underflow case is not defined to set errno - implementation defined.
// So let code accept all underflow cases
if (errno) {
if (fabs(result) == HUGE_VAL) {
return 0; // value too large
}
}
return 1; // Success
}
OP 的代码
result == 0 && end_ptr == str
中的 result == 0
没有值。简化为 end_ptr == str
.
而不是 if (end_ptr < str + strlen(str))
,一个简单的 if (*end_ptr)
就足够了。
if (result == HUGE_VAL ...
是一个问题,原因有两个。 1)当result == HUGE_VAL
有两种情况:合法转换和溢出转换。需要测试 errno
来区分。 2) 测试应该if (fabs(result) == HUGE_VAL ...
来处理负数。