Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лаб_раб_08.doc
Скачиваний:
9
Добавлен:
23.09.2019
Размер:
334.85 Кб
Скачать

1.2. Строковые данные и их представление в памяти эвм

В языке C среди базовых типов данных строк как таковых не оказалось. Вместо этого язык C предлагает использовать одномерные символьные массивы, в которых хранятся те же строки в виде последовательности однобайтовых символов, завершающихся байтом с нулевым кодом. Для этого признака конца строки в состав Escape-последовательностей включен специальный код '\0', хотя можно было бы воспользоваться и другой комбинацией – '\0x0'.

В языке C++ появился гораздо более удобный класс строковых данных string.

Значения строковых констант или начальные значения строковых "переменных" в отличие от символьных данных заключаются в двойные кавычки:

const char c1[]="ABCDEFGH";

char str1[]="1234";

char letter[]="a";

char symbol='a';

Байт с нулевым кодом система автоматически добавляет вслед за последним символом строки. Поэтому для символьного массива c1 будет выделено 9 байтов, а для символьного массива str1 – 5 байтов. Обратите внимание на то, что массив letter занимает в памяти 2 байта, тогда как символьная переменная symbol – 1 байт. Так как строка представлена одномерным массивом символов, то доступ к каждому ее символу осуществляется самым обычным способом:

c1[3] – четвертый символ в массиве c1 (т.е. буква 'D')

str1[0] – первый символ в массиве str1 (т.е. цифра '1')

Значение любого символа в строковой "переменной" можно изменить во время работы программы:

str1[3]='L';

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

str1[4]=5; //Байт с признаком конца строки испорчен

str1[5]=6; //Испорчен байт с какими-то данными

1.3. Ввод текстовых данных во время работы программы

1.3.1. Форматный ввод

Список форматных указателей функции scanf предусматривает возможность ввода значений односимвольных (%c) и многосимвольных (%s) переменных:

#include <stdio.h>

void main()

{ char ch1,ch2;

char str1[10];

scanf("%c %c",&ch1,&ch2);

scanf("%s",str1);

....................

Обратите внимание на то, что для ввода данных в скалярные переменные ch1 и ch2 в списке ввода необходимо указывать их адреса (&ch1, &ch2), а при вводе в массив str1 – достаточно написать его имя. Дело в том, что имя массива одновременно выполняет роль адреса своего первого элемента. Поэтому str1 и &str1[0] указывают на один и тот же адрес.

Ввод значений символьных переменных ch1 и ch2 можно организовать одним из двух способов. Во-первых, в строке ввода можно набрать два требуемых символа либо слитно, либо разделяя их хотя бы одним пробелом и нажать клавишу Enter. Во-вторых, можно набрать первый символ, предназначенный для переменной ch1, и нажать клавишу Enter. Затем повторить аналогичным образом ввод следующего символа.

Значение, предназначенное для строковой "переменной" str1, не должно содержать более 9 символов (признак конца строки система добавляет автоматически) и среди них не должен присутствовать пробел. Дело в том, что пробел при форматном вводе воспринимается как разделитель данных. Это не означает, что среди символов строки пробел вообще не допустим, просто для организации ввода в строку нескольких слов надо использовать другие средства.

Довольно неожиданно, но с помощью задания ширины поля ввода и одного форматного указателя %с можно за один прием ввести несколько символов в элементы символьного массива:

char q[20];

............

scanf("%20c",q); //ввод 20 символов в массив q

В отличие от ввода по форматному указателю %s в массив q здесь не записывается признак конца строки – вводятся только запрашиваемые символы, которые набираются в одной строке с последующим нажатием клавиши Enter.

Функция scanf предусматривает еще два интересных форматных указателя, которые обеспечивают ввод либо тех символов, которые указаны в заданном множестве, либо всех символов, которые не принадлежат заданному множеству. Например, для ввода цифр из диапазона от 0 до 9 такой указатель имеет вид %[0-9], а для ввода символов, не являющихся цифрами – %[^0-9]. Рассмотрим следующий пример, который не только демонстрирует ввод по таким форматным указателям, но и содержит непредвиденный пассаж, связанный с использованием "грязного" буфера ввода.

#include <stdio.h>

#include <conio.h>

void main()

{ char str[10];

int j;

printf("Enter 123ABC\n");

scanf("%[0-9]",str);

printf("str=%s\n",str);

for(j=0; j<10; j++)

printf("%3x",str[j]);

printf("\nEnter DEF123\n");

scanf("%[^0-9]",str);

printf("str=%s\n",str);

for(j=0; j<10; j++)

printf("%3x",str[j]);

getch();

}

//=== Результат работы ===

Enter 123ABC

str=123

31 32 33 0 0 1 0 0 1 0

Enter DEF123

str=ABC

DEF

41 42 43 a 44 45 46 0 1 0

После ввода первой строки программе были переданы символы '123', вслед за которыми в массив str был записан нулевой байт – признак конца строки. Однако в буфере ввода остались невостребованными символы 'ABC' и код клавиши Enter (код 0xa). После набора второй строки к содержимому буфера ввода добавились еще три символа 'DEF' и т.к. все семь первых символов не являются кодами цифр, то все они были переданы в массив str. При выводе первые три отобразились в одной строке, затем сработал управляющий код 0xa и три следующие символа были выведены в следующей строке. Для наглядности содержимое массива после каждого вывода по формату %s отображалось еще и в шестнадцатеричном формате. Значения байтов, начиная с str[4], объясняются тем, что массив str является локальным, и под него выделяется "грязная память". Если его описание вынести за пределы main, то он станет глобальным и будет расписан нулями.

Чтобы не пострадать от непредвиденного ввода символов, задержавшихся в буфере ввода, рекомендуется после обращения к функции scanf чистить буфер ввода с помощью функции fflush(stdin). Если бы мы включили в предыдущий пример обращение к функции fflush, то после ввода второй строки в массиве str оказались бы только символы 'DEF'.