Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 有没有更好的方法读取多个变量?_C++ - Fatal编程技术网

C++ 有没有更好的方法读取多个变量?

C++ 有没有更好的方法读取多个变量?,c++,C++,我有一个类,它有很多字符串变量: struct Person { string name, dob, state, best_friend, /* etc... */; }; 我必须在我的istream操作符中执行此操作: getline(cin, p.name); getline(cin, p.dob); getline(cin, p.state); getline(cin, p.best_friend); ... 对于所有其他成员变量,我必须一遍又一遍地这样做。我的问题是有更好的

我有一个类,它有很多字符串变量:

struct Person
{
    string name, dob, state, best_friend, /* etc... */;
};
我必须在我的istream操作符中执行此操作:

getline(cin, p.name);
getline(cin, p.dob);
getline(cin, p.state);
getline(cin, p.best_friend);
...

对于所有其他成员变量,我必须一遍又一遍地这样做。我的问题是有更好的方法吗?

另一种方法是将所有字符串保持为字符串数组

struct Person
{
    string data[4];
};
然后您的操作员可以这样做:

for ( size_type t = 0 ; t < sizeof(data)/sizeof(string) ; ++t )
{
    getline(cin, p.data[t]);
}
struct Person
{
    std::map<std::string, std::string> fields;
};

我还将定义一个包含字段索引的枚举,以避免出现“幻数”。

如果有某种自动方法来实现这一点,您将牺牲对行为的控制权。有一百万种情况会使这样的构造变得无用/不可能(例如,如果你只是在某处插入一个
int
字段怎么办?)

使用您拥有的结构,no,无法自动
getline
进入每个字段。您必须将每个字段名以及分配它们的位置放入类型定义中

但是你有其他的方法。例如,像这样编写您的
Person
结构:

for ( size_type t = 0 ; t < sizeof(data)/sizeof(string) ; ++t )
{
    getline(cin, p.data[t]);
}
struct Person
{
    std::map<std::string, std::string> fields;
};
struct-Person
{
std::映射字段;
};
其中
字段
将字段名(如
“name”
)映射到用户输入的字符串。虽然现在已启用将字段视为数组,但会丢失字段类型中的元数据。例如,对于原始代码,拼写错误的
Name
将生成编译器错误。使用
std::map
“Naame”
不会生成编译器错误

正是因为这个原因,我最喜欢你的原始代码。为了类型安全和在编译器级别保留错误,您需要支付一些复制和粘贴费用

类似地,使用数据结构还有许多其他方法可以做到这一点。

这行吗

基本上,创建一个指向各种字符串的指针数组,以NULL结尾,然后遍历数组,得到每个字符串

void getInput(Person& p)
{
    string* input[]={&p.name, &p.dob, &p.state, NULL};

    for(*input != NULL)
    {
        getline(cin, *input);
        input++;
    }
}

您可以使用这个函数,只需编写一次代码,然后就可以使用它了。您应该使用对对象的引用来使用函数向其写入内容。

有时候,自动化繁琐的过程就是一个解决方案

如果您真的想继续使用多个
getline()
语句,并且您有“许多”字符串,那么另一个不像前面提到的那样“以C++为中心”的解决方案是编写一个代码生成器,从结构生成
getline
语句


代码生成器只需创建一个包含所有
getline
语句的文件,您只需将这些行复制/粘贴到代码中(或者可以
#将其作为头文件包含)

我发现以下帮助函数很有用:

static int delimiter(){static int idx(std::ios_base::xalloc());返回idx;}
模板
std::istream&variadic_getline(std::istream&is,Args&…Args)
{
char delim=is.iword(分隔符());
如果(!delim)
delim='\n';
autol={0,(std::getline(is,std::forward(args),delim),0);
(无效)l;
回报是;
}
那么就做:

if(变量行(std::cin,p.name,p.dob,p.state,p.best\u friend)){
}

您是从控制台获取这些信息的吗?好吧,您可以编写一个函数,为
人员的所有成员(而不是实例
p
的成员)执行此操作,然后重用它。。。但是没有通用的方法告诉编译器您想要编写流操作符@user2030677-这些成员变量中有多少?因此您可能希望让用户在一行中输入所有这些信息。可能是相关的,值得一看:最好使用偏移量,而不是数组可以是静态常量。您需要字符串**current=input,然后在循环中使用“current”。或者使用int索引到输入[]。但这似乎是合理的,可以添加一个索引的静态常量数组吗?索引的静态常量数组不会使它更具可读性。我想应该是这样的:
enum字段{Name,DOB,State}然后您可以这样做:
string&getName(){returndata[Name];}+1哇!!!这可能有点超出了OP的实际概念,但它很好地描述了这个习语!!你介意在我对这个问题的评论中提到的我的经典尝试中补充这一点吗?@πάνταῥεῖ 当然可以我对
autol={0,(std::getline(is,std::forward(args),delim),0)…)有点迷茫
thing…@Chnossos初始值设定项列表用于解包参数,第一个和第二个零是一个故障保护,如果
Args…
为空,则不会引发编译时错误。实际上,我认为不需要零,因为我认为如果
Args..
为空,应该会出现错误。但我想将相反的设置作为默认设置,并让其他用户根据自己的喜好进行更改。@0x499602D2哦,我明白了!谢谢!