Перейти к содержимому

Как ввести неопределенное количество чисел с

  • автор:

Форматированный ввод данных в Си — функция scanf

В то время как функция printf() осуществляет форматированный вывод данных, функция scanf() осуществляет их форматированный ввод. Это значит, что поступающие на ввод данные преобразуются соответственно указанному формату(ам) и записываются по адресу(ам) указанной(ых) переменной(ых):

scanf(строка_формата, адреса_переменных);

Причина, по которой в scanf() передаются адреса, а не значения переменных, очевидна. Функция scanf() должна изменять значения переменных тех функций, из которых вызывается. Единственный способ — это получить адреса областей памяти.

Спецификации, допустимые в строке формата, для scanf() почти идентичны тем, что были описаны для функции printf() .

Ввод чисел, символов и строк

Пример ввода-вывода целого и вещественного чисел, символа и строки:

int a; float b; char ch, str[30]; scanf("%d%f%c%s", &a, &b, &ch, str); printf("%d %.3f %c %s\n", a, b, ch, str);
45 34.3456y hello 45 34.346 y hello

Здесь при выполнении программы все данные были введены в одну строку. Разделителем между числами и строками является пробел, а также любой другой символ пустого пространства (например, ‘\n’). Однако при считывании символа, пробел учитывается как символ; чтобы этого не произошло, в примере букву записали сразу после числа. Данные можно было бы ввести, разделяя их переходом на новую строку (опять же при этом надо иметь ввиду, как считывается символ).

В строке формата функции scanf() между спецификациями вполне допустимо поставить пробелы: %d %f %c %s . Они никакой роли не сыграют. Понятно, что данные можно было получить и так:

scanf("%d", &a); scanf("%f", &b); scanf("%c", &ch); scanf("%s", str);

Обратите внимание, перед переменной str отсутствует знак амперсанда. В последующих уроках вы узнаете, что имя массива уже само по себе является ссылкой на массив (другими словами, str содержит адрес начала массива).

В функции scanf() в спецификации формата вещественных чисел не указывается точность представления числа. Запись типа %.3f или %.10lf приведет к невозможности получить вещественное число. Чтобы получить число типа double используют формат %lf , для long double ‒ %Lf .

Для целых чисел: длинное целое ‒ %ld , короткое целое ‒ %hd . Существуют спецификации для ввода восьмеричных и шестнадцатеричных чисел.

Функция scanf() возвращает количество удачно считанных данных; т.е. значение, возвращаемое функцией, можно проанализировать и таким образом узнать, корректно ли были введены данные. Например:

int a; double b; char ch, str[30]; ch = scanf("%d %lf %s", &a, &b, str); if (ch == 3) printf("%d %.3lf %s\n", a, b, str); else printf("Error input\n");

Обычные символы в строке формата

В строке формата scanf() допустимо использование обычных символов. В этом случае при вводе данных также должны вводиться и эти символы:

int a, b, c; scanf("%d + %d = %d", &a, &b, &c); printf("Your answer is %d\n", c); printf("The correct is %d\n", a+b);

В данном случае, когда программа выполняется, ввод должен выглядеть примерно так: 342+1024 = 1366. Знаки «+» и » lang»>% , но перед буквой формата звездочку * . В таком случае данные считываются, но никакой переменной не присваиваются. Это можно использовать, например, когда нет определенной уверенности в том, что поступит на ввод, с одной стороны, и нужды сохранять эти данные, с другой:

float arr[3]; int i; for(i = 0; i  3; i++) scanf("%*s %f", &arr[i]); printf("Sum: %.2f\n", arr[0]+arr[1]+arr[2]);

Здесь предполагается, что перед каждым числом будет вводиться строка, которую следует проигнорировать, например:

First: 23.356 Second: 17.285 Third: 32.457 Sum: 73.098

Использование «шаблонов»

