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

自制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 java在应用程序里获取不到扬声器设备
  • ¥15 echarts动画效果的问题,请帮我添加一个动画。不要机器人回答。
  • ¥60 许可证msc licensing软件报错显示已有相同版本软件,但是下一步显示无法读取日志目录。
  • ¥15 Attention is all you need 的代码运行
  • ¥15 一个服务器已经有一个系统了如果用usb再装一个系统,原来的系统会被覆盖掉吗
  • ¥15 使用esm_msa1_t12_100M_UR50S蛋白质语言模型进行零样本预测时,终端显示出了sequence handled的进度条,但是并不出结果就自动终止回到命令提示行了是怎么回事:
  • ¥15 前置放大电路与功率放大电路相连放大倍数出现问题
  • ¥30 关于<main>标签页面跳转的问题
  • ¥80 部署运行web自动化项目
  • ¥15 腾讯云如何建立同一个项目中物模型之间的联系