#cpp #алгоритм
Можно ли в c++ создать функцию которая бы задавала маску при вводе?: Н-р номера телефона. "+7(***)***-**-**" при вводе уже должна быть выведена маска строки, при нажатии на клавиатуру вместо звездочек должны появляться цифры.
Ответы
Ответ 1
Вот такое у меня в винде получилось, работает с MinGW компилятором. Чисто демонстрация, дальше можете развивать как хотите уже. #include#include #include int main() { int length = 0; int pospos = 0; int posarrays[10] = {3,4,5,7,8,9,11,12,14,15}; int pos = posarrays[pospos]; char mask[17] = "+7(***)***-**-**"; printf("%s", mask); while(length != 10){ int ch = getch(); if(ch >= '0' && ch <= '9'){ length++; mask[pos] = ch; system("cls"); pospos++; pos = posarrays[pospos]; printf("%s", mask); } } return 0; } Ответ 2
Непосредственно при вводе (из консоли из стандартного потока) задать маску не получится. Но проверить номер телефона сразу после ввода можно используя регулярные выражения. Например: #include#include int main() { std::string tel = "+7(495)123-45-67"; std::regex rx("\\+([0-9]{1,3})(\\([0-9]{1,3}\\))([0-9\\-]{9})"); std::cout << std::regex_match(tel, rx) << std::endl; } Ответ 3
Вариант с выключенным эхом и getch() для POSIX систем (для Windows будет полезна ссылка) #include#include #include #include using namespace std; void turn_off_input_echo(); #ifdef __linux #include #include #include #include static termios s_savedAttributes = termios(); static void reset_input_mode() { tcsetattr(STDIN_FILENO, TCSANOW, &s_savedAttributes); } void turn_off_input_echo() { struct termios tattr; char *name; /* Make sure stdin is a terminal. */ if (!isatty(STDIN_FILENO)) { fprintf (stderr, "Not a terminal.\n"); exit(EXIT_FAILURE); } /* Save the terminal attributes so we can restore them later. */ tcgetattr(STDIN_FILENO, &s_savedAttributes); atexit(reset_input_mode); /* Set the funny terminal modes. */ tcgetattr (STDIN_FILENO, &tattr); tattr.c_lflag &= ~(ICANON | ECHO); /* Clear ICANON and ECHO. */ tattr.c_cc[VMIN] = 1; tattr.c_cc[VTIME] = 0; tcsetattr (STDIN_FILENO, TCSAFLUSH, &tattr); } int getch() { fd_set rfds; FD_ZERO(&rfds); FD_SET(STDIN_FILENO, &rfds); auto sts = select(STDIN_FILENO + 1, &rfds, nullptr, nullptr, nullptr); if (sts < 0) return -1; unsigned char ch; sts = read(STDIN_FILENO, &ch, sizeof(ch)); if (sts == -1) return -1; return ch; } #elif defined(__WIN32) #error Implement turn_off_input_echo() #endif class ProcessInputPattern { public: ProcessInputPattern(const string& pattern) : m_pattern(pattern) { } virtual ~ProcessInputPattern() = default; bool processInput() { init(); redraw(); while (true) { auto ch = getch(); switch (ch) { case EOF: case '\n': cout << endl; return m_pos == m_count; case 127: case 8: if (m_pos > 0) --m_pos; redraw(); break; default: if (doValidate(static_cast (ch))) { if (m_pos < m_count) { m_input[m_pos++] = ch; redraw(); } } break; } } } string getFilledPattern() const { string pattern = m_pattern; if (m_pos) { size_t idx = 0; for (auto& ch : pattern) { if (isPlaceholder(ch) && idx < m_pos) { ch = m_input[idx++]; } } } return pattern; } string getInputData() const { string data; if (!m_pos) return data; data.resize(m_pos); for (size_t idx = 0; idx < m_pos; ++idx) data[idx] = m_input[idx]; return data; } size_t currentPos() const { return m_pos; } size_t placeholdersCount() const { return m_count; } bool completeLine() const { return m_count == m_pos; } protected: void init() { m_pos = 0; m_count = 0; for (auto ch : m_pattern) { if (isPlaceholder(ch)) ++m_count; } m_input.resize(m_count); } void redraw() const { cout << '\r' << getFilledPattern() << flush; } virtual bool doValidate(char ch) const { return ch >= '0' && ch <= '9'; } virtual bool isPlaceholder(char ch) const { return ch == '*'; } private: string m_pattern; vector m_input; size_t m_count = 0; size_t m_pos = 0; }; int main() { turn_off_input_echo(); ProcessInputPattern inp("+7(***)***-**-**"); auto sts = inp.processInput(); if (sts) cout << "complete line: " << inp.getFilledPattern() << " / " << inp.getInputData() << endl; else cout << "partial line: " << inp.getFilledPattern() << " / " << inp.getInputData() << endl; return 0; } Вывод может выглядеть примерно так: $ ./a.out +7(436)365-37-78 complete line: +7(436)365-37-78 / 4363653778 $ ./a.out +7(444)***-**-** partial line: +7(444)***-**-** / 444 Решение призвано показать идею. Конкретную реализацию делайте на свой усмотрение. Возможно, лучшим вариантом будет рассмотреть библиотеки типа ncurses или S-Lang для управления терминалом или их аналоги для Windows (конкретики не подскажу).
Комментариев нет:
Отправить комментарий