Как записать слово в переменную в c

от admin

Как записать слово в переменную в c

Функция sscanf считывает данные из строки (массива символов) в переменные. Функция имеет следующий синтаксис

Первый параметр функции представляет строку, из которой считываются данные. Второй параметр представляет формат считывания. В качестве последующих параметров указываются переменные, в которые идет считывание.

Считаем данные из строки

В данном случае строка, из которой считываются данные:

Разделителем между значениями является пробел, либо последовательность пробелов, табуляция и перевод строки.

Эту строку передаем в функцию sscanf первым аргументом и считываем ее значения в переменные c , n , d :

А второй аргумент — формат считывания определяет, как данные из строки будут сопоставляться с переменными:

Поскольку значения в строке buff разделены пробелами, то и в строки форматирования спецификаторы разделены пробелами. Первый спецификатор %c позволяет считать первый символ в переменную типа char c .

Второй спецификатор — %d обеспечивает считывание целого числа в переменную n .

И третий спецификатор %lf считывает данные в переменную типа double — d

То есть в итоге консольный вывод был бы следующим:

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

Еще один пример. Пусть в строке содержатся данные пользователя, как имя, возраст, зарплата. Считаем эти данные в переменные:

Причем строка форматирования может быть более сложной. Например:

В данном случае исходная строка представляет текст «Name is Tom and age is 38» . И на эту строку накладывается строка форматирования «Name is %s and age is %d» . Соответственно здесь спецификатор %s будет представлять строку «Tom», а спецификатор %d — число 38.

Считывание с консоли

Комбинируя это функцию с fgets() , можно считывать данные с консоли:

Пример консольного ввода:

Данный способ имеет премущества по сравнению с чтением через scanf , поскольку при считывании функция scanf удаляет из входного буфера только значения, которые соответствуют спецификаторам. Поэтому, если ввод через scanf не соответствует чему-либо, оставшиеся в буфере символы будут считываться при следующем вызове scanf.

sprintf

Функция sprintf производит обратное действие — записывает данные в строку:

В качестве первого параметра функция принимает указатель на буфер, в который идет запись. Второй параметр представляет строку форматирования. Кроме того, в качестве дополнеительных аргументов в функцию можно передавать дополнительные значения для спецификаторов из строки форматирования. Результатом функции является длина количество записанный символов плюс нулевой символ.

В данном случае в переменную text записывается строка «Name: %s Age: %d\n» , в которую вместо спецификаторов подставляются значения переменных name и age .

4.12 – Знакомство с std::string

Самая первая написанная вами программа на C++, вероятно, выглядела примерно так:

Так что точно такое " Hello, world! "? " Hello, world! " представляет собой набор последовательных символов, называемый строкой. В C++ мы используем строки для представления текста, такого как имена, адреса, слова и предложения. Строковые литералы (например, " Hello, world!\n ") помещаются в двойные кавычки, чтобы идентифицировать их как строки.

Поскольку в программах строки обычно используются, большинство современных языков программирования включают в себя базовый строковый тип данных. В C++ строки не являются базовым типом (на самом деле они являются составным типом и определены в стандартной библиотеке C++, а не как часть ядра языка). Но строки достаточно просты и полезны, поэтому мы представим их здесь, а не будем дожидаться главы о составных типах (глава 8).

std::string

Чтобы использовать строки в C++, нам сначала нужно включить через #include заголовочный файл <string> , чтобы ввести объявления для std::string . Как только это будет сделано, мы сможем определить переменные типа std::string .

Вы можете инициализировать или присваивать значения строкам, как и обычным переменным, что и следовало ожидать:

Обратите внимание, что строки также могут содержать числа:

В строковой форме числа обрабатываются как текст, а не как числа, и поэтому ими нельзя манипулировать как числами (например, вы не можете их умножать). C++ не будет автоматически преобразовывать строковые числа в целочисленные значения или значения с плавающей запятой.

Вывод строк

Строки можно выводить, как и ожидалось, с помощью std::cout :

Эта программа печатает:

Пустые строки ничего не напечатают:

Эта программа напечатает:

Ввод строк с помощью std::cin

Использование строк с std::cin может преподнести сюрпризы! Рассмотрим следующий пример:

Ниже показаны результаты пробного запуска этой программы:

