Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
syberuser
0 / 0 / 1
Регистрация: 06.12.2012
Сообщений: 30
1

Подсчет вводимых символов

31.10.2016, 15:12. Просмотров 966. Ответов 8
Метки нет (Все метки)

Добрый день!
решил приобщиться к прекрасному и в качестве старта выбрал книгу: "Язык программирования Си Брайан Керниган, Деннис Ритчи 3-е издание". пишу в консольке на mint17

есть в ней вот такой пример:
C
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
// подсчет вводимых символов. v1.0
main()
{
        long nc;
        nc = 0;
        while (getchar() != EOF) 
                ++nc;
        printf ("%ld\n", nc);
}
однако, окончание ввода и нажатие Enter не вызывают EOF. т.е. программа не выходит из цикла. если код printf ("%ld\n", nc); поместить внутрь цикла - то он продолжает увеличивать nc после каждого последующего ввода символов + enter

в книжке написано вот так:
Кликните здесь для просмотра всего текста
Существует проблема: как отличить конец ввода от обычных читаемых данных. Решение заключается в том,
чтобы функция getchar по исчерпании входного потока выдавала в качестве результата такое значение,
которое нельзя было бы спутать ни с одним реальным символом. Это значение есть EOF (аббревиатура от end
of file — конец файла). Мы должны объявить переменную с такого типа, чтобы его "хватило" для
представления всех возможных результатов, выдаваемых функцией getchar. Нам не подходит тип char,
так как c должна быть достаточно "емкой", чтобы помимо любого значения типа char быть в состоянии
хранить и EOF. Вот почему мы используем int, а не char.
EOF — целая константа, определенная в <stdio.h>. Какое значение имеет эта константа — неважно, лишь
бы оно отличалось от любого из возможных значений типа char. Использование именованной константы с
унифицированным именем гарантирует, что программа не будет зависеть от конкретного числового
значения, которое, возможно, в других Си-системах будет иным.


я что-то делаю не так или есть другая причина такого поведения кода?
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
31.10.2016, 15:12
Ответы с готовыми решениями:

Подсчет вводимых символов
Во второй версии подсчета вводимых символов написан вот такой цикл: #include...

Подсчет вводимых символов
Код взял из книжки кернигана и он не понятно почему не работает. Программа...

Подсчет вводимых символов
При компиляции ошибок нет. При запуске я ввожу текст, но в итоге ничего не...

Подсчет вводимых символов
Когда нажимаешь enter вместо результата переходит на следующюю строчку, как...

Подсчет вводимых символов работает некорректно
здравствуйте! только начинаю изучение Си. написал программу из учебника...

8
Max Dark
шКодер самоучка
1982 / 1754 / 866
Регистрация: 09.10.2013
Сообщений: 3,869
Записей в блоге: 6
Завершенные тесты: 2
31.10.2016, 15:32 2
Лучший ответ Сообщение было отмечено syberuser как решение

Решение

Цитата Сообщение от syberuser Посмотреть сообщение
я что-то делаю не так или есть другая причина такого поведения кода?
при вводе в консоли символ окончания ввода тоже нужно набрать.
для windows это комбинация Ctrl+Z, в *nix - Ctrl+D
0
syberuser
0 / 0 / 1
Регистрация: 06.12.2012
Сообщений: 30
31.10.2016, 15:41  [ТС] 3
вот почему, поиском вообще ничего не нашел, а в похожих темах, после создания своей - ответ лежит
видимо поиском тоже не умею пользоваться

EOF вызывается ctrl+D (именно большая D, т.е. ctrl+shift+D), причем, если после ввода строки не нажат Enter - то ctrl+D 2 раза. иначе - один, но символов будет на один больше, ибо перевод строки

спасибо модератору за подсветку синтаксиса. сам не нашел=)
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
4848 / 2492 / 696
Регистрация: 18.10.2014
Сообщений: 4,319
31.10.2016, 18:18 4
Цитата Сообщение от syberuser Посмотреть сообщение
если после ввода строки не нажат Enter - то ctrl+D 2 раза
Дело в том, что Ctrl+D в Линуксе - это совсем никакой не EOF, а команда терминала, которая просто насильно проталкивает накопившийся на данный момент входной буфер строки терминала на вход программе, т.е. ждущей входа функции чтения стандартной библиотеки (там внутри стоит какой-нибудь вызов read или аналог).

Если в этот момент входной буфер был пуст, то ждущая входа read считывает 0 байт из входа, что и интерпретируется стандартной библиотекой, как ситуация EOF.

Если же в этот момент входной буфер был не пуст, то он просто проталкивается в функцию чтения и ситуации EOF не возникает.

