我试图实现文本间隙文本编辑器,乍一看似乎一切正常。但是,在看似随机的点上,垃圾数据将进入混合状态。我已经删除了所有GUI和图形shennanigans的代码,只是文本gap类和它的伙伴在一个简单的main中实现,当使用g ++ main.cpp -o main运行时附加了控制台输出的日志。
P.S。文本间隙意味着将内存中的文本划分为至少两个数据结构,但将它们作为不间断的流呈现给用户,从而允许简单的插入/删除/游标语义。 Essentiall stringA + stringB = whatusersees。因此插入是前半部分的简单推回,而删除键是后半部分的弹出前端。向任一方向移动光标意味着只需从一个方向弹出并推入另一个方向。
PPS。在我的多次运行中,无论是作为字符还是作为最终字符串,都不会显示垃圾数据。此外,错误似乎是随机发生的,有时仅在几个字符之后,有时在很多之后。
PPPS。我可以通过使用string-n-copy函数清除整个值集来摆脱它,但除非我在concatTextBlockRange的前半部分运行它,否则它将无法工作。而且它相对昂贵,当我应该做的只是访问一个解除引用的迭代器,而不是访问一个解除引用的迭代器,然后计算它的一部分。
PPPPS。在concatTextBlockRange的前半部分之前没有垃圾数据,但只要dataIter指向“污染的”字符位置(包含字符(h或g或其他))以及一堆难以理解的垃圾数据,它就会出现。 。下半场似乎没有产生这个。虽然如果你继续输入密钥就会出现这一代。
CODE:
//test2.cpp
#include <iostream>
#include <string>
#include <list>
struct TextBlock{
std::list<char> data;
void assign( std::string inStr ) {
std::string::iterator myIter = inStr.begin();
std::string::iterator end = inStr.end();
while( myIter != end ) {
data.push_back( (*myIter) );
++myIter;
}
}
char pop_front( ) {
if( data.empty() == true ) { std::cout << "ERROR" << std::endl; return '#'; }
char toret = data.front();
data.pop_front();
return toret;
}
char pop_back( ) {
if( data.empty() == true ) { std::cout << "ERROR" << std::endl; return '?'; }
char toret = data.back();
data.pop_back();
return toret;
}
void push_front( char inChar ) { data.push_front( inChar ); }
void push_back( char inChar ) { data.push_back( inChar ); }
void backspace_key( ) { data.pop_back(); }
void delete_key( ) { data.pop_front(); }
int size( ) { return data.size(); }
bool empty( ) { return data.empty(); }
void PrintString( ) {
std::cout << ".:::PRINTING:::." << std::endl;
std::list<char>::iterator myIter = data.begin();
std::list<char>::iterator end = data.end();
while( myIter != end ) {
std::cout << (*myIter);
++myIter;
}
std::cout << std::endl;
}
};
std::string concatTextBlockRange( const TextBlock * const in1, const TextBlock * const in2, int backrange, int frontrange ) {
std::string toret;
std::list<char>::const_iterator dataIter1 = in1->data.end();
for( int i=0; i<backrange; i++ ) { --dataIter1; }
for( int i=0; i<backrange; i++ ) {
toret.append( &(*dataIter1) );
++dataIter1;
}
std::list<char>::const_iterator dataIter2 = in2->data.begin();
for( int i=0; i<frontrange; i++ ) {
toret.append( &(*dataIter2) );
++dataIter2;
}
return toret;
}
class Text{
public:
Text( std::string inFirst, std::string inSecond ) {
First.assign(inFirst);
Second.assign(inSecond);
}
void incGap( ) {
if( Second.empty() == false ) { First.push_back( Second.pop_front() ); }
}
void decGap( ) {
if( First.empty() == false ) { Second.push_front( First.pop_back() ); }
}
void incGap( int reps ) {
for( int i=0; i<reps; i++ ) { First.push_back( Second.pop_front() ); }
}
void decGap( int reps ) {
for( int i=0; i<reps; i++ ) { Second.push_front( First.pop_back() ); }
}
void insert( char inKey ) {
First.push_back( inKey );
}
void delete_key( ) {
Second.delete_key();
}
void backspace_key( ) {
First.backspace_key();
}
void space_key( ) {
insert(' ');
}
std::string retString( int backrange, int frontrange ) {
if( frontrange >= Second.size() ) { frontrange = Second.size(); }
if( backrange >= First.size() ) { backrange = First.size(); }
return concatTextBlockRange( &First, &Second, backrange, frontrange );
}
private:
TextBlock First, Second;
};
int main(){
Text myText( "The cat " , " because " );
char in;
bool tripped;
while( in != '`' ) {
std::cout << myText.retString(1000,1000) << std::endl;
tripped = false;
std::cin >> in;
if( in == ']' ) { myText.incGap(); tripped = true; }
if( in == '[' ) { myText.decGap(); tripped = true; }
if( in == '\\' ) { myText.backspace_key(); tripped = true; }
if( in == '-' ) { myText.delete_key(); tripped = true; }
if( in == '_' ) { myText.space_key(); tripped = true; }
if( tripped == false ) { myText.insert( in ); }
}
return 0;
}
CONSOLE:
The cat because
qwer
The cat q because
The cat qw because
The cat qwe because
The cat qwer because
qwerttyyu
The cat qwerq because
The cat qwerqw because
The cat qwerqwe because
The cat qwerqwer because
The cat qwerqwert because
The cat qwerqwertt because
The cat qwerqwertty because
The cat qwerqwerttyy because
The cat qwerqwerttyyu because
yuiop
The cat qwerqwerttyyuy because
The cat qwerqwerttyyuyu because
The cat qwerqwerttyyuyui because
The cat qwerqwerttyyuyuio because
The cat qwerqwerttyyuyuiop because
sdfghj
The cat qwerqwerttyyuyuiops because
The cat qwerqwerttyyuyuiopsd because
The cat qwerqwerttyyuyuiopsdf because
The cat qwerqwerttyyuyuiopsdfg because
The cat qwerqwerttyyuyuiopsdfgh because
The cat qwerqwerttyyuyuiopsdfghj because
ertasfj
The cat qwerqwerttyyuyuiopsdfghje because
The cat qwerqwerttyyuyuiopsdfghjer because
The cat qwerqwerttyyuyuiopsdfghjert because
The cat qwerqwerttyyuyuiopsdfghjerta because
The cat qwerqwerttyyuyuiopsdfghjertas because
The cat qwerqwerttyyuyuiopsdfghjertasf because
The cat qwerqwerttyyuyuiopsdfghjertasfj because
dsrtjgf
The cat qwerqwerttyyuyuiopsdfghjertasfjd because
The cat qwerqwerttyyuyuiopsdfghjertasfjds because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsr because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrt because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtj because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjg because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgf because
dftjdgh
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfd because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfdf because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfdft because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfdftj because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfdftjd because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfdftjdg because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfdftjdgh because
sfgkjsdfgj
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfdftjdghs because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfdftjdghsf because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfdftjdghsfg because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfdftjdghsfgk��� because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfdftjdghsfgk���j���fghj1 because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfdftjdghsfgk���j���fghj1s���` because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfdftjdghsfgk���j���fghj1s���`d��� because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfdftjdghsfgk���j���fghj1s���`d���f���` because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfdftjdghsfgk���j���fghj1s���`d���f���`g��� because
The cat qwerqwerttyyuyuiopsdfghjertasfjdsrtjgfdftjdghsfgk���j���fghj1s���`d���f���`g���j���` because
感谢阅读!
答案 0 :(得分:2)
你使用string::append
的错误重载,即append(const char *)
。它期望作为一个论点NUL
- 终止,所谓的&#34; C&#34;字符串与std::list<char>::const_iterator
返回的字符串不兼容。
修复此错误的最短方法是通过编写append(size_t, char)
等来调用另一个重载toret.append(1, *dataiter1)
。
通过在Valgrind内存调试器下运行示例程序,我可以相对轻松地发现这个bug:
仅供参考,您是否检查了__gnu_cxx::rope
我认为您可以替换自己的差距缓冲区实现?