我有一个字符串str ( "1 + 2 = 3" )
。我想以十进制值(而不是ASCII)获取字符串的单个数字。我尝试过atoi
和c_str()
。但是它们都要求整个字符串只包含数字。我用C ++编写代码。
任何帮助都会很棒。
我的挑战是评估前缀表达式。我正在读取一个文件,其中每行包含一个前缀表达式。我用于标记化和存储变量的代码片段如下所示。该文件的每一行都包含以空格分隔的数字和运算符(+
,-
,*
)。
前 - line = ( * + 2 3 4);
ifstream file;
string line;
file.open(argv[1]);
while(!file.eof())
{
getline(file,line);
if(line.length()==0)
continue;
else
{
vector<int> vec;
string delimiters = " ";
size_t current;
size_t next = -1;
do
{
current = next + 1;
next = line.find_first_of( delimiters, current );
if((line[next] <=57)&&(line[next] >=48))
vec.push_back(atoi((line.substr( current, next - current )).c_str()));
}while (next != string::npos);
cout << vec[0] << endl;
}
}
file.close();
在这种情况下,vec[0]
打印50
而不是2
。
答案 0 :(得分:4)
您需要学习划分字符串。您的分隔字符将是数学运算符(即:
C: creating array of strings from delimited source string
http://www.gnu.org/software/libc/manual/html_node/Finding-Tokens-in-a-String.html
对于第二个链接,您可以执行以下操作:
const char delimiters[] = "+-=";
有了这些知识,你可以创建一个字符串数组,并在每个字符串上调用atoi()来获得数字等价物。然后,您可以使用每个分隔符的地址(数组索引)来确定哪个运算符。
对于加法和减法这样的事情,这很简单。如果您想要操作顺序和乘法,括号等,您的流程逻辑会更复杂。
有关更深入的示例,请参阅此最终链接。 C中的一个简单的命令行计算器。这应该使它清晰。
答案 1 :(得分:0)
您不会落入if
,因为您的下一个职位将是分隔符。
string delimiters = " ";
...
next = line.find_first_of( delimiters, current );
if((line[next] <=57)&&(line[next] >=48))
...
由于您的delimiters
由" "
组成,因此line[next]
将成为空格字符。
从您的问题描述中,您缺少可以省去您的操作员的代码。没有代码可以尝试查找运算符。
您不必假设ASCII用于测试数字。例如,您可以使用is_digit()
,也可以与'9'
和'0'
进行比较。
当你打印vector元素时,你可能会不恰当地访问向量,因为没有任何项目可能已被插入到数组中。
答案 2 :(得分:0)
Don't use fin.eof()
to control a loop。该函数仅在读取失败后才有用。
There are a number of ways to get int
s from a std::string
,在这种情况下,我从C ++ 11标准中选择了std::stoi()
。
#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
typedef std::vector<int> ints;
bool is_known_operator(std::string const& token)
{
static char const* tokens[] = {"*", "/", "+", "-"};
return std::find(std::begin(tokens), std::end(tokens), token) != std::end(tokens);
}
ints tokenise(std::string const& line)
{
ints vec;
std::string token;
std::istringstream iss(line);
while (iss >> token)
{
if (is_known_operator(token))
{
std::cout << "Handle operator [" << token << "]" << std::endl;
}
else
{
try
{
auto number = std::stoi(token);
vec.push_back(number);
}
catch (const std::invalid_argument&)
{
std::cerr << "Unexpected item in the bagging area ["
<< token << "]" << std::endl;
}
}
}
return vec;
}
int main(int, const char *argv[])
{
std::ifstream file(argv[1]);
std::string line;
ints vec;
while (std::getline(file, line))
{
vec = tokenise(line);
}
std::cout << "The following " << vec.size() << " numbers were read:\n";
std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, "\n"));
}