Другими словами Ctrl+D - это фактически просто аналог клавиши Enter, с той только разницей, что клавиша Enter добавляет во входной буфер символ перевода строки и проталкивет этот буфер в программу, а Ctrl+D - ничего не добаваляет, а просто проталкивет буфер в программу.
3
syberuser
0 / 0 / 1
Регистрация: 06.12.2012
Сообщений: 30
01.11.2016, 10:48  [ТС] 5
С практической точки зрения, в процессе обучения мне не важно как работает ctrl+D. Важно, что работает в принципе. Но в целях повышения образованности - как то не стыкуется:

соглашусь, что ctrl+D - это команда терминала, но т.к.
C
1
while (getchar() != EOF)
заканчивается, то, все таки та самая -1 должна бы передаваться в буфер.

И в этом примере мы так же получим -1 при нажатии ctrl+D
C
1
2
3
   while ((с=getchar()) != EOF) 
                ++nc;
        printf ("%d\n", c);
Исходя из этого, могу предположить, что
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
а Ctrl+D - ничего не добаваляет
- так же не верно, ибо добавляет и это видно.
0
LFC
730 / 535 / 416
Регистрация: 17.09.2015
Сообщений: 1,598
01.11.2016, 11:05 6
Цитата Сообщение от syberuser Посмотреть сообщение
поиском вообще ничего не нашел
https://ru.wikipedia.org/wiki/EOF
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
4848 / 2492 / 696
Регистрация: 18.10.2014
Сообщений: 4,319
01.11.2016, 11:16 7
Цитата Сообщение от syberuser Посмотреть сообщение
все таки та самая -1 должна бы передаваться в буфер.
Почему вы решили, что эта -1 должна обязательно пройти через буфер мне не ясно. Это не так.

Никакой -1 в буфер помещаться не должно. Функция getchar() внутри вызывает классическую функцию read(), и когда read() возвращает 0 (т.е. "не смогла прочитать ни одного байта"), тогда getchar() просто возвращает код возврата -1 (т.е. EOF).

EOF - это просто код завершения getchar(), никакого прямого отношения к комбинации Ctrl+D не имеющий.

Добавлено через 8 минут
Цитата Сообщение от syberuser Посмотреть сообщение
так же не верно, ибо добавляет и это видно.
Если бы это "было видно", то оно было бы "видно" и при нажатии Ctrl+D при непустом буфере строки. А как вы сами видели, при непустом буфере строки после такого нажатия Ctrl+D никакого EOF в буфере найти не получается. Куда же оно девалось?
1
Evg
Эксперт CАвтор FAQ
19626 / 7318 / 551
Регистрация: 30.03.2009
Сообщений: 20,462
Записей в блоге: 30
01.11.2016, 16:08 8
getchar одновременно выдаёт две сущности:
1. Информация о том, что ввод завершён
2. Информацию о коде символа, если ввод ещё не завершён.

Обе эти сущности объединены в одном результате типа int. И закодированы так, что если возвращаемое значение равно EOF (-1), то имеем пункт 1, иначе имеем пункт 2, а само значение совпадает с кодом введённого символа

Идеологически так поступать некрасиво. Идеологически правильным (или даже "красивым") было бы иметь два интерфейса - один проверят, есть ли данные, а второй эти данные извлекает. Но многие стандартные функции Си спроектированы криво. Одной из причин является то, что в старые времена сильно гнались за производительностью. Думаю, в случае getchar'а именно производительность и явилось причиной
1
syberuser
0 / 0 / 1
Регистрация: 06.12.2012
Сообщений: 30
01.11.2016, 16:56  [ТС] 9
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
и при нажатии Ctrl+D при непустом буфере строки.
непустой буфер строки = ввел значение и не нажал Enter ?
Если да, то действительно ctrl+D срабатывает так же как Enter. В принипе - да, аргумент. К сожалению, я не знаю, как работает классический read() и все мои доводы = догадки. Благо мы в ветке про новичков.

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
EOF - это просто код завершения getchar(), никакого прямого отношения к комбинации Ctrl+D не имеющий
тоже согласен. ctrl+D - функция терминала и здесь соглашусь.

еще раз все перечитал - получается вот так:
если я жму Enter - то программе передается строка + \n - т.е. код символа перевода строки
а когда жму ctrl+D - передается только строка
соответственно, когда я жму Enter в пустой строке - всеравно передается \n
а когда жму ctrl+D в пустой строке - передается - ничего. А это ничего и есть, по сути, EOF и поэтому цикл завершается.

так?
0
01.11.2016, 16:56
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.11.2016, 16:56

Подсчет среднего геометрического последовательности положительных чисел, вводимых с клавиатуры
Помогите пожалуйста) Написать программу для подсчета среднего геометрического...

Подсчет цифр, символов-разделителей и прочих символов в массиве
Здравствуйте. В учебнике дан код: #include &lt;stdio.h&gt; /* подсчет цифр,...

Подсчет цифр, символов-разделителей и прочих символов в строке
#include &lt;stdio.h&gt; #include &lt;locale.h&gt; /* подсчет цифр,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru