МУ_ЛР4_ОП (Методические указания к лабораторным работам), страница 2
Описание файла
Файл "МУ_ЛР4_ОП" внутри архива находится в папке "Методические указания к лабораторным работам". Документ из архива "Методические указания к лабораторным работам", который расположен в категории "". Всё это находится в предмете "программирование на основе классов и шаблонов" из 2 семестр, которые можно найти в файловом архиве МГТУ им. Н.Э.Баумана. Не смотря на прямую связь этого архива с МГТУ им. Н.Э.Баумана, его также можно найти и в других разделах. Архив можно найти в разделе "книги и методические указания", в предмете "программирование на основе классов и шаблонов" в общих файлах.
Онлайн просмотр документа "МУ_ЛР4_ОП"
Текст 2 страницы из документа "МУ_ЛР4_ОП"
Строка (scanf) -> '12345'
При другом вводе (с пробелом!) результат будет другим, так как пробел ограничивает размер вводимой строки:
12345 678909
Строка (scanf) -> '12345'
Строка (scanf) -> '67890'
Для ввода с пробелами и другими особенностями для строк используют функции gets и puts и другие. Вам предлагается здесь познакомиться с этими функциями самостоятельно. Мы рассмотрим данные функции позже.
8 Манипуляция со строками и в строке
Для сравнения строк в СИ используются библиотечные функции: strcmp, strncmp, _strnicmp и другие. Пример и рузельтаты приведены ниже.
// strcmp , strncmp - сравнение строк
char Name[14] = " Василий"; // Посмотреть в отладчике нуль-терм.
setlocale( LC_ALL, "" ); // нужно подключить locale.h
//
if ( strcmp(Name , "Василий") == 0) printf ("Строки равны (идентичны)! \n" );
if ( strcmp(Name , "Алексей") > 0) printf ("Строки не равны (1-я > 2- й)! \n" );
if ( strcmp(Name , "Федор") < 0) printf ("Строки не равны (1-я < 2- й)! \n" );
// число сравниваемых данных - 5
if ( strncmp(Name , "Василиса" , 5 ) == 0) printf ("Строки равны (идентичны)! \n" );
// нет ограничения
if ( strcmp(Name , "Василиса" ) == 0)
printf ("Строки равны (идентичны)! \n" );
else
printf ("Строки не равны ! \n" );
// _strnicmp – сравнение без учета регистра
if ( _strnicmp("Name" , "NAME" , 3 ) == 0) printf ("Строки равны (_strnicmp - идентичны)! \n" );
Результат получим такой:
Строки равны (идентичны)!
Строки не равны (1-я > 2- й)!
Строки не равны (1-я < 2- й)!
Строки равны (идентичны)!
Строки не равны !
Строки равны (_strnicmp - идентичны)!
Для поиска первого и последнего вхождения символа в строке используются функции: strchr и strrchr. Пример их применения дан ниже.
// strrchr - первое вхождение "и" в слове Василий
printf ("Строка исходная = %s Часть с найденным \"и\" = %s \n" , Name , strchr(Name , 'и') );
// strrchr - последнее вхождение "и" в слове Василий
printf ("Строка исходная = %s Часть с найденным \"и\" = %s \n" , Name , strrchr(Name , 'и') );
Результат получим такой:
Строка исходная = Василий Часть с найденным "и" = илий
Строка исходная = Василий Часть с найденным "и" = ий
Контроль строки на содержания подмножества символов производиться функцией strspn.
// strspn
char string1[] = "cabbage";
int result;
result = strspn( string1, "abc" );
printf( "Размер подстроки '%s', в которой только символы: a, b, or c "
"= %d байт\n", string1, result );
Результат получим такой:
Размер подстроки 'cabbage', в которой только символы: a, b, or c = 5 байт
9 Преобразование к нижнему или верхнему регистру
Для преобразования строки к нижнему и верхнему регистру (строчные и прописные буквы) применяют функции strlwr и strupr, соответственно.
// ПРЕОБРАЗОВАНИЕ К НИЖНЕМУ И ВЕРХНЕМУ РЕГИСТРУ
char string5[10] = ;
strcpy( string5 , "Sample");
printf( " %s\n", _strupr ( string5 ) );
setlocale( LC_ALL, "" );
strcpy( string5 , "Пример!"); // русские не преобразет без setlocale( LC_ALL, "" )
printf( " %s\n", strupr ( string5 ) );
printf( " %s\n", strlwr ( string5 ) );
Результат получим такой:
SAMPLE
ПРИМЕР!
пример!
10 Дублирование динамических строк
Для дублирования строки с выделением памяти применяют функцию strdup (или _strdup). После ее использования ее освобождают функцией free. Отметим что эта операция отличается от операции копирования указателей.
char buffer[] = "Это текст буферной строки!";
char *newstring;
printf( "Исходная строка 1: %s\n", buffer );
newstring = strdup( buffer ); // Дублирование строки динамически выделяется память
newstring[2] = '*' ; // Изменение 3-го символа в строке
printf( "Копия строки: %s\n", newstring );
printf( "Исходная строка 2: %s\n", buffer );
free( newstring ); // Изменение исвобождение памяти под дубль строку
Результат получим такой:
Исходная строка 1: Это текст буферной строки!
Копия строки: Эт* текст буферной строки!
Исходная строка 2: Это текст буферной строки!!
11 Выделение подстрок на множестве разделителей
Удобной возможностью разбиения строки на части является применения функции strtok. На основе заданного множества разделителей (у нас в примере: пробел, запятая, табуляция и конец строки) последовательно в цикле выделяются подстроки. Такие действия, соответствуют грамматическому разбору строки и часто называются парзингом (parse). В примере подстроки выводятся на экран.
/// ВЫДЕЛЕНИЕ ПОДСТРОК НА МНОЖЕСТВЕ РАЗДЕЛИТЕЛЕЙ
char strText4[] = "Строка\tдля ,,разделения на tokens\n по множеству разделителей\n";
char seps[] = " ,\t\n"; // Допустимые разделители
char *token;
printf( "Исходная строка:%s\n", strText4 ); // Разделители не видны
printf( "Подстроки (tokens):\n" );
// Получение первой подстроки:
token = strtok(strText4, seps ); //
// можно взять и функцию strtok_s
while( token != NULL ) // проверка наличия новых подстрок
{
// Вывод
printf( " %s\n", token );
// Новыя подстрока :
token = strtok( NULL , seps ); //
}
//
Результат получим такой:
Исходная строка:Строка для ,,разделения на tokens
по множеству разделителей
Подстроки (tokens):
Строка
для
разделения
на
tokens
по
множеству
разделителей
12 Преобразование данных в строку и обратно
Очень важные действия в языках программирования связаны с взаимными преобразованиями данных. Например, число преобразуется в строку или наоборот строка с цифровым текстом преобразуется в число. Для таких преобразований в СИ есть функции, которые включены в библиотеку stdlib.h. Ниже показаны примеры такого использования.
// Преобразование из строки в число и чисел в строку
char Buf[15];
int Dec , Sign;
//
printf("Из Строки (printf) -> '%s' в целое - %d\n", "125" , atoi( "125" ) );
printf("Из Строки (printf) -> '%s' в вещественное - %8.3f или %e \n", "125.5" , atof( "125.5" ) );
printf("Из целого (printf) -> '%d' в строку - %s в строку(itoa_s) - %s \n", 125 , itoa( 125, Buf , 10 ), _itoa_s( 25, Buf , 14 ,10 ) );
printf("Из целого с защитой Buf (printf) -> '%s' \n", Buf );
_gcvt( -35.5, 12, Buf );
printf("Из вещественного Buf (_gcvt) -> '%s' \n", Buf );
//
Результат получим такой:
Из Строки (printf) -> '125' в целое - 125
Из Строки (printf) -> '125.5' в вещественное - 125.500 или 1.299551e-257
Из целого (printf) -> '125' в строку - 125 в строку(itoa_s) - (null)
Из целого с защитой Buf (printf) -> '125'
Из вещественного Buf (_gcvt) -> '-35.5'
13 Сортировка срок
Сортировка массива строк массива строк по убыванию выполняется аналогично сортировке целого массива, только отличается фрагмент сравнения и обмена элементов в массиве строк. В примере предполагается, что все строки занимают разменр не более 9-ти сисмволов. Для обмена используется спеуиальная функция SwapStr, которая предварительно описывается.
// Функция обмена строк вне main
void SwapStr (char * S1 , char * S2 )
{
char TempStr[20];
strcpy(TempStr , S1 );
strcpy(S1 , S2);
strcpy( S2 , TempStr);
};
//
#define RazmMas 5
…
// Массив строк инициализируется в программе фамилиями
char StrMas[RazmMas][10]={"Сидоров", "Алетров", "Иванов", "Жучков" , "Акулов"};
// печать массива строк до сортировки
printf ("До сортировки \n");
for (int i =0 ; i < RazmMas ; i++ )
printf (" %d. - %s \n" , i + 1 , &StrMas[i][0]);
// Сортировка
for (int k = 0 ; k < RazmMas - 1 ; k++)
for ( int i =0 ; i < RazmMas - 1; i++ )
{
if ( strcmp(&StrMas[i][0] , &StrMas[i +1][0]) > 0 ) // Для убывания по алфавиту
// Обмен если условие сортировки не соблюдается
SwapStr(&StrMas[i][0] , &StrMas[i +1][0]);
};
// печать массива строк после сортировки
printf ("После сортировки \n");
for (int i =0 ; i < RazmMas ; i++ )
printf (" %d. - %s \n" , i + 1 , &StrMas[i][0]);
Результат получим такой:
До сортировки
1. - Сидоров
2. - Алетров
3. - Иванов
4. - Жучков
5. - Акулов
После сортировки
1. - Акулов
2. - Алетров
3. - Жучков
4. - Иванов
5. - Сидоров
14 Динамические строки
Часто все переменные и массивы располагаются в оперативной памяти заранее, до начала выполнения программы. Все рассмотренные ранее примеры включали такие переменные и массивы. Размер выделенной памяти под массив/строку, то есть его размерность в этом случае изменить в программе стандартным способом нельзя. Поэтому приходится заранее рассчитывать максимально возможную размерность массива, которая приемлема для всех случаев. Это приводит к перерасходу памяти для отдельных случаев. Для экономии памяти и для построения более универсальных программ используют динамически выделяемую память под массивы, строки и переменные. Такие данные называются динамическими. Важность динамического выделения памяти для строк трудно переоценить. Так как, например, для записи в новую строку текста превосходящего объема, нужно выделить новый больший объем ОП. Это выделение выполняется через предварительное освобождение старого фрагмента динамической памяти.
Для строк имя символьного массива рассматривается системой как указатель на char (char *). Это позволяет его использовать отдельно в функциях и операциях как специальный объкт (строка).
В языке СИ оперативная память выделялась с помощью специальных функций (alloc, calloc, malloc, free и т.д.). Они включены в библиотеку СИ – malloc.h. C помощью специальных операций в zpsrt С++ (new и delete) аналогично можно выделять память во время выполнения программы. Динамические переменные располагаются в оперативной памяти в специальной области. Для работы с такими данными используют указатели и ссылки. Примеры выделения динамической памяти для указателей и массивов втрок доны ниже.:
// Динамическая память
char * pStr = (char *) malloc( 10);
strcpy( pStr , "Динамика!" );
printf ("Динамическая память - %s \n" , pStr);
// Освобождение памяти
free (pStr);
pStr = (char *) calloc (15 , sizeof(char));
strcpy( pStr , "Новая память!" );
printf ("Новая память - %s \n" , pStr);
free (pStr);
//
int Razm;
/////////////////////////////
// Динамический массив строк
/////////////////////////////
printf ("Введите размер массива строк: \n" );
scanf ("%d", &Razm);