在C++中实现文本间隙后的奇怪行为

Strange Behavior After Implementing Text-Gap In C++

本文关键字:间隙 C++ 实现 文本      更新时间:2023-10-16

我试图实现一个文本间隙文本编辑器,乍一看似乎一切正常。但是,在看似随机的点,垃圾数据将进入混合。我已经包含了删除所有 GUI 和图形恶作剧的代码,只是在一个简单的 main 中实现了文本间隙类及其伙伴,并在使用 g++ main 运行时附加了控制台输出的日志.cpp-o main。

P.S. 文本间隙意味着将内存中的文本划分为至少两种数据结构,但将它们作为不间断的流呈现给用户,从而允许轻松插入/删除/光标语义。Essentiall stringA+stringB=whatusersees.因此,插入是前半部分的简单推回,删除键是后半部分的弹出式前置。向任一方向移动光标意味着简单地从一个方向弹出并向另一个方向推动。

.PPS。在我的多次运行中,垃圾数据在输入被推送时不会显示,无论是作为字符还是作为最终字符串。此外,错误似乎是随机发生的,有时只在几个字符之后,有时在很多字符之后。

购买力平价。我可以通过基本上使用 string-n-copy 函数来清理整组值来摆脱它,但除非我在 concatTextBlockRange 的前半部分运行它,否则这将不起作用。它相对昂贵,当我应该做的只是访问一个取消引用的迭代器,而不是访问一个取消引用的迭代器,然后计算它的一部分。

购买力平价。在concatTextBlockRange的前半部分之前没有垃圾数据,但是每当dataIter指向"污染"的字符位置时,它就会出现,该位置包含字符(h或g或其他)以及一堆难以理解的垃圾数据。后半部分似乎没有产生这种情况。生成是不可靠的,尽管如果您不断输入密钥,就会发生。

法典:

//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;
}

安慰:

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 

感谢您的阅读!

您使用了错误的string::append重载,即append(const char *) 。 它期望一个NUL终止的所谓"C"字符串作为参数,该字符串与从std::list<char>::const_iterator返回的内容不兼容。

修复此错误的最短方法是通过编写toret.append(1, *dataiter1)等调用另一个重载append(size_t, char)

  • http://www.cplusplus.com/reference/string/string/append/

通过在 Valgrind 内存调试器下运行您的示例程序,我可以相对容易地发现此错误:

  • http://valgrind.org/docs/manual/quick-start.html

仅供参考,您是否检查过我认为您可以替换自己的间隙缓冲区实现的__gnu_cxx::rope

  • https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00066.html