0

Ввод символов в массив

Пожалуйста, приостановите работу AdBlock на этом сайте.

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

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

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

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

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

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

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

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

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

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

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

Рис.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 .

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

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

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

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

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

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

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

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

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

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

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

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

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

Практика

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

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

Исследовательские задачи для хакеров

  1. Проверьте как ведет себя ваш компилятор в случае переполнения буфера.

Предположим, я объявляю массив

и я должен ввести имя «Андрей»(менее 20 символов) в переменной вручную, как это возможно?

** Редактировать: я попробовал этот код, и он дает мне эту ошибку

ошибка: несовместимые типы при назначении const char [10] для char [30]

Решение

Есть несколько способов сделать это, так как с массивом вы можете получить доступ к отдельным элементам массива через [x] (где x это элемент, к которому вы хотите получить доступ).

В этих примерах я предполагаю, что «Andrew» является строкой C (то есть она заканчивается нулевым символом).

Первый способ (самый утомительный) — установить каждый элемент массива индивидуально:

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

Но есть и более простой способ! Если вы используете двойные кавычки ( ". " ), это будет в основном приравнять код выше (с фантазией <. >обозначения):

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

Читайте также:  Две блютуз гарнитуры к одному телефону

В этом случае мы можем либо использовать первый метод (очень утомительно !!), либо мы можем использовать аккуратную функцию, включенную в , называется strcpy :

strcpy работает путем копирования источника ( "Andrew" ) к месту назначения ( name ), пока он не встретит символ NULL (и также скопирует символ NULL). Эта функция также полезна, когда у вас нет постоянного значения. Например, вы можете сделать это:

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

Обратите внимание, что если источник ( "Andrew" ) длиннее 20, символ NULL добавляться не будет. Так что, если вы хотите сохранить строку C, попробуйте это:

РЕДАКТИРОВАТЬ: о том, почему это невозможно сделать char name[20]; name = "Andrew"; Я не знаю ни одной технической причины, которая делает это невозможным. Я предполагаю, что это всего лишь ограничение в синтаксисе Си.

Я решил посмотреть, что происходит в сборке, поэтому из этого исходного кода:

Результат сборки был:

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

Не делайте этого, если вы не хотите серьезно раздражать своих коллег: P Я уверен, что большинство современных компиляторов должны оптимизировать strcpy функционировать, если это константа (т.е. "Andrew" вместо переменной или функции, как getenv("HOME") ).

Другие решения

Вы указываете язык c ++ и массив char и просите ввести значение вручную. Ответ:

Если вы хотите прочитать значение из консоли, используйте это:

Но лучше использовать библиотеку c ++:

Или без синтаксического сахара:

Вы также можете использовать
strcpy(name, "Some Name")

Развернув первый ответ, попробуйте этот код, и он покажет, как это назначение работает с массивом.

Символы в «Эндрю» присваиваются имени, а остальные элементы массива фиксированного размера пусты.

Пример работы с одномерным массивом

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

С использованием одномерных массивов и строк

Программирование циклических вычислительных процессов

Массив – конечномерная последовательность данных одного типа. Массив – объект сложного типа. Каждый элемент массива определяется именем массива и индексом (целое число), по которому к элементу массива производится доступ. Рассмотрим одномерные массивы. Индексы у массивов в языке С/C++ начинаются с 0. В программе одномерный массив объявляется следующим образом:

где, размер – количество элементов одномерного массива.

Размер массива может задаваться константой или константным выражением. Нельзя задавать массив переменного размера, для этого существует отдельный механизм – динамическое выделение памяти.

Пример объявления массива целого типа:

в массиве а первый элемент а[0], второй – а[1], …, пятый – а[4]. В языке С/C++ не проверяется выход индекса за пределы массива. Корректность использования индексов элементов массива должен контролировать программист.

В массиве а целого типа найти индекс и значение максимального элемента и переставить его с первым элементом. Программа также должна подсчитать количество положительных и отрицательных элементов данного мaссива.

Читайте также:  Инст мобильная версия вход

Текст программы может быть следующим:

< int a[4]=<-1,-20,4,100>; // объявление массива с инициализацией

// индексы принимают значения от 0 до 3

puts("
ИСХОДНЫЙ МАССИВ
");

Например, описание: char a[7], означает, что строка содержит шесть символов, а последний байт отведен под нуль-терминатор.

Строковая константа в языке С/C++ – это набор символов, заключенных в двойные кавычки. Например: “Лабораторная работа по строкам”. В конце строковой константы явно указывать символ ´ ´ не нужно, так как это сделает компилятор языка С/C++.

Строки можно инициализиорвать при декларировании, например:

char S1[10]=”123456789”, S2[]=”12345”;

в последнем случае размер строки будет установлен по фактическому количеству символов.

Для ввода строки с клавиатуры дисплея используются две стандартные библи­отечные функции, прототипы которых приведены в файле stdio.h.

Функция scanf( ) вводит значения для строковых переменных спецификатором ввода %s. Но надо помнить, что функция scanf( ) вводит символы до появления первого символа “пробел”.

Библиотечная функция gets( ), обеспечивает ввод строки с пробелами внутри этой строки. При этом ввод строки символов завершается нажатием клавиши ENTER.

Обе функции автоматически ставят в конец строки нулевой байт. И, кроме того, так как строка – это символьный массив, а имя массива – это указатель на его начало в памяти, то символ «&» перед именами строковых объектов при использовании этих функций указывать не надо.

Вывод строк производится функциями printf( ) или puts( ). Обе функции выводят символьный массив до первого нулевого байта. Функция printf( ) не переводит курсор после вывода на начало новой строки, программист должен предусмотреть такой перевод в строке формата. Функия puts( ) автоматически переводит курсор после вывода строковой информации в начало новой строки.

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

1. Функция strcpy(S1, S2) – копирует содержимое строки S2 в строку S1.

2. Функция strcat(S1, S2) – присоединяет строку S2 к строке S1 и помещает ее в массив, где находилась строка S1, при этом строка S2 не изменяется. Нулевой байт, который завершал строку S1, заменяется первым символом строки S2.

3. Функция strcmp(S1, S2) сравнивает строки S1 и S2 и возвращает значение =0, если строки равны, т.е. содержит одно и то же число одинаковых символов; значение 0, если S1>S2.

4. Функция strlen(S) возвращает длину строки, т.е. количество символов, начиная с нулевого и до нуль-терминатора, нулевой байт не учитывается.

5. Функции преобразования строки S в число:

целое: int atoi(S); длинное целое: long atol(S); действительное: double atof(S); при ошибке возвращает значение 0.

6. Функции преобразования числа V в строку S:

целое: itoa(int V,char S,int kod); длинное целое: ltoa(long V,char S,int kod); 2

Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: Студент – человек, постоянно откладывающий неизбежность. 10571 – | 7330 – или читать все.

78.85.5.224 © studopedia.ru Не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования. Есть нарушение авторского права? Напишите нам | Обратная связь.

Отключите adBlock!
и обновите страницу (F5)

очень нужно

admin

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

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