在C ++中实现Text-Gap后的奇怪行为

时间:2015-01-24 17:42:44

标签: c++

我试图实现文本间隙文本编辑器,乍一看似乎一切正常。但是,在看似随机的点上,垃圾数据将进入混合状态。我已经删除了所有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 

感谢阅读!

1 个答案:

答案 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我认为您可以替换自己的差距缓冲区实现?