C++ 如何使用istringstream提取混合格式
为什么我的程序不输出:C++ 如何使用istringstream提取混合格式,c++,istringstream,formatted-input,C++,Istringstream,Formatted Input,为什么我的程序不输出: 10 1.546 ,Apple 1 而不是 10 1 <empty space> 10 1. 以下是我的节目: #include <iostream> #include <string> #include <sstream> using namespace std; int main () { string str = "10,1.546,Apple 1"; istringstream stream
10
1.546
,Apple 1
而不是
10
1
<empty space>
10
1.
以下是我的节目:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main () {
string str = "10,1.546,Apple 1";
istringstream stream (str);
int a;
double b;
string c, dummy;
stream >> a >> dummy >> b >> dummy >> c;
cout << a << endl;
cout << b << endl;
cout << c << endl;
return 0;
}
#包括
#包括
#包括
使用名称空间std;
int main(){
string str=“10,1.546,苹果1”;
istringstream(str);
INTA;
双b;
字符串c,虚拟;
流>>a>>虚拟>>b>>虚拟>>c;
cout您应该执行以下更改:
string str = "10 1.546 Apple 1";
及
在你的例子中,哑人会得到字符串“1.546,苹果”。因为遇到非数字字符时,它被馈送给变量A。然后,所有的东西都被添加到哑(字符串)中,直到默认分隔符(空间)在IOFiString中达到
< P>,字符串(即C字符串和C++字符串)。几乎没有格式要求。只有在找到空白字符或捕获流的结尾之前,才会将任何和所有字符提取到字符串中。在您的示例中,您使用的字符串旨在消耗重要数据之间的逗号,但您所经历的输出是I jus行为的结果t解释说:dummy
字符串不仅吃逗号,还吃字符序列的其余部分,直到下一个空白字符
为了避免这种情况,您可以对虚拟变量使用char
,该变量只有一个字符的空间。如果您希望将Apple 1
放入字符串中,则需要进行无格式提取,因为格式化提取程序运算符>>()
只读取到空格。此处使用的适当函数是std::getline()
:
在格式化提取之后清除换行也是必要的,这就是为什么我使用std::ws
来清除前导空格。我还使用if
语句来包含提取,以判断提取是否成功
任何更顺利的方法都会对我大有帮助
您可以使用流中嵌入的区域设置的std::ctype
方面将逗号字符的分类设置为空白字符。这将不需要使用伪变量。以下是一个示例:
namespace detail
{
enum options { add, remove };
class ctype : public std::ctype<char>
{
private:
static mask* get_table(const std::string& ws, options opt)
{
static std::vector<mask> table(classic_table(),
classic_table() + table_size);
for (char c : ws)
{
if (opt == add)
table[c] |= space;
else if (opt == remove)
table[c] &= ~space;
}
return &table[0];
}
public:
ctype(const std::string& ws, options opt)
: std::ctype<char>(get_table(ws, opt)) { }
};
}
class adjustws_impl
{
public:
adjustws_impl(const std::string& ws, detail::options opt) :
m_ws(ws),
m_opt(opt)
{ }
friend std::istream& operator>>(std::istream& is,
const adjustws_impl& manip)
{
const detail::ctype* facet(new detail::ctype(manip.m_ws, manip.m_opt));
if (!std::has_facet<detail::ctype>(is.getloc())
{
is.imbue(std::locale(is.getloc(), facet));
} else
delete facet;
return is;
}
private:
std::string m_ws;
detail::options m_opt;
};
adjustws_impl setws(const std::string& ws)
{
return adjustws_impl(ws, detail::add);
}
adjustws_impl unsetws(const std::string& ws)
{
return adjustws_impl(ws, detail::remove);
}
int main()
{
std::istringstream iss("10,1.546,Apple 1");
int a; double b; std::string c;
iss >> setws(","); // set comma to a whitespace character
if ((iss >> a >> b) && std::getline(iss >> std::ws, c))
{
// ...
}
iss >> unsetws(","); // remove the whitespace classification
}
名称空间详细信息
{
枚举选项{添加,删除};
类ctype:public std::ctype
{
私人:
静态掩码*get_表(const std::string&ws,options opt)
{
静态std::向量表(经典_表(),
经典表格()+表格大小);
for(字符c:ws)
{
如果(opt==添加)
表[c]|=空间;
else if(opt==删除)
表[c]&=~空间;
}
返回&表[0];
}
公众:
ctype(const std::string&ws,options opt)
:std::ctype(get_表(ws,opt)){
};
}
类调整w_impl
{
公众:
adjustws_impl(常数std::string&ws,细节::选项选项):
m_ws(ws),
m_opt(opt)
{ }
friend std::istream&operator>>(std::istream&is,
常数调整(安装和维护)
{
const detail::ctype*facet(新的detail::ctype(manip.m_-ws,manip.m_-opt));
如果(!std::has_facet(is.getloc())
{
is.imbue(std::locale(is.getloc(),facet));
}否则
删除刻面;
回报是;
}
私人:
std::字符串m_ws;
细节:选项m_opt;
};
adjustws_impl setws(常量标准::字符串和字符串)
{
返回调整ws_impl(ws,detail::add);
}
adjustws_impl unsetws(常量std::string&ws)
{
返回调整ws_impl(ws,detail::remove);
}
int main()
{
标准:istringstream iss(“10,1.546,苹果1”);
int a;double b;std::string c;
iss>>setws(“,”;//将逗号设置为空白字符
如果((iss>>a>>b)和&std::getline(iss>>std::ws,c))
{
// ...
}
iss>>取消设置(“,”;//删除空白分类
}
我可以稍微修改一下代码。还没有实现0x499602D2
方法,但下面是对我有效的方法
#include <iostream>
#include <string>
#include <cstdlib>
#include <sstream>
using namespace std;
int main () {
string str = "10,1.546,Apple 1";
istringstream stream (str);
int a;
double b;
string c;
string token;
while (getline (stream, token, ',')) {
if (token.find (".") == string::npos && token.find (" ") == string::npos) {
a = atoi (token.c_str ());
} else if (token.find (".") != string::npos) {
b = atof (token.c_str ());
} else {
c = string (token);
}
}
cout << a << endl;
cout << b << endl;
cout << c << endl;
return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
int main(){
string str=“10,1.546,苹果1”;
istringstream(str);
INTA;
双b;
字符串c;
字符串标记;
while(getline(流,令牌,,)){
if(token.find(“.”==string::npos&&token.find(“”==string::npos){
a=atoi(token.c_str());
}else if(token.find(“.”)=string::npos){
b=atof(token.c_str());
}否则{
c=字符串(令牌);
}
}
请允许我提出以下建议
<> P>我不认为它更流畅,因为CI/CUT对话不是“平滑”的,imHo。< /P>
但我认为这可能更接近你想要的
int main (int, char**)
{
// always initialize your variables
// to value you would not expect from input
int a = -99;
double b = 0.0;
std::string c("");
char comma1 = 'Z';
char comma2 = 'z';
std::string str = "10,1.546,Apple 1";
std::istringstream ss(str);
ss >> a >> comma1 >> b >> comma2;
// the last parameter has the default delimiter in it
(void)getline(ss, c, '\n'); // to get past this default delimiter,
// specify a different delimiter
std::cout << std::endl;
std::cout << a << " '" << comma1 << "' " << std::endl;
std::cout << b << " '" << comma2 << "' " << std::endl;
std::cout << c << std::endl;
return 0;
}
int main(int,char**)
{
//始终初始化变量
//为您不期望的输入值
int a=-99;
双b=0.0;
std::字符串c(“”);
字符comma1='Z';
char comma2='z';
std::string str=“10,1.546,苹果1”;
std::istringstream ss(str);
ss>>a>>comma1>>b>>comma2;
//最后一个参数中包含默认分隔符
(void)getline(ss,c,'\n');//要通过此默认分隔符,
//指定不同的分隔符
std::cout char dummy将修复它(第二个是吃掉输入)@DieterLückingstring dummy;
d'oh。我像白痴一样盯着代码看,没有看到:)@DieterLücking是的,它已经改进为输出10和1.546,但我需要Apple 1
,而且什么也没有得到,我现在得到了Apple
,但仍然没有Apple 1
。有什么想法吗?@SunilKundal提取停止在Apple
和1
之间。你需要使用std::getline()
(当然是在清除了新线之后)。你应该解释一下原因。我喜欢这个
#include <iostream>
#include <string>
#include <cstdlib>
#include <sstream>
using namespace std;
int main () {
string str = "10,1.546,Apple 1";
istringstream stream (str);
int a;
double b;
string c;
string token;
while (getline (stream, token, ',')) {
if (token.find (".") == string::npos && token.find (" ") == string::npos) {
a = atoi (token.c_str ());
} else if (token.find (".") != string::npos) {
b = atof (token.c_str ());
} else {
c = string (token);
}
}
cout << a << endl;
cout << b << endl;
cout << c << endl;
return 0;
}
int main (int, char**)
{
// always initialize your variables
// to value you would not expect from input
int a = -99;
double b = 0.0;
std::string c("");
char comma1 = 'Z';
char comma2 = 'z';
std::string str = "10,1.546,Apple 1";
std::istringstream ss(str);
ss >> a >> comma1 >> b >> comma2;
// the last parameter has the default delimiter in it
(void)getline(ss, c, '\n'); // to get past this default delimiter,
// specify a different delimiter
std::cout << std::endl;
std::cout << a << " '" << comma1 << "' " << std::endl;
std::cout << b << " '" << comma2 << "' " << std::endl;
std::cout << c << std::endl;
return 0;
}