Для функции scanf() есть пара спецификаций формата, отдаленно напоминающих шаблоны командной оболочки и др. Формат […] позволяет получить строку, содержащую любые символы, указанные в квадратных скобках. Как только на ввод поступает символ, не входящий в указанный набор, считывание данных прекращается. Формат [^…] , наоборот, помещает в строку символы, не входящие в указанный набор, до тех пор пока не встретит любой из указанных.

В примере ниже как только поступает не цифра, считывание ввода завершается. При этом если первый символ — не цифра, то в str вообще ничего не записывается:

char str[30]=""; scanf("%[0-9]", str); printf("%s\n", str);

А в этом случае строке будет присвоена последовательность символов до любого из указанных знаков препинания:

scanf("%[^;. ]", str); printf("%s\n", str);
one two three four five! one two three four five

Обратите внимание, что в примере выше в строку были записаны как символы пробелов, так и символ перехода на новую строку. Таким образом, если надо прочитать одну строку вместе с пробелами, можно использовать такой подход:

scanf("%[^'\n']", str);

Здесь в строку считываются все символы, кроме перехода на новую строку. Как только встречается этот символ ‒ ‘\n’ , запись данных в переменную прекращается.

Некоторые особенности и ограничения функции scanf

Как только поступают некорректные данные, функция scanf() завершает свою работу. В примере:

scanf("%d%f", &a, &b);

если переменной a попытаться присвоить символ или строку, что невозможно, то в переменную b потом уже не получится записать число. Можно предположить, что так будет надежнее:

scanf("%d", &a); scanf("%f", &b);

Вроде бы неудачное считывание a не должно оказывать никакого влияния на b , т.к. это уже иной вызов scanf() . Но не все так просто: при некорректном вводе данные остаются в буфере и пытаются «навязать» себя последующим вызовам scanf() . Поэтому при использовании scanf() надо думать о том, как в случае некорректного ввода очистить буфер. Например, это можно сделать так, как показано ниже, или путем использования специальных функций (здесь не рассматриваются):

// если данные не удалось присвоить, if (scanf("%d", &a) != 1) // то выбросить их в виде строки scanf("%*s"); scanf("%f", &b);
  1. На прошлом занятии вы написали программу, содержащую функции, вычисляющие факториал числа и заданный элемент ряда Фибоначчи. Измените эту программу таким образом, чтобы она запрашивала у пользователя, что он хочет вычислить: факториал или число Фибоначчи. Затем программа запрашивала бы у пользователя либо число для вычисления факториала, либо номер элемента ряда Фибоначчи.
  2. Напишите программу, которая запрашивает у пользователя две даты в формате дд.мм.гггг. Дни, месяцы и года следует присвоить целочисленным переменным. Программа должна выводить на экран информацию о том, какая дата более ранняя, а какая более поздняя.
  3. Используя цикл, напишите код, в котором пользователю предлагается вводить данные до тех пор, пока он не сделает это корректно, т.е. пока все указанные в scanf() переменные не получат свои значения. Протестируйте программу.

Курс с решением задач:
pdf-версия

Как ввести неопределённое количество строк С++?

Здравствуйте. Сразу оговорюсь, я только начала изучать строки, я не знаю векторов и много еще чего. Нужно ввести неопределенное количество строк. Проблема в том, что я не знаю как это осуществить. Моих знаний явно не хватает для этого. Пожалуйста, помогите.

  • Вопрос задан более двух лет назад
  • 1451 просмотр

3 комментария

Простой 3 комментария

А что сделать-то надо?
Karapolo @Karapolo Автор вопроса
cicatrix, ввести данные и работать с ними.

Karapolo, как осуществляется приём входных данных? С консоли, из файла, из базы данных, с интернет-ресурса?
Написать надо что? Отдельную функцию или программу целиком?
Есть ли ограничения, чем можно пользоваться, чем нельзя?
Потому как в простом случае, приём строки с консоли осуществляется вот так:

