getline(),直到输入结束
getline() until end of input C++
这是我的代码。它应该在输入结束之前获取输入,并将该输入放入字符串data中。然后,它应该使用分隔符"#"对输入进行标记。然后,我反复调用函数nexttoken()来将标记存储在变量中。
std::istream_iterator<char> it(std::cin);
std::istream_iterator<char> end;
std::string data(it,end);
std::string delimiter = "#";
StringTokenizer strtok(data,delimiter);
std::string t1 = strtok.nextToken();
std::string t2 = strtok.nextToken();
当我像这样在命令行传递一个文件时,这一切都有效:
program.exe <testcase1.txt
testcase1.txt
S A B #
S -> a A #
S -> z B #
A -> b B c B #
B -> d A #
##
输出S A B
a: 1
b: 1
c: 1
d: 1
z: 1
everything check out and works.
我的问题是这样的:当我在IDE中推运行时,我可以手动输入输入,但当我这样做时,没有办法使程序接受输入,除非我按ctrl-z。这个问题在linux中也存在,当我在终端中传递文件时,它只是挂在那里让我输入无限行。
这里是我的代码的一个较小的版本,只计算3个标记,只检查a,b和c
main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
#include <cstddef>
#include "StringTokenizer.h"
int countSubstring(const std::string& str, const std::string& sub)
{
if (sub.length() == 0) return 0;
int count = 0;
for (size_t offset = str.find(sub); offset != std::string::npos;
offset = str.find(sub, offset + sub.length()))
{
++count;
}
return count;
}
int main(int argc, char* argv[1])
{
int task;
if (argc < 2)
{
std::cout << "Error: missing argumentn";
return 1;
}
task = atoi(argv[1]);
switch(task){
case 0:
{
std::istream_iterator<char> it(std::cin);
std::istream_iterator<char> end;
std::string data(it,end);
std::string delimiter = "#";
StringTokenizer strtok(data,delimiter);
int a = 0;
int b = 0;
int c = 0;
//reading the first token and puting it in tk1
std::string t1 = strtok.nextToken();
std::string tk1(t1);
tk1.erase(0, tk1.find_first_not_of(" "));
tk1.erase(tk1.find_last_not_of(" ")+1);
// token 2 and 3 are different because 1 is always the same format
std::string t2 = strtok.nextToken();
std::string tk2(t2);
if(countSubstring(tk2,"a") > 0)
{
a = a + 1;
}
if(countSubstring(tk2,"b") > 0)
{
b=b + 1;
}
if(countSubstring(tk2,"c") > 0)
{
c=c + 1;
}
std::string t3 = strtok.nextToken();
std::string tk3(t3);
if(countSubstring(tk3,"a") > 0)
{
a = a + 1;
}
if(countSubstring(tk3,"b") > 0)
{
b=b + 1;
}
if(countSubstring(tk3,"c") > 0)
{
c=c + 1;
}
// this is where the output is
std::cout << tk1 << std::endl;
if(a > 0)
{
std::cout << "a: " << a <<std::endl;
}
if(b > 0)
{
std::cout << "b: " << b <<std::endl;
}
if(c > 0)
{
std::cout << "c: " << c <<std::endl;
}
}
break;
//////////////////////////////////////////////////
case 1:
break;
case 2:
break;
default:
std::cout << "Error: unrecognized task number " << task << "n";
break;
}
return 0;
}
StringTokenizer.h
#ifndef INCLUDE_STRINGTOKENIZER_H
#define INCLUDE_STRINGTOKENIZER_H
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
class StringTokenizer
{
public:
StringTokenizer(const std::string& _str, const std::string& _delim);
~StringTokenizer(){};
std::string nextToken();
std::string nextToken(const std::string& delim);
private:
std::string token_str;
std::string delim;
};
#endif
StringTokenizer.cpp
#include "StringTokenizer.h"
StringTokenizer::StringTokenizer(const std::string& _str, const std::string& _delim)
{
if ((_str.length() == 0) || (_delim.length() == 0)) return;
token_str = _str;
delim = _delim;
/*
Remove sequential delimiter
*/
unsigned int curr_pos = 0;
while(true)
{
if ((curr_pos = token_str.find(delim,curr_pos)) != std::string::npos)
{
curr_pos += delim.length();
while(token_str.find(delim,curr_pos) == curr_pos)
{
token_str.erase(curr_pos,delim.length());
}
}
else
break;
}
/*
Trim leading delimiter
*/
if (token_str.find(delim,0) == 0)
{
token_str.erase(0,delim.length());
}
/*
Trim ending delimiter
*/
curr_pos = 0;
if ((curr_pos = token_str.rfind(delim)) != std::string::npos)
{
if (curr_pos != (token_str.length() - delim.length())) return;
token_str.erase(token_str.length() - delim.length(),delim.length());
}
}
std::string StringTokenizer::nextToken()
{
if (token_str.length() == 0)
return "";
std::string tmp_str = "";
unsigned int pos = token_str.find(delim,0);
if (pos != std::string::npos)
{
tmp_str = token_str.substr(0,pos);
token_str = token_str.substr(pos+delim.length(),token_str.length()-pos);
}
else
{
tmp_str = token_str.substr(0,token_str.length());
token_str = "";
}
return tmp_str;
}
std::string StringTokenizer::nextToken(const std::string& delimiter)
{
if (token_str.length() == 0)
return "";
std::string tmp_str = "";
unsigned int pos = token_str.find(delimiter,0);
if (pos != std::string::npos)
{
tmp_str = token_str.substr(0,pos);
token_str = token_str.substr(pos + delimiter.length(),token_str.length() - pos);
}
else
{
tmp_str = token_str.substr(0,token_str.length());
token_str = "";
}
return tmp_str;
}
1:我如何改变我的代码,使它将停止搜索输入当我完成输入?或者当它看到##已经输入时?(##表示输入结束)
2:这在我当前的代码中是可能的吗?
Linux和我的IDE都用g++编译
您正在使用来自std::cid
的输入流来读取数据,它只会在到达文件结束时停止,这就是为什么您需要终止输入,在windows中使用Ctrl-z,在Linux中使用Ctrl-d。
最简单的变化是逐行读取并独立处理它们。这将允许您读取终止标记##
而不继续进行(假设标记实际上是两个#
后面跟着一个新行)。
std::string line;
while (std::getline(std::cin, line)) {
if (line == "##") break;
// process a single line
}
如果不能保证分隔符后面跟着一行,则可能需要逐个字符地读取,但这是不可能的。
相关文章:
- 根据用户输入用字母填充矢量,并将"开始"和"结束"放在四肢
- 为什么我的程序在输入某个形状的面积的测量值后没有结束?
- 在Visual Studio中运行/调试C ++时,如何在结束时等待输入
- 确定用户字符输入 C++ 的结束
- 如何使用Chrono或ctime libaray输入设置的开始和结束时间
- 通过终端在文件中输入时检测EOF(文件结束)时出现问题
- 如何在输入结束时修复预期}错误
- cin函数是否添加了在输入结束时终止的null
- 错误:预期的“}”输入结束时 - 有一个
- 正则表达式在开头单独匹配单词,或者在输入结束时通过不重复字符串附加到某些内容但附加到某些内容
- 使用 std::getline 检测输入结束
- 使用 cin.peek() 和使用 cin.peek() 检测输入结束时出现问题
- C++查找数字总和,直到用户输入结束
- Cin,直到输入结束
- XTerm usnig键盘中的输入结束
- getline(),直到输入结束
- 自定义缓冲输入流.输入结束
- Windows 中的 Control+Z 表示输入 c++ 结束的信号
- Visual Studio 2013 c++控制台程序的输入结束
- 提振.Property_tree读取json预期的输入结束