c++将文本附加到字符串中,直到看到特定的字符
c++ appending text into a string until see a specific character
我有不止一个这样的输入文件:
>1aab_
GKGDPKKPRGKMSSYAFFVQTSREEHKKKHPDASVNFSEFSKKCSERWKT
MSAKEKGKFEDMAKADKARYEREMKTYIPPKGE
>1j46_A
MQDRVKRPMNAFIVWSRDQRRKMALENPRMRNSEISKQLGYQWKMLTEAE
KWPFFQEAQKLQAMHREKYPNYKYRPRRKAKMLPK
>1k99_A
MKKLKKHPDFPKKPLTPYFRFFMEKRAKYAKLHPEMSNLDLTKILSKKYK
ELPEKKKMKYIQDFQREKQEFERNLARFREDHPDLIQNAKK
>2lef_A
MHIKKPLNAFMLYMKEMRANVVAESTLKESAAINQILGRRWHALSREEQA
KYYELARKERQLHMQLYPGWSARDNYGKKKKRKREK
这里,我要做的:
vector <string> names;
vector <string> seqs;
names.resize(total); //"total" is already known.
seqs.resize(total);
counter=0;char input;
while ((input = myInput.get()) != EOF)
{
if(input=='>')
names[counter]= take all line (>1aab_, >1j46_A, so...)
else
untill the see next '>' append the character into sequence[counter]
counter++;
}
最后是这样的:
names[0]=">1aab_"
sequence[0]="GKGDPKKPRGKMSSYAFFVQTSREEHKKKHPDASVNFSEFSKKCSERWKTMSAKEKGKFEDMAKADKARYEREMKTYIPPKGE"
等等。
我想了两个小时都想不通。有人能帮我吗?提前谢谢。
有几种方法可以解决这个问题;我会给出一些例子,但我不是在测试/编译这些代码,所以可能会有一些小错误——逻辑是重要的。
由于您的伪代码似乎是逐字符处理输入的,因此我将其视为一种要求。
你似乎认为它是用一对循环来实现的——一个用于读取名称,另一个用于阅读序列——它们被封装在一个外部循环中,以便处理所有记录。
这看起来像以下内容:
// first character in file should be a '>', indicating the start
// of a record.
input = myInput.get();
if (input != '>')
{
std::cerr << "Malformed input file!" << std::endl;
return /*...*/;
}
do
{
// record name continues up until the newline
while ((input = myInput.get()) != EOF)
{
if (input == 'n' || input == 'r')
break;
names[counter].push_back(input);
}
// read sequence until we hit a '>' or EOF
while ((input = myInput.get()) != EOF)
{
if (input == '>')
{
// advance to next record number
counter++;
break;
}
sequence[counter].push_back(input);
}
} while (input != EOF && counter < total);
您还会注意到,我将初始'>'的检查移到了循环之前,这是一种吸收(和丢弃)字符的方式,也是对输入进行基本健全性检查的方式。这是因为我们真的用这个字符来标记序列的结束(而不是"记录的开始")——当我们进入循环时,我们假设我们已经在读取记录名称。
另一种方法是使用状态机。本质上,这利用了额外的变量来跟踪解析器所处的状态。
对于这种特殊情况,您只有两种状态:要么正在读取记录名,要么正在读取序列。所以,我们可以只使用一个布尔值来跟踪我们所处的状态
有了状态变量,我们就可以根据所处的状态来决定如何处理刚刚读取的字符。在最简单的级别上,如果我们处于"读取记录名称"状态,我们会将字符添加到names
变量中,否则我们会将其添加到sequence
变量中。
// state flag to indicate if we're currently reading a name line,
// i.e. a line starting with ">"
// This should be set true by the first record we encounter, so
// we'll set it false (to indicate we're reading a sequence) in
// order to allow us to detect bad input files.
bool reading_name = false;
// indicate we're on the first record, so we can avoid incrementing
// the record counter
bool first_record = true;
// process input character-by-character until end of file
while ((input = myInput.get()) != EOF)
{
// check for start of new record
if (input == '>')
{
// for robustness, verify we're not already reading a name,
// as this probably indicates invalid input
if (reading_name)
{
std::cerr << "Input is malformed?!" << endl;
break;
}
// switch to reading name state
reading_name = true;
// advance to next record, but only if it isn't the first record
if (first_record)
{
// disable the first_record flag, and explicitly set the
// record counter to 0.
first_record = false;
counter = 0;
}
else if (++counter >= total)
{
std::cerr << "Error: too many records!" << std::endl;
break;
}
}
// first character in file should start a new record
else if (first_record)
{
std::cerr << "Missing record start character at beginning of input!" << std::endl;
break;
}
// make sure we are processing a valid record number
else if (counter >= total)
{
std::cerr << "Invalid record number!" << std::endl;
break;
}
// continue reading the name
else if (reading_name)
{
// check if we've reached the end of the line; you
// may also want/need to check for r if your input
// files may have Windows-style line endings
if (input == 'n')
{
// switch to reading sequence state
reading_name = false;
}
else
{
// add character to current name
names[counter].push_back(input);
}
}
// continue reading the sequence
else
{
// you might need to handle line ending characters here,
// maybe just skipping them?
// add character to current sequence
sequence[counter].push_back(input);
}
}
这增加了相当多的复杂性,这对这项特定的工作来说有值得怀疑的价值,但确实使未来添加更多的州变得更容易。它还有一个好处,即在代码中只有一个位置可以完成I/O,这减少了出错的机会(不检查EOF、溢出数组边界等)
在这种情况下,我们实际上使用'>'字符作为新记录正在启动的指示符,因此我们添加了一些额外的逻辑,以确保所有内容都能与记录计数器一起正常工作。您也可以为counter
变量使用一个带符号的整数,并从-1
开始,这样它在第一条记录开始时会增加到0,但使用带符号的变量对数组进行索引不是一个好主意。
有更多的方法可以解决这个问题,但希望这能给你一个开始自己解决问题的地方。
- 将字符指针十六进制转换为字符串并保存在文本文件C++中
- 如何在C++中确定文本文件中的元素是字符还是数字
- 如何从文本文件中读取数值,直到遇到字符类型?
- 如何在C++中反转文本文件中字符的顺序?
- 如何从代码本身向 wxwidgets 中的文本控件插入字符?
- 无法将整个文本文件复制到字符数组
- 在处理任何字符大小的模板中使用字符串文本
- 从我的 2DgridArray 中的文本文件中获取每个字符
- 从文本文件 (C++) 生成字符矩阵
- 如何在给定文本中用字符数组替换符号
- 如何在文本文件中间插入字符
- 将字符串文本分配给字符*:const_cast<字符 *> 与使用 char 数组
- 如何从文本文件中一次读取一个字符
- 字符* 文本消息[] 如何在内存中格式化?
- VS2013 字符文本不能作为 MSDN 的规范工作
- 为什么 C 中的字符文本大小与 C++ 中的字符文本大小不同
- 以本地化安全的方式比较C++中的字符串/字符和字符串/字符文本
- 在块中分配字符文本"if"
- C++编译时将字符串文本转换为多字符文本
- C++将字符串文本添加到字符文本