#include std::string str; std::getline(std::cin, str);

Но у того, кто дал тебе это задание, могут быть иные идеи в отношении использования string, например.

Решения вопроса 2
Алексей Уколов @alexey-m-ukolov

Такое условие означает, что вам нужно со строкой работать посимвольно, а не писать её всю в память, потому что памяти может не хватить.

Ответ написан более двух лет назад
Karapolo @Karapolo Автор вопроса

А что мне делать с пробелами, если я буду вводить посимвольно? Как это осуществить? Я пробовала через scanf(«%c», s), но у меня это не получилось. Или через массив? Но даже если так, то нам не известно количество символов, также есть еще пробелы.

Алексей Уколов @alexey-m-ukolov
Что «это»? Что «делать»? Массив — это не посимвольно.

Therapyx

Data Science

смотря на сколько привередливый проф. Может быть реально как сказал Алексей, но
обычно в универе такие ключевые слова как «неопределенное» означает что-то динамическое. Т.е. Вектор.
Для самых отбитых можно сделать функцию буфера, т.е. если ветор имеет более «х» строк, то выкачать это в фаил (но не думаю, что это потребуется).
А алгоритм в принципе простой, надо только перевести в код

Инициализируй переменную статуса меню
Задекларируй Вектор, куда будут попадать все данные
Инициализируй переменные для статистики (если их много, желательно сделай отдельный класс, а на этом месте будет обьект этого класса).

напиши while loop и используй сканнер, который добавляет строки в вектор до тех пор, пока к примеру пользователь не нажмет 0, где 0 будет считаться выходом из программы, т.е. break

тут выбор, или ты сразу после добавления строки делаешь статистику, или после того как пользовательно нажмет кнопку «0» и тогда для всего вектора.
Если же второе, то делаешь опять for loop на вектор и на каждую строку пишешь нужную обработку статистики.

Вывод данных: тут уж проблем с статистикой из класса быть не должно.

Проблему я вижу в другом, «я только начала изучать строки, я не знаю векторов и много еще чего»
Как ты это писать то собираешься? Готовься к малому сну )) А выучить это надо, я думаю с такими заданиями дальше у вас будет по нарастающей. Пропустишь это — потом опустишь вообще руки.
Конкретно с некоторыми позициями тут помогут спокойно. Писать же все. Для этого есть фриланс.

Как прочитать неопределенное количество строк с клавиатуры?

Мне необходимо ввести с клавиатуры определенной число строк, содержащих float числа. В первой строке вводится число — количество строк, в каждой последующей строке вводится два float числа. Мой вариант для 3 строк выглядит так:

N = int(input()) a1 = list(map(float, input().split())) a2 = list(map(float, input().split())) a3 = list(map(float, input().split())) b1 = a1[0], a2[0], a3[0] b2 = a1[1], a2[1], a3[1] 

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

Отслеживать
Timur Shleminov
задан 19 апр 2019 в 11:11
Timur Shleminov Timur Shleminov
47 4 4 бронзовых знака

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Используйте цикл, и сохраняйте данный в список списков:

n = int(input()) b = [] for i in range(n): a = list(map(float, input().split())) b.append(a) print(b) 

Отслеживать
ответ дан 19 апр 2019 в 12:21
20.4k 4 4 золотых знака 25 25 серебряных знаков 52 52 бронзовых знака

    Важное на Мете
Похожие

Подписаться на ленту

Лента вопроса

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.3.2953

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

1.4.3. Ввод неизвестного количества данных

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

int sum = 0, value = 0;

// читать данные до конца файла, вычислить сумму всех значений

while (std::cin >> value)

sum += value; // эквивалентно sum = sum + val

Если ввести значения 3 4 5 6, то будет получен результат Sum is: 18.

Первая строка функции main() определяет две переменные типа int по имени sum и value, инициализируемые значением 0. Переменная value применяется для хранения чисел, вводимых в условии цикла while.

while (std::cin >> value)

Условием продолжения цикла while является выражение

Это выражение читает следующее число со стандартного устройства ввода и сохраняет его в переменной value. Как упоминалось в разделе 1.2, оператор ввода возвращает свой левый операнд. Таким образом, в условии фактически проверяется объект std::cin.

Когда объект типа istream используется при проверке условия, результат зависит от состояния потока. Если поток допустим, т.е. не столкнулся с ошибкой и ввод следующего значения еще возможен, это условие считается истинным. Объект типа istream переходит в недопустимое состояние по достижении конца файла (end-of-file) или при вводе недопустимых данных, например строки вместо числа. Недопустимое состояние объекта типа istream в условии свидетельствует о том, что оно ложно.

Таким образом, пока не достигнут конец файла (или не произошла ошибка ввода), условие остается истинным и выполняется тело цикла while. Тело состоит из одного составного оператора присвоения, который добавляет значение переменной value к текущему значению переменной sum. Однажды нарушение условия завершает цикл while. По выходе из цикла выполняется следующий оператор, который выводит значение переменной sum, сопровождаемое манипулятором endl.

Ввод конца файла с клавиатуры

Разные операционные системы используют для конца файла различные значения. Для ввода символа конца файла в операционной системе Windows достаточно нажать комбинацию клавиш (удерживая нажатой клавишу , нажать клавишу ), а затем клавишу или . На машине с операционной системой UNIX, включая Mac OS-X, как правило, используется комбинация клавиш .

Возвращаясь к компиляции

Одной из задач компилятора является поиск ошибок в тексте программ. Компилятор, безусловно, не может выяснить, делает ли программа то, что предполагал ее автор, но вполне способен обнаружить ошибки в форме записи. Ниже приведены примеры ошибок, которые компилятор обнаруживает чаще всего.

Синтаксические ошибки. Речь идет о грамматических ошибках языка С++. Приведенный ниже код демонстрирует наиболее распространенные синтаксические ошибки, снабженные комментариями, которые описывают их суть.

// ошибка: отсутствует ‘)’ список параметров функции main()

// ошибка: после endl используется двоеточие, а не точка с запятой

// ошибка: отсутствуют кавычки вокруг строкового литерала

// ошибка: отсутствует второй оператор вывода

// ошибка: отсутствует ‘;’ после оператора return

Ошибки несовпадения типа. Каждый элемент данных языка С++ имеет тип. Значение 10, например, является числом типа int. Слово «привет» с парными кавычками — это строковый литерал. Примером ошибки несовпадения является передача строкового литерала функции, которая ожидает целочисленным аргумент.

Ошибки объявления. Каждое имя, используемое в программе на языке С++, должно быть вначале объявлено. Использование необъявленного имени обычно приводит к сообщению об ошибке. Типичными ошибками объявления является также отсутствие указания пространства имен, например std. при доступе к имени, определенному в библиотеке, а также орфографические ошибки в именах идентификаторов.

int v1 = 0, v2 = 0;

std::cin >> v >> v2; // ошибка: используется «v» вместо «v1»

// cout не определен, должно быть std::cout

Сообщение об ошибке содержит обычно номер строки и краткое описание того, что компилятор считает неправильным. Исправлять ошибки имеет смысл в том порядке, в котором поступают сообщения о них. Зачастую одна ошибка приводит к появлению других, поэтому компилятор, как правило, сообщает о большем количестве ошибок, чем имеется фактически. Целесообразно также перекомпилировать код после устранения каждой ошибки или небольшого количества вполне очевидных ошибок. Этот цикл известен под названием «редактирование, компиляция, отладка» (edit-compile-debug).

Упражнения раздела 1.4.3

Упражнение 1.16. Напишите собственную версию программы, которая выводит сумму набора целых чисел, прочитанных при помощи объекта cin.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *