linux-rm 2022-03-06 17:33 采纳率: 50%
浏览 51
已结题

自制c++密码程序报错,如何解决?(操作系统-linux)

运行平台:linux,编译器:g++
g++版本:

# g++ -v
使用内建 specs。
COLLECT_GCC=/usr/bin/g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
目标:x86_64-redhat-linux
配置为:../configure --enable-bootstrap --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl=/builddir/build/BUILD/gcc-11.2.1-20220127/obj-x86_64-redhat-linux/isl-install --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux --with-build-config=bootstrap-lto --enable-link-serialization=1
线程模型:posix
Supported LTO compression algorithms: zlib zstd
gcc 版本 11.2.1 20220127 (Red Hat 11.2.1-9) (GCC)

问题/错误:有时按退格键会报错,但编译时没有问题
如文本/视频后半段所示:
https://v.douyin.com/NNHWbSx/

# g++ -o test a.cpp
#ls -a
.  ..  a.cpp  main.cpp  test
# ./test
请输入 /builddir/build/BUILD/gcc-11.2.1-20220127/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_string.h:1059: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::reference std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator[](std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::reference = char&; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]: Assertion '__pos <= size()' failed.
zsh: IOT instruction (core dumped)  ./test
error:134

代码:

/*
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <iostream>
using namespace std;

char getch()
{
    char c;
    // static struct termios oldt, newt;
    // tcgetattr(STDIN_FILENO, &oldt);
    // newt = oldt;
    // newt.c_lflag &= ~(ICANON);
    // tcsetattr(STDIN_FILENO, TCSANOW, &newt);
    system("stty -echo");
    // while ((c = getchar()) != '\n')
    while ((c = getchar()))
    {
        cout << 8;
        return c;
    }
    // system("stty echo");
    // tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
    return -1;
}
*/

#include <stdio.h>
#include <termios.h>
#include <assert.h>
#include <string.h>
#include <iostream>
#include <unistd.h>

using namespace std;

char getch()
{

    char c = 0;

    struct termios org_opts, new_opts;

    int res = 0;

    //-----  store old settings -----------

    res = tcgetattr(STDIN_FILENO, &org_opts);

    assert(res == 0);

    //---- set new terminal parms --------

    memcpy(&new_opts, &org_opts, sizeof(new_opts));

    new_opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOKE | ICRNL);

    tcsetattr(STDIN_FILENO, TCSANOW, &new_opts);

    c = getchar();

    //------  restore old settings ---------

    res = tcsetattr(STDIN_FILENO, TCSANOW, &org_opts);

    assert(res == 0);

    return c;
}

string get()
{
    char a;
    int i = 0;
    string PassWord;
    cout << "请输入密码:";
    while (1)
    {
        a = getch(); //获取输入
        if (PassWord.length() >= 0)
        {
            switch (a)
            {
            case 10: //回车
                return PassWord;
                break;

            case 127: //退格
                cout << "\b \b";
                i++;
                PassWord[PassWord.length() - i] = '\0';
                break;

            default:
                PassWord += a;
                cout << "*";
                break;
            }
        }
        else
        {
            cout << "\r密码为空,请输入密码:";
            continue;
        }

        /*
                a = getch(); //获取输入的密码
                if (a == 10) //回车返回
                {
                    if (PassWord.length() >= 0)
                    {
                        break;
                    }
                }
                if (a == 127) //退格
                {
                    if (PassWord.length() == 0) //如果第一个键为退格键
                    {
                        cout << "密码为空,请输入密码:";
                        continue;
                    }
                    else
                    {
                        cout << "\b \b";
                        i++; //清除所要删掉的字符
                        PassWord[PassWord.length() - i] = '\0';
                    }
                }
                else
                {
                    PassWord += a;
                    cout << "*";
                }
            }

            */
        // return PassWord;
    }
}

int main()
{
    cout << get() << endl;
    return 0;
}

修改过80~105行,但问题依旧
修改前

                a = getch(); //获取输入的密码
                if (a == 10) //回车返回
                {
                    if (PassWord.length() >= 0)
                    {
                        break;
                    }
                }
                if (a == 127) //退格
                {
                    if (PassWord.length() == 0) //如果第一个键为退格键
                    {
                        cout << "密码为空,请输入密码:";
                        continue;
                    }
                    else
                    {
                        cout << "\b \b";
                        i++; //清除所要删掉的字符
                        PassWord[PassWord.length() - i] = '\0';
                    }
                }
                else
                {
                    PassWord += a;
                    cout << "*";
                }
            }

我的预期(不论怎么按退格都不会报错):

# ./test
请输入密码:****1235
  • 写回答

2条回答 默认 最新

  • [PE]经典八炮 2022-03-06 18:57
    关注

    首先,这人就是拿出来炫耀一下,竟然当真了...
    你这个删除算法太怪异了,一般不都是用pop_back吗????

    #include<iostream>
    #include<conio.h>
    std::string get()
    {
        std::string PassWord;
        while (1)
        {
            char a = _getch(); //获取输入
            switch (a)
            {
            case '\r': //回车(我这里是\r,不知道你那里是\r还是\n)
                if(PassWord.size())
                    return PassWord;
                break;
            case '\b': //退格
                if (PassWord.size())
                {
                    std::cout << "\b \b";
                    PassWord.pop_back();
                }
                break;
            default:
                PassWord += a;
                std::cout << "*";
                break;
            }
        }
    }
    int main()
    {
        std::cout << get();
        return 0;
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 3月20日
  • 已采纳回答 3月12日
  • 创建了问题 3月6日

悬赏问题

  • ¥20 收一个快手协议下单算法
  • ¥15 求一个图片中的成交量选股公式
  • ¥15 已知正方形内随机生成坐标matlab
  • ¥30 关于#python#的问题:我想要的是这79个大特征对于房屋售价的最大的影响前十名(相关搜索:随机森林)
  • ¥15 使用matlab计算自定义特殊函数的二重积分,改变积分顺序所得的结果不同的问题?
  • ¥15 mysql做碎片化处理老是报错怎么办
  • ¥15 如何正确在vs2010中初始化map对象
  • ¥30 mmdet3d模型部署问题
  • ¥15 comsol仿真反射率、吸收率时峰值位置和深度不对!
  • ¥30 Visual Studio找不到sdk,如何解决?