将字符串转换为浮点数;无法正确清除 stringstream?
Converting string to floats; can't clear stringstream correctly?
免责声明:我必须使用 c++ 98
作为 class 作业的一部分,我的任务是将 space 分隔的字符串转换为浮点数(然后用这些浮点数计算跨度,但这与我的问题无关)。字符串来自文本文件。如果浮动有任何差异,我应该忽略它并认为它已损坏。例如,一个文本文件可能包含这样一行:
34.6 24.2 18.a 54.3 20.0 15.6
在这种情况下,18.a 将被简单地视为已损坏,无需对其进行进一步操作。
现在,我在清除损坏数据的字符串流时遇到了问题。作为参考,这是我的代码:
#include <vector>
#include <limits>
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
//Open file
ifstream infile("dataFile");
//Get all file input into a single string
string line;
string buffer;
while (getline(infile, buffer)) {
line += buffer + " ";
}
infile.close();
//Populate vector
float temp;
//I have tried to clear the stream with `data >> dummy` for
//both string and single char types below, but `data >> string`
//always clears too much, and `data >> char` doesn't seem to clear
//correctly either
//string dummy;
//char dummy;
vector<float> temps;
istringstream data(line);
while (data) {
//values between -100 and 100 are also considered corrupt
if (data >> temp && (temp <= 100 && temp >= -100)) {
temps.push_back(temp);
}
else if (!data.eof()) {
data.clear();
//trying to ignore all characters until I reach a space
//but that doesn't work correctly either
data.ignore(numeric_limits<streamsize>::max(), ' ');
//data >> dummy;
//cout << "Dummy: " << dummy << endl;
temps.push_back(-101.0);
}
}
//display resulting vector values
for(int i=0; i<temps.size(); ++i) {
cout << temps[i] << " ";
}
cout << endl;
}
我的问题出在 while (data)
循环内,特别是在 else if (!data.eof())
块内。当 data >> temp (type float)
失败时,else if
块运行。我清除了相应的 failbit
并尝试忽略剩余的字符,直到出现下一个 space 分隔符。但是,文本文件中有这样一行:
a *a -100.1 100.1 a 10.a a 13-6s 12abc -12.a
产生问题。 13 和 -6 都被处理为有效的浮点数。我想忽略 13-6s
的整个块,因为这些值旨在以 space 分隔。
处理这个 istringstream
问题的正确方法是什么,字符没有按照我想要的方式被忽略?
我的教授告诉我,我可以使用非常基本的 STL 技术来完成此任务。他明确建议使用 stringstream
作为解析浮点数的方法。他错了吗?
如果需要,请评论以进一步说明;我从事此工作已经有一段时间了,非常感谢您的帮助。
谢谢!
尝试使用演示程序中显示的以下方法。
#include <iostream>
#include <string>
#include <sstream>
#include <cstdlib>
#include <vector>
int main()
{
std::string line( "a *a -100.1 100.1 -100 a 10.a a 13-6s 100 12abc -12.a" );
std::istringstream is( line );
std::vector<float> values;
std::string item;
while ( is >> item )
{
const char *s = item.c_str();
char *tail;
float value = std::strtof( s, &tail );
if ( *tail == '[=10=]' && -100.0f <= value && value <= 100.0f )
{
values.push_back( value );
}
}
for ( float value : values ) std::cout << value << ' ';
std::cout << std::endl;
return 0;
}
程序输出为
-100 100
如果使用这个字符串
std::string line( "34.6 24.2 18.a 54.3 20.0 15.6" );
那么程序输出将是
34.6 24.2 54.3 20 15.6
另一种方法如下。
#include <iostream>
#include <string>
#include <sstream>
#include <limits>
#include <vector>
int main()
{
std::string line( "a *a -100.1 100.1 -100 a 10.a a 13-6s 100 12abc -12.a" );
// std::string line( "34.6 24.2 18.a 54.3 20.0 15.6" );
std::istringstream is( line );
std::vector<float> values;
while ( !is.eof() )
{
float value;
int c;
if ( not ( is >> value ) || ( ( c = is.get() ) != ' ' && c != std::char_traits<char>::eof() ) )
{
is.clear();
is.ignore( std::numeric_limits<std::streamsize>::max(), ' ' );
}
else if ( -100.0f <= value && value <= 100.0f )
{
values.push_back( value );
}
}
for ( float value : values ) std::cout << value << ' ';
std::cout << std::endl;
return 0;
}
输出与上图相同。
这应该可以满足您的需求。
#include <iostream>
#include <string>
#include <sstream>
int main() {
std::string temp;
// cin will write to temp with each space delimited entry
while (std::cin >> temp) {
std::stringstream s(temp);
float f;
// the first case checks if the actual write the float succeeds
// the second case checks if the entire stringstream has been read
if (!(s >> f) || !s.eof()) {
std::cout << temp << " failed!" << std::endl;
}
else {
std::cout << f << std::endl;
}
}
}
很抱歉无法回答您的 stringstream
问题,但此解决方案应该消除了任何必要性。
请注意,34.6 24.2 18.a 54.3 20.0 15.6
returns 的输入是:
的输出
34.6
24.2
18.a failed!
54.3
20
15.6
编辑:我在 if
语句中添加了一个案例来处理陌生案例(即 13-6s)。这是我发现的一个巧妙的解决方案 here.
编辑 2:我注释了一些更复杂的部分。
免责声明:我必须使用 c++ 98
作为 class 作业的一部分,我的任务是将 space 分隔的字符串转换为浮点数(然后用这些浮点数计算跨度,但这与我的问题无关)。字符串来自文本文件。如果浮动有任何差异,我应该忽略它并认为它已损坏。例如,一个文本文件可能包含这样一行:
34.6 24.2 18.a 54.3 20.0 15.6
在这种情况下,18.a 将被简单地视为已损坏,无需对其进行进一步操作。
现在,我在清除损坏数据的字符串流时遇到了问题。作为参考,这是我的代码:
#include <vector>
#include <limits>
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
//Open file
ifstream infile("dataFile");
//Get all file input into a single string
string line;
string buffer;
while (getline(infile, buffer)) {
line += buffer + " ";
}
infile.close();
//Populate vector
float temp;
//I have tried to clear the stream with `data >> dummy` for
//both string and single char types below, but `data >> string`
//always clears too much, and `data >> char` doesn't seem to clear
//correctly either
//string dummy;
//char dummy;
vector<float> temps;
istringstream data(line);
while (data) {
//values between -100 and 100 are also considered corrupt
if (data >> temp && (temp <= 100 && temp >= -100)) {
temps.push_back(temp);
}
else if (!data.eof()) {
data.clear();
//trying to ignore all characters until I reach a space
//but that doesn't work correctly either
data.ignore(numeric_limits<streamsize>::max(), ' ');
//data >> dummy;
//cout << "Dummy: " << dummy << endl;
temps.push_back(-101.0);
}
}
//display resulting vector values
for(int i=0; i<temps.size(); ++i) {
cout << temps[i] << " ";
}
cout << endl;
}
我的问题出在 while (data)
循环内,特别是在 else if (!data.eof())
块内。当 data >> temp (type float)
失败时,else if
块运行。我清除了相应的 failbit
并尝试忽略剩余的字符,直到出现下一个 space 分隔符。但是,文本文件中有这样一行:
a *a -100.1 100.1 a 10.a a 13-6s 12abc -12.a
产生问题。 13 和 -6 都被处理为有效的浮点数。我想忽略 13-6s
的整个块,因为这些值旨在以 space 分隔。
处理这个 istringstream
问题的正确方法是什么,字符没有按照我想要的方式被忽略?
我的教授告诉我,我可以使用非常基本的 STL 技术来完成此任务。他明确建议使用 stringstream
作为解析浮点数的方法。他错了吗?
如果需要,请评论以进一步说明;我从事此工作已经有一段时间了,非常感谢您的帮助。
谢谢!
尝试使用演示程序中显示的以下方法。
#include <iostream>
#include <string>
#include <sstream>
#include <cstdlib>
#include <vector>
int main()
{
std::string line( "a *a -100.1 100.1 -100 a 10.a a 13-6s 100 12abc -12.a" );
std::istringstream is( line );
std::vector<float> values;
std::string item;
while ( is >> item )
{
const char *s = item.c_str();
char *tail;
float value = std::strtof( s, &tail );
if ( *tail == '[=10=]' && -100.0f <= value && value <= 100.0f )
{
values.push_back( value );
}
}
for ( float value : values ) std::cout << value << ' ';
std::cout << std::endl;
return 0;
}
程序输出为
-100 100
如果使用这个字符串
std::string line( "34.6 24.2 18.a 54.3 20.0 15.6" );
那么程序输出将是
34.6 24.2 54.3 20 15.6
另一种方法如下。
#include <iostream>
#include <string>
#include <sstream>
#include <limits>
#include <vector>
int main()
{
std::string line( "a *a -100.1 100.1 -100 a 10.a a 13-6s 100 12abc -12.a" );
// std::string line( "34.6 24.2 18.a 54.3 20.0 15.6" );
std::istringstream is( line );
std::vector<float> values;
while ( !is.eof() )
{
float value;
int c;
if ( not ( is >> value ) || ( ( c = is.get() ) != ' ' && c != std::char_traits<char>::eof() ) )
{
is.clear();
is.ignore( std::numeric_limits<std::streamsize>::max(), ' ' );
}
else if ( -100.0f <= value && value <= 100.0f )
{
values.push_back( value );
}
}
for ( float value : values ) std::cout << value << ' ';
std::cout << std::endl;
return 0;
}
输出与上图相同。
这应该可以满足您的需求。
#include <iostream>
#include <string>
#include <sstream>
int main() {
std::string temp;
// cin will write to temp with each space delimited entry
while (std::cin >> temp) {
std::stringstream s(temp);
float f;
// the first case checks if the actual write the float succeeds
// the second case checks if the entire stringstream has been read
if (!(s >> f) || !s.eof()) {
std::cout << temp << " failed!" << std::endl;
}
else {
std::cout << f << std::endl;
}
}
}
很抱歉无法回答您的 stringstream
问题,但此解决方案应该消除了任何必要性。
请注意,34.6 24.2 18.a 54.3 20.0 15.6
returns 的输入是:
34.6
24.2
18.a failed!
54.3
20
15.6
编辑:我在 if
语句中添加了一个案例来处理陌生案例(即 13-6s)。这是我发现的一个巧妙的解决方案 here.
编辑 2:我注释了一些更复杂的部分。