
- •Тема 8. Строки Что такое строка в языке Си?
- •Присвоение значения строке
- •Строки и символы: кавычки или апострофы?
- •Ввод и вывод строк
- •Библиотека string.H
- •Передача строк в качестве аргументов функций
- •Сортировка массива строк
- •Выбор порядка сортировки динамически
- •Передача массива строк в качестве аргументов функций
Сортировка массива строк
Задача сортировки массива строк аналогична задаче сортировки числового массива, и все алгоритмы сортировки чисел могут быть применены для сортировки строк. Разница заключается только в деталях реализации этих алгоритмов. Две основные операции, которые используются в сортировке – это сравнение элементов и перестановка элементов. При сравнении чисел, если выполняется неравенство a>b, то мы говорим, что число a «больше» числа b. Самым распространенным вариантом сравнения строк является алфавитный или более общий лексико-графический порядок. Он задается функцией strcmp(), поэтому при сравнении строк вместо
If (Str1<str2)
Нужно писать
If (Strcmp(str1,str2)<0)
Если нужно отсортировать строки по длине, то следует записать так:
If (strlen(str1)<strlen(str2))
Перестановка двух строк также специфична. Поскольку строка представляет собой массив, то шаблон перестановки для чисел не подойдет.
Str1=str2
Необходимо использовать функцию strcpy()
Strcpy(str1,str2)
Следующая программа демонстрирует сортировку строк (жирным шрифтом выделена собственно сортировка):
#define N 8
char names[N][20] = {
"Сергей", "Мария", "Василий", "Дмитрий",
"Татьяна", "Виталий", "Артем", "Елена"
};
void printNames() {
for (int i=0; i<N; i++) {
puts(names[i]);
}
}
void sortNames() {
for (int i=1; i<N; i++) {
for (int j=0; j<N-1; j++) {
if (strcmp(names[j],names[j+1]) > 0) {
char temp[20];
strcpy(temp, names[j]);
strcpy(names[j], names[j+1]);
strcpy(names[j+1], temp);
}
}
}
}
int main() {
puts("До сортировки:");
printNames();
puts("\nПосле сортировки:");
sortNames();
printNames();
}
Если в данном коде изменить условие, поставив вместо
if (strcmp(names[j],names[j+1]) > 0) {
…
}
условие
if (strlen(names[j])<strlen(names[j+1])) {
…
}
то строки будут отсортированы по длине:
Выбор порядка сортировки динамически
Порядок сортировки может быть разным. В предыдущем примере сортировка осуществлялась либо в алфавитном порядке, либо согласно длине. В алфавитном порядке отсортировать также можно двумя способами: по возрастанию и по убыванию. Если же мы будем работать не с массивом строк или чисел, а с массивом записей, каждая из которых состоит из нескольких полей, то типов сортировки может быть еще больше. Вопрос заключается в следующем: «Для каждой сортировки нужно писать свою функцию, или, все-таки, можно обойтись одной?»
В рассмотренном выше примере сортировка по алфавиту и сортировка по длине отличается лишь условием, поэтому неразумно делать две функции, которые почти одинаковы. Хорошим решением является передача типа сортировки в качестве аргумента. Но какого? Однозначного ответа нет, поскольку вариантов сортировки может быть много, поэтому давайте положим, что требуется реализовать сортировку либо по возрастанию, либо по убыванию. Для этого сойдет параметр логического типа, который принимает значение true, если требуется обратный порядок, и false – прямой. Чтобы не было путаницы эти значения лучше задать именованными константами REVERSE_ORDER и STRAIGHT_ORDER.
Ниже приведена программа, которая определяет порядок сортировки массива согласно выбору в меню.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//Размер списка
#define N_CITIES 12
//Максимальная длина названия
#define MAX_LENGTH 15
//Обратный порядок сортировки
#define REVERSE_ORDER true
//Прямой порядок сортировки
#define STRAIGHT_ORDER false
//Список городов
char cities[N_CITIES][MAX_LENGTH] = {
"Новосибирск", "Москва", "Цюрих",
"Нью Йорк", "Мадрид", "Париж",
"Барселона", "Лондон", "Токио",
"Монте-Карло", "Глазго", "Каир"
};
//Прототипы используемых функций
void printCities();
void sortCities(bool order);
void printMenu();
int getChoice();
int main() {
while (true) {
printMenu();
switch(getChoice()) {
case 1 :
sortCities(STRAIGHT_ORDER);
printCities();
break;
case 2 :
sortCities(REVERSE_ORDER);
printCities();
break;
case 0 :
exit(EXIT_SUCCESS);
default :
exit(EXIT_FAILURE);
}
//Подождать, пока пользователь
//нажмет любую клавишу
system("pause");
}
return 0;
}
//Вывод списка городов
void printCities() {
for (int i=0; i<N_CITIES; i++) {
puts(cities[i]);
}
}
//Сортировка списка городов
//(метод прямого выбора)
//Аргумент order может равняться
//STRAIGHT_ORDER или REVERSE_ORDER
void sortCities(bool order) {
for (int i=0; i<N_CITIES-1; i++) {
int min=i;
for (int j=i+1; j<N_CITIES; j++) {
if (order ^
strcmp(cities[min], cities[j])>0) {
min=j;
}
}
char temp[MAX_LENGTH];
strcpy(temp, cities[min]);
strcpy(cities[min], cities[i]);
strcpy(cities[i], temp);
}
}
//Вывод меню на экран
void printMenu() {
//Очистка экрана
system("cls");
printf("---МЕНЮ---\n");
printf("1-Прямой порядок\n");
printf("2-Обратный порядок\n");
printf("0-Выход\n");
printf("Ваш выбор - ");
}
//Выбор пункта меню и
//проверка его правильности (0, 1 или 2)
int getChoice() {
int choice;
scanf("%d", &choice);
if (choice<0 || choice>2) {
printf("Нет такого пункта\n");
printf("Выберите еще раз - ");
//Если выбор неверный,
//то предлагаем попробовать еще раз
return getChoice();
}
return choice;
}