LINUX.ORG.RU

C++ и виндовая getche() в Linux

 , ,


0

1

Всем привет! Изучаю C++ по книге Лафоре - ООП в C++.

Всё шло прекрасно, до момента появления в примерах виндового заголовочного файла «conio.h» и входящей в него функции getche().

Пошарившись по форумам нашёл кусок кода который имитирует функцию getche(), но приспособив её в код примера из книги, на выходе получил, что ввод с клавиатуры не осуществляется, вот уже час чешу репу и не могу понять где костыль, надеюсь на вашу помощь. Если в кратце, то программа подсчитывает количество введённых символов и слов, а после нажатия ENTER, выводит результат. Ниже привожу листинг:

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

int getche()
{
  struct termios oldt, newt;
  int ch;
  tcgetattr(STDIN_FILENO, &oldt);
  newt = oldt;
  newt.c_lflag &= ~(ICANON | ECHO);
  tcsetattr(STDIN_FILENO, TCSANOW, &newt);
  ch = getchar();
  tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
  return ch;
}
int main(){
    int symbols = 0;
    int words = 1;
    char ch = 'a';
    cout << "Введите строку: ";
    while(ch != '\r'){
        ch = getche();
        if(ch == ' ')
            words++;
        else
            symbols++;
    }
    cout << "\nСлов: " << words << endl;
    cout << "Букв: " << (symbols-1) << endl;
}
Так же буду признателен, если посоветуете хорошую книгу по c++ для начинающих, в духе Лафоре, но только без вендовставок, и ещё пару книг для последующего изучения.


Во-первых символ перевода строки — \n. Во-вторых код наверняка сломается на utf-8.

PolarFox ★★★★★ ()

Почитай Прату. И почему нельзя просто использовать cin.get[line]()?

z00ke ()
Последнее исправление: z00ke (всего исправлений: 3)
Ответ на: комментарий от PolarFox

1. \n - сработает после прекращения цикла, так что он тут вообще никак не влияет. 2. Не сломается, если я не буду вводить клавы кириллицу.

slip ()
Ответ на: комментарий от z00ke

И почему нельзя просто использовать cin.get[line]()?

А можно по подробнее? Я видел данную функцию, но попытка припилить не увенчалась успехом (

slip ()

виндового заголовочного файла «conio.h»

Это DOSовский еще файл. Его ближайшим аналогом в Linux является ncurses.h, но ты реально не хочешь туда.

tailgunner ★★★★★ ()
Ответ на: комментарий от z00ke

Поковыряв код, заметил интересную фичу, если потоки вывода поместить вне цикла while, то по нажатию ENTER цикл не прервывается, а если потоки переместить в цикл после else, то после нажатия ENTER вылетает простыня:

слов: X
букв: Y
слов: X
букв: Y
....
слов: X
букв: Y
итого сейчас код имеет вид:
#include <iostream>

using namespace std;

int main(){
    int symbols = 0;
    int words = 1;
    char ch = 'a';
    cout << "Введите строку: ";
    while(ch != '\r'){
        ch = cin.get();
        if(ch == ' '){
            words++;
        }
        else{
            symbols++;
        }
        //cout << "Слов: " << words << endl;  // потоки внутри цикла
        //cout << "Букв: " << (symbols-1) << endl; // Код работает, но получается простыня
    }
    cout << "Слов: " << words << endl;
    cout << "Букв: " << (symbols-1) << endl;
}

slip ()

ЕМНИП в Лафоре в приложении приводились какие-то костылики для совместимости, с недостающими (как в этом случае) заголовочниками, чтобы примеры можно было на любой системе компилировать. Ну и традиционно на сайте издательства можно порыскать.

Проверить не могу, потому что мой бумажный экземпляр давно ушёл по рукам.

yoghurt ★★★★★ ()

ЕМНИП у Шилдта вендовставок не было. Я, кстати, на первом курсе пользовался этим костылем(и еще парой с очисткой входного потока и экрана), все работало нормально :/

CrossFire ★★★★★ ()
Последнее исправление: CrossFire (всего исправлений: 1)
Ответ на: комментарий от CrossFire

Всё! Нашёл в чём костыль был! Надо было всего-то заменить '\r' на '\n' и цикл благополучно завершался :D

Всем спасибо за помощь, варианты хороших учебников по прежнему принимаю )

slip ()
Ответ на: комментарий от slip

заметил интересную фичу

у тебя cin.get() тянет ввод оттуда, куда ты делаешь вывод через cout. эта фича называется «непонимание работы программы».

x0r ★★★★★ ()
Ответ на: комментарий от slip

Проблема не в C++ и потоках, а в буферизации ввода терминалом. Чтобы всё работало как с getche() необходимо отключить буферизацию. Рабочий пример:

#include <iostream>

#include <termios.h>
#include <unistd.h>

using namespace std;

int main(){
    int symbols = 0;
    int words = 1;
    char ch = 'a';

    // отключение буферизации
    termios term;
    tcgetattr(STDIN_FILENO, &term);
    term.c_lflag &= ~ICANON;
    tcsetattr(STDIN_FILENO, TCSANOW, &term);

    cout << "Введите строку: ";
    while(ch != '\n'){
        cin.read(&ch, 1U);
        if(ch == ' '){
            words++;
        }
        else{
            symbols++;
        }
        cout << "\nСлов: " << words << endl;  // потоки внутри цикла
        cout << "Букв: " << (symbols-1) << endl; // Код работает, но получается простыня
    }
    cout << "Слов: " << words << endl;
    cout << "Букв: " << (symbols-1) << endl;
}

xaizek ★★★★★ ()
Ответ на: комментарий от slip

Ты не правильно используешь терминологию: костыли – некие грязноватые ухищрения для достижения работоспособности. А у тебя был баг, на который указали в первом посте, да)

CrossFire ★★★★★ ()
Ответ на: комментарий от CrossFire

Ну это conio.h не входит в стандарт gcc, а значит это как вы выразились «Некое грязноватое ухищрение», только применяемое в вантузе, а значит это костыль. ))

slip ()

Забей пока на плюсы учи для начала С по книге K&R.

Dron ★★★★★ ()
Ответ на: комментарий от slip

Нашёл в чём __костыль__ был!
вот уже час чешу репу и не могу понять где __костыль__, надеюсь на вашу помощь

Кусок кода, переключающий режимы терминала — костыль, если почему-то не работает, это баг.

CrossFire ★★★★★ ()
Ответ на: комментарий от slip

Ну это conio.h не входит в стандарт gcc

оно вообще никуда не входит кроме MS-DOS, и Windows(в которую добавили для совместимости с MS-DOS).

Не мучайся, используй fgetc(3) в чистом C, а в плюсах cin::

(впрочем на плюсах тебе пока рано)

emulek ()

Изучаю C++ по книге Лафоре - ООП в C++.

Всё шло прекрасно, до момента появления в примерах виндового заголовочного файла «conio.h» и входящей в него функции getche().

Это в каком издании было? Зачем читаете устаревшее издание?

sbar ()

А кто это поправил темы в тэге code? Зачем такой синий странный? Фу!

cdshines ★★★★ ()

читаю книгу по С++, очень нравится. Автор Шилдт, називается «С++ для начинающих »

anonymous ()
Ответ на: комментарий от cdshines

А кто это поправил темы в тэге code? Зачем такой синий странный? Фу!

Если ты про std и cout, то согласен, с tango css вообще не сочитается.

korvin_ ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.