2010-09-03 50 views
1

在java中,如果我想创造出能同时接收双打和字符串作为适当的输入一些应用程序,我可能会做到以下几点:C++字符串来解析异常?

String input = getInput();// 
try { 
    double foo = Double.valueOf(input); 
    //Do stuff with foo here 
} catch (NumberFormatException e) { 
    //Do other validation with input 
} 

你怎么会去这样做,在C++? atof()对于无效输入返回0.0,但您将如何区分“0.0”的有效双精度?另外,本项目中我只能包括<iostream>,<string>,<cstdlib><cassert>。我假设我需要以某种方式使用cin,但在cin未能将某些字符串解析为双精度后,如何获取原始输入?

编辑:我大概可以使用以下,但正如我之前说的,我不能对这个分配导入<sstream>出于某种原因

string input; 
getline(cin, input); 

double x; 
istringstream foo(input); 
foo >> x 
if(cin){ 
    //do manipulations with x 
} 
else{ 
    //since it's not a number, check if input is a valid command etc.. 
} 
+0

如果没有简单的方法,那就用硬性的方法...如果'atof'返回0,手动检查字符串是否真的是一个字符串。 – smerlin 2010-09-04 00:56:51

回答

4

异常应预留特殊情况。虽然你肯定可以这样滥用他们,但这是一个糟糕的主意 - 显然你很期待除了双打之外的其他东西,所以把它当作例外处理并没有什么意义。

唯一真正的问题是您希望将输入视为字符串的确切情况。举个例子,如果输入的字符串是类似“1.23e2非数字数据”的东西,那么你是否想仅仅使用“1.23e2”作为一个数字,或者你想把整个事物当作一个字符串?

无论采用哪种方式,您都需要我们strtod进行转换 - 区别仅在于您对返回结果有何反应。特别是,strtod需要两个参数,而不是像atof一样。第二个参数是指向char的指针。假设你传递一个非NULL指针,strtod将它设置为指向它成功转换的输入字符串中的最后一个字符。如果它指向输入字符串的开头,则不会转换任何内容。如果它指向最后,一切都会被转换。如果它介于两者之间,则部分字符串转换,部分字符不转换。

就目前而言,我会假设你想要一个双值保持任何数量可能在字符串的开头转换,以及任何无法转换视为字符串:

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

int main() { 
    char input[] = "12.34 non-numeric data"; 
    char *string; 
    double value = strtod(input, &string); 

    printf("Number: %f\tstring: %s\n", value, string); 
    return 0; 
} 
+0

在我发布之前,我只是用'strtod'来确认这一点。唯一需要注意的是,即使只有空白被跳过,我认为'endptr'会前进。任何人都可以确认吗? – torak 2010-09-04 00:27:53

+0

@torak:'endptr'将会指向任何*之后*的内容。如果没有任何转换,它将指向输入字符串的开头,即使空白将被跳过以获取数字数据。因此,“1.2 x”将转换为1.2,并且“endptr”将指向“x”,而:“x”不会转换,并且“endptr”将指向“x”。 – 2010-09-04 00:51:46

+0

感谢您阅读我的整篇文章,并提供了一个很好的答案。我可能最终会使用这个,除非我可以用cin破解类似的东西。实际的程序是一个简单的反向抛光记法计算器,它一次读取一个输入。输入是要放在堆栈上的十进制数字,或者是用于特殊操作的一对保留字符之一,例如退出程序的“q”。 – Grantismo 2010-09-04 00:54:01

0

C++标准库似乎在回避一个例外人们可能期望他们的很多事情,这可能不是你想听到的答案,但解析双打并不完全是火箭科学,所以也许可以“手工”做到这一点?

一注意如果你这样做,你可能会想收集到一个整数,然后转换为一个双精度除以10^number_of_digits_after_decimal_point。

2

C++流将好,坏和失败状态标志关联起来。它们分别存储在ios_base::goodbit,ios_base::badbitios_base::failbit中,但通常通过ios::good(),ios::bad()ios::fail()存储。还有ios_base::eofbitios::eof(),但暂时忽略这一点。

如果解析失败,则引发坏点。此外,流对象可转换为布尔型兼容类型。如果数据流处于良好状态,那么声明

if(stream) 

评估stream为真。否则,它评估它为假。有了这个就在眼前,抓住从标准输入值归结为:

#include <iostream> 

// ... 
double d = 0; 
if (std::cin >> d) { 
    // input is a double. handle that here. 
} else { 
    // input isn't a double. handle that here. 
} 
+0

我了解cin的基本功能,但我试图避免的是提示用户第二次输入特定信息,因为双打和字符都是该程序的有效输入。有没有办法在解析Double之后检索原始输入。我可能会离开基地,但类似cin.seekg(-1 * cin.gcount(),ios :: cur);再试一次? – Grantismo 2010-09-04 00:51:12

+0

如何解析输入,如果不是双重?通常我只是将输入读入'std :: string',然后将它重新插入到'std :: stringstream'中,然后检查它是否为double或者... – smerlin 2010-09-04 00:53:29

+0

这就是我正在计划的操作,但是我们的教授将我们限制在我原来的帖子中提到的图书馆,不幸的是,sstream和fstream不是一种选择。 – Grantismo 2010-09-04 01:19:43

1

试“的strtod” stdlib.h中

0

你可以在boost::lexical_cast看看,这样可以让你写Java代码的几乎等价的:

string input; 
getline(cin, input); 

try { 
    double x = boost::lexical_cast<double>(input); 
    //Do manipulations with x 
} catch (boost::bad_lexical_cast &) { 
    //Do other validation with input 
}