Хммм, это неправильно! Что случилось? Оказывается, что при использовании operator>> для извлечения из cin строки operator>> возвращает только символы до первого попавшегося пробела. Все остальные символы остаются внутри std::cin в ожидании следующего извлечения.

Поэтому, когда мы использовали operator>> для извлечения строки в переменную name , было извлечено только " John ", оставив " Doe " внутри std::cin . Когда мы снова использовали operator>> для получения переменной age , он извлек " Doe " вместо того, чтобы ждать, пока мы введем возраст. На этом программа заканчивается.

Для ввода текста используйте std::getline()

Чтобы прочитать всю строку входных данных в переменную строки, лучше вместо этого использовать функцию std::getline() . std::getline() принимает два параметра: первый – это std::cin , а второй – ваша строковая переменная.

Вот та же программа, что и выше, с использованием std::getline() :

Теперь наша программа работает как и ожидалось:

Что еще за std::ws ?

В уроке «4.8 – Числовые типы с плавающей точкой» мы обсудили манипуляторы вывода, которые позволяют нам изменять способ отображения выводимых значений. В том уроке мы использовали функцию манипулятора вывода std::setprecision() , чтобы изменить количество значащих цифр, отображаемых std::cout .

C++ также поддерживает манипуляторы ввода (определенные в заголовке iomanip ), которые изменяют способ приема входных данных. Манипулятор ввода std::ws говорит std::cin игнорировать любые начальные пробелы. Обратите внимание, что std::ws не является функцией.

Давайте разберемся, чем он полезен. Рассмотрим следующую программу:

Вот пример результата работы этой программы:

Данная программа сначала просит вас ввести 1 или 2 и ждет, когда вы это сделаете. Пока всё хорошо. Затем она просит вас ввести свое имя. Однако на самом деле она не будет ждать, пока вы введете свое имя! Вместо этого она печатает строку " Hello ", а затем завершит работу. Что случилось?

Оказывается, когда вы вводите значение с помощью operator>> , std::cin не только захватывает значение, но также захватывает символ новой строки (' \n '), который появляется, когда вы нажимаете клавишу Enter . Итак, когда мы набираем 2 и нажимаем Enter , std::cin получает строку " 2\n ". Затем он извлекает 2 в переменную choice , оставляя символ новой строки на потом. Затем, когда std::getline() переходит к чтению имени, он видит, что " \n " уже находится в потоке, и полагает, что мы, должно быть, ввели пустую строку! Это определенно не то, что было задумано.

Мы можем изменить приведенную выше программу, чтобы использовать манипулятор ввода std::ws , чтобы указать std::getline() игнорировать любые начальные пробельные символы:

Теперь эта программа будет работать так, как задумано.

Лучшая практика

Если для чтения строк используется функция std::getline , используйте манипулятор ввода std::ws , чтобы игнорировать начальные пробелы.

Ключевые выводы

Использование оператора извлечения ( >> ) с std::cin игнорирует начальные пробелы.

std::getline не игнорирует начальные пробелы, если вы не используете манипулятор ввода std::ws .

Длина строки

Если мы хотим знать, сколько символов находится в std::string , мы можем спросить переменную std::string о ее длине. Синтаксис для этого отличается от того, что вы видели раньше, но он довольно прост:

Обратите внимание, что вместо того, чтобы запрашивать длину строки как length(myName) , мы говорим myName.length() . Функция length() не является обычной автономной функцией – это особый тип функции, которая принадлежит std::string и называется функцией-членом. Позже мы расскажем о функциях-членах, в том числе о том, как написать свои собственные.

Заключение

std::string сложен и использует многие языковые функции, которые мы еще не рассмотрели. К счастью, вам не нужно разбираться в этих сложностях, чтобы использовать std::string для простых задач, таких как простейший ввод и вывод строк. Мы рекомендуем вам начать экспериментировать со строками прямо сейчас, а дополнительные возможности строк мы рассмотрим позже.

Небольшой тест

Вопрос 1

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

Ввод и вывод символьных строк в Си

Итак, строки в языке Си. Для них не предусмотрено отдельного типа данных, как это сделано во многих других языках программирования. В языке Си строка – это массив символов. Чтобы обозначить конец строки, используется символ '\0' , о котором мы говорили в прошлой части этого урока. На экране он никак не отображается, поэтому посмотреть на него не получится.

Создание и инициализация строки

Так как строка – это массив символов, то объявление и инициализация строки аналогичны подобным операциям с одномерными массивами.

Читать:
Media scrub vdisk что это

Следующий код иллюстрирует различные способы инициализации строк.

Рис.1 Объявление и инициализация строк

В первой строке мы просто объявляем массив из десяти символов. Это даже не совсем строка, т.к. в ней отсутствует нуль-символ \0 , пока это просто набор символов.

Вторая строка. Простейший способ инициализации в лоб. Объявляем каждый символ по отдельности. Тут главное не забыть добавить нуль-символ \0 .

Третья строка – аналог второй строки. Обратите внимание на картинку. Т.к. символов в строке справа меньше, чем элементов в массиве, остальные элементы заполнятся \0 .

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

Как вывести строку

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

Различные способы вывода строки на экран

Рис.2 Различные способы вывода строки на экран

Как видите, есть несколько основных способов вывести строку на экран.

  • использовать функцию printf со спецификатором %s
  • использовать функцию puts
  • использовать функцию fputs , указав в качестве второго параметра стандартный поток для вывода stdout .

Единственный нюанс у функций puts и fputs . Обратите внимание, что функция puts переносит вывод на следующую строку, а функция fputs не переносит.

Как видите, с выводом всё достаточно просто.

Ввод строк

С вводом строк всё немного сложнее, чем с выводом. Простейшим способом будет являться следующее:

Функция gets приостанавливает работу программы, читает строку символов, введенных с клавиатуры, и помещает в символьный массив, имя которого передаётся функции в качестве параметра.
Завершением работы функции gets будет являться символ, соответствующий клавише ввод и записываемый в строку как нулевой символ.
Заметили опасность? Если нет, то о ней вас любезно предупредит компилятор. Дело в том, что функция gets завершает работу только тогда, когда пользователь нажимает клавишу ввод. Это чревато тем, что мы можем выйти за рамки массива, в нашем случае — если введено более 20 символов.
К слову, ранее ошибки переполнения буфера считались самым распространенным типом уязвимости. Они встречаются и сейчас, но использовать их для взлома программ стало гораздо сложнее.

Итак, что мы имеем. У нас есть задача: записать строку в массив ограниченного размера. То есть, мы должны как-то контролировать количество символов, вводимых пользователем. И тут нам на помощь приходит функция fgets :

Функция fgets принимает на вход три аргумента: переменную для записи строки, размер записываемой строки и имя потока, откуда взять данные для записи в строку, в данном случае — stdin . Как вы уже знаете из 3 урока, stdin – это стандартный поток ввода данных, обычно связанный с клавиатурой. Совсем необязательно данные должны поступать именно из потока stdin , в дальнейшем эту функцию мы также будем использовать для чтения данных из файлов.

Если в ходе выполнения этой программы мы введем строку длиннее, чем 10 символов, в массив все равно будут записаны только 9 символов с начала и символ переноса строки, fgets «обрежет» строку под необходимую длину.

Обратите внимание, функция fgets считывает не 10 символов, а 9 ! Как мы помним, в строках последний символ зарезервирован для нуль-символа.

Давайте это проверим. Запустим программу из последнего листинга. И введём строку 1234567890 . На экран выведется строка 123456789 .

Пример работы функции fgets

Рис.3 Пример работы функции fgets

Возникает вопрос. А куда делся десятый символ? А я отвечу. Он никуда не делся, он остался в потоке ввода. Выполните следующую программу.

Вот результат её работы.

Непустой буфер stdin

Рис.4 Непустой буфер stdin

Поясню произошедшее. Мы вызвали функцию fgets . Она открыла поток ввода и дождалась пока мы введём данные. Мы ввели с клавиатуры 1234567890\n ( \n я обозначаю нажатие клавиша Enter ). Это отправилось в поток ввода stdin . Функция fgets , как и полагается, взяла из потока ввода первые 9 символов 123456789 , добавила к ним нуль-символ \0 и записала это в строку str . В потоке ввода осталось ещё 0\n .

Далее мы объявляем переменную h . Выводим её значение на экран. После чего вызываем функцию scanf . Тут-то ожидается, что мы можем что-то ввести, но т.к. в потоке ввода висит 0\n , то функция scanf воспринимает это как наш ввод, и записывается 0 в переменную h . Далее мы выводим её на экран.

Это, конечно, не совсем такое поведение, которое мы ожидаем. Чтобы справиться с этой проблемой, необходимо очистить буфер ввода после того, как мы считали из него строку, введённую пользователем. Для этого используется специальная функция fflush . У неё всего один параметр – поток, который нужно очистить.

Исправим последний пример так, чтобы его работа была предсказуемой.

Теперь программа будет работать так, как надо.

Сброс буфера stdin функцией fflush

Рис.4 Сброс буфера stdin функцией fflush

Подводя итог, можно отметить два факта. Первый. На данный момент использование функции gets является небезопасным, поэтому рекомендуется везде использовать функцию fgets .

Второй. Не забывайте очищать буфер ввода, если используете функцию fgets .

На этом разговор о вводе строк закончен. Идём дальше.

Сохрани в закладки или поддержи проект.

Практика

Решите предложенные задачи:

Для удобства работы сразу переходите в полноэкранный режим

Язык С: переменные

Переменная — это не что иное, как именованная область памяти, которой могут манипулировать программы. Каждая переменная в языке C характеризуется:

  • типом, определяющим размер и расположение памяти переменной;
  • диапазоном значений, которые могут храниться в этой памяти;
  • набором операций, которые можно применить к переменной.

Имя переменной может состоять из букв, цифр и символа подчеркивания. Оно должно начинаться либо с буквы, либо с символа подчеркивания. Строчные и заглавные буквы различаются, поскольку C чувствителен к регистру. Выделим основные типы переменных:

  • char — целочисленный тип, представляющий обычно один октет (один восьмибитовый байт);
  • int — наиболее естественный размер целого числа для компьютера;
  • float — значение с плавающей запятой одинарной точности;
  • double — значение с плавающей запятой двойной точности;
  • void — представляет отсутствие типа.

Язык C также позволяет определять другие типы переменных (перечисление, указатель, массив, структура, объединение и т.д.), которые будут рассмотрены в последующих разделах. Здесь уделим внимание только основным типам переменных.

Определение переменных

Определение переменной указывает компилятору, где и какой объем памяти нужно создать для этой переменной. Определение переменных задает тип данных и содержит список одной или нескольких переменных этого типа следующим образом:

Здесь type должен быть допустимым типом данных языка C, включая char , w_char , int , float , double , bool или любой объект, определяемый пользователем; а variable_list может состоять из одного или нескольких имен идентификаторов, разделенных запятыми. Ниже показаны некоторые допустимые объявления:

Строка int i, j, k; объявляет и определяет переменные i , j и k ; которые инструктируют компилятор создать переменные с именами i , j и k типа int .

Переменные могут быть инициализированы (им присваивается начальное значение) в их объявлении. Блок инициализации состоит из знака равенства, за которым следует константное выражение, как показано ниже:

Определение без инициализации: переменные со статической длительностью хранения неявно инициализируются со значением NULL (все байты имеют значение 0 ); начальное значение всех остальных переменных не определено.

Объявление переменных

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

Объявление переменной полезно при использовании нескольких файлов и определении переменной в одном из файлов, который будет доступен во время сборки программы. Можно использовать ключевое слово extern для объявления переменной в любом месте. Хотя в своей программе вы можете объявлять переменную несколько раз, она должна быть определена только один раз в файле, функции или блоке кода.

Пример

Рассмотрим пример, где переменные были объявлены в самом верху, но определены и инициализированы внутри главной функции.

Когда приведенный выше код компилируется и выполняется, выдается следующий результат:

Тот же принцип применим к объявлению функции, когда вы указываете имя функции во время ее объявления, а ее фактическое определение может быть дано в любом другом месте. Например:

L-значения и R-значения

В языке C есть два вида выражений:

  1. L-значения. Выражения, которые ссылаются на область памяти, называются выражениями l-значения. L-значение может появляться как в левой, так и в правой части присваивания.
  2. R-значения. Термин r-значение относится к значению данных, которое хранится по некоторому адресу в памяти. R-значение — это выражение, которому не может быть присвоено значение, что означает, что r-значение может появляться только в правой части присваивания.

Переменные — это l-значения, поэтому они могут появляться в левой части присваивания. Числовые литералы являются r-значениями, поэтому их нельзя присвоить и они не могут появляться в левой части. Посмотрите на следующие допустимые и недопустимые операторы:

Похожие статьи