Last active
December 20, 2017 23:38
-
-
Save Lerbytech/ff2499b0077f47092950a5e7c752af81 to your computer and use it in GitHub Desktop.
Финальная задача Жуковой
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<stdio.h> | |
#include<stdlib.h> | |
#include<string.h> | |
#include<malloc.h> | |
#include<ctype.h> | |
int podstroki(char *st, char **pod_str, int k, int *massiv_nomerov, int m) | |
{ | |
char *pl, *pr, **q; | |
int n = strlen(st); | |
char *temp; | |
int length = 0; | |
char *dig; | |
q = pod_str + k; | |
pl = strstr(st, "**"); | |
if (pl == NULL) | |
return q - pod_str; | |
pl += 2; | |
for (; pl < st + n; pl++) | |
{ | |
pr = strstr(pl, "**"); | |
if (pr == NULL) | |
return q - pod_str; | |
else length = (int)(pr - pl); | |
for (dig = pl; dig < pr; dig++) | |
if (isdigit(*dig)) | |
break; | |
if (length > 0 && dig == pr) | |
{ | |
*q = (char*)malloc(length * sizeof(char)); | |
strncpy(*q, pl, length); | |
*(*q + length) = '\0'; | |
q++; | |
*(massiv_nomerov + k) = m; | |
k++; | |
} | |
pl = pr + 2; | |
} | |
return q - pod_str; | |
} | |
int poisk_max_podstroki(char **a, int n) | |
{ | |
char **s; int d, max; | |
d = 0; | |
for (s = a; s<a + n; s++) | |
{ | |
if (strlen(*s) > d) | |
{ | |
max = (s - a); | |
d = strlen(*s); | |
} | |
} | |
return max; | |
} | |
void zamena_simvola(char *st, char sim1, char sim2) | |
{ | |
char *p; | |
p = st; | |
while ((p = strchr(p, sim1))) *p = sim2; | |
} | |
int main() | |
{ | |
char **st, buf[80], **a, **pod_str, sim1, sim2; | |
int n = 0, k = 0, max, *i, m=0, *massiv_nomerov; | |
st = (char**)malloc(10 * sizeof(char*)); | |
a = st; | |
// выделение памяти под массив | |
while (n<100 && *gets_s(buf) != '\0') | |
{ | |
*a = (char*)malloc(strlen(buf) + 1); | |
strcpy(*a, buf); | |
a++; | |
n++; | |
} | |
massiv_nomerov = (int*)malloc(20 * sizeof(int)); | |
pod_str = (char**)malloc(20 * sizeof(char*)); | |
for (a = st; a<st + n; a++) | |
{ | |
k = podstroki(*a, pod_str, k, massiv_nomerov, m); | |
m++; | |
} | |
if (k == 0) | |
{ | |
printf("Podstroki ne naydeni! gtfo \n"); | |
return 0; | |
} | |
printf("Vivod vsex podctrok:\n"); | |
for (a = pod_str; a< pod_str + k; a++) | |
puts(*a); | |
max = poisk_max_podstroki(pod_str, k); | |
printf("Samaya dlinnaya podstroka:"); | |
puts(*(pod_str + max)); | |
printf("Prinadlejit stroke:"); | |
char *swap = *(st + *(massiv_nomerov + max)); | |
puts(swap); | |
printf("\n Vvedite simvoli:\n"); | |
printf("1> "); scanf("%c", &sim1); | |
getchar(); | |
printf("2> "); scanf("%c", &sim2); | |
zamena_simvola(swap, sim1, sim2); | |
printf("Vivod vsex podctrok:\n"); | |
for (a = st; a< st + n; a++) | |
puts(*a); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Последняя задача Жуковой.
Последняя в семестре задача состоит из трёх подзадач. Последовательность решения всех трёх задач следующая:
0. Ввести массив подстрок (обозначим его как А)
Если рассматривать структуру решения, то , вам следует написать 4 функции:
Важно: Для простоты изложения я буду называть функции адекватными и понятными обозначениями. Не забудьте переписать названия под себя.
Для решения всей задачи надо заранее ответить на один вопрос: как сопоставлять подстроке из массива Б строку из массива А?

Одним из самых простых вариантов: ввести некоторую таблицу, хранящую сколько строк вынули из массива А. Её устройство может быть различным.
Рассмотрим 3 варианта, основанных на массиве. Для простоты будем рассматривать разбиение массива строк на подстроки по пробелам.
Вариант 1:
Таблица представлена в виде массива, его размерность равна количеству выделенных подстрок. В каждую ячейку записан номер строки из массива А, из которой мы выделили подстроку.
Вариант 2:

В данном случае размерность массива равна количеству исходных строк. В каждую ячейку записано количество выделенных подстрок.
Пусть по обеим таблицам нам следует найти строку, содержавшую подстроку
2E
. По варианту 1 мы сразу получаем ответ.По варианту 2, нам необходимо проявить смекалку: зная порядковый номер подстроки
2E
мы должны найти строку из массива А, содержащую i-ую подстроку. Нас интересует такая строка, что предыдущая строка массива А гарантированно не содержит искомую.Можно выполнить некоторую оптимизацию и вывести вариант 3:

Вариант 1 является самым простым.
0. Ввести массив подстрок
Всё необходимое описано в подробном разборе ввода массива подстрок по ссылке/
1. Выделить массив подстрок
Будем работать с массивом А (введён с клавиатуры) и массивом Б (формируем сами).
Выделение подстрок из массива/. Для выделения массива подстрок вы проходите в цикле по всему массиву А
Анализ вариантов из задания показывает следующие варианты разбиения:
Отдельно стоит вариант 10: для него лучше всего воспользоваться циклом for и
2. Выделить из А новый массив подстрок Б.
Условия разбиения можно разбить по следующим группам:
Заметка про задачи где встречаются "скобки": считайте, что все скобки стоят верно, каждой открывающей соответствует закрывающая и вложенных выражений вида
((АBC)D(EFG))
не встречается. Если ТВ предъявит вам что надо было проверять, то она во-первых этому не учит, во-вторых пусть научится техзадание адекватно формулировать.Отметим условие задачи: пустые подстроки не следует выделять и нельзя печатать. Если вы выделяете подстроки, то убедитесь что разница
Для решения всех задач я рекомендую ввести два указателя:
char *p_left
иchar *p_right
, обозначающие левую и правую границу вашей подстроки (то есть, её первый и последний символы).Также напоминаю полезные для работы функции:
strstr(strA, strB)
возвращает первое вхождениеstrB
вstrA
.strchr(str, letter)
вернёт позициюletter
вstr
strncpy(dest, length, source)
- копирует изsource
вdest
первыеn
элементовЕсть нюанс между. Допустим вы идете с начала строки. "Найти заключенные подстроки" означает, что нужно выделить подстроки ограниченные слева и справа. Следовательно, перед циклом прохода по строке вы можете пропустить часть подстроки, пока не найдете последовательность символов с которой начинается ваше слово.
Если же следует найти "разделенные", то начало строки пропускать нельзя.
Рассмотрим вариант задания 9, где требуется разбить на подстроки, разделенные двумя звездочками .
"Более чем двумя звездочками" означает две вещи. Во-первых, мы можем пользоваться strstr(str, "***") для нахождения границ подстроки. Во-вторых, после выделения строки необходимо пролистать лишние звездочки: из
111***333******AA
нужно выделить111
,333
,AA
.Функция gen_podst() принимает аргументы:
char *st
- строка которую следует разбитьchar **pod_str
- указатель на массив подстрок. В него могут быть уже внесены некоторые подстроки.int k
- смещение в массиве подстрок начиная с которого можно добавлять новые строки.int *massiv_nomerov
- указатель на массив номеров, позволяющий сопоставлять А и Б. Заполняется по варианту 1int m
- порядковый номер текущей строки.Функция же возвращает модифицированное значение
k
, то есть общее кол-во всех выделенных подстрокПеременные необходимые для работы:
char *p_left, *p_right
- указатели на левую и правую частьchar **q
- указатель для работы с pod_strint n = strlen(st)
- длина исходной строки. Считаем сразу для оптимизацииint length = 0;
- длина выделенной подстрокиint *nomer_stroki;
- указатель для работы с massiv_nomerovchar *dig
- переменная для проверки на цифру (см. условие варианта 3)Инициализируем значения:
Общая логика алгоритма такая:
находим правую границу, вычисляем длину
length
выделяем строку отp_left
доp_right
, проверяем её на наличие цифры, если всё хорошо - копируем, затем ставимp_left = p_right + 1
. Обязательно+1
, так какp_left
далее в цикле будет увеличено на 1, а всего мы ищем 2 звездочки. В противном случае, пропускали бы лишний 1 символ в последующих подстроках. Когдаp_right
равноNULL
, копируем остаток строки.3. Поиск подстроки по условию.
Поиск подстроки осуществляется функцией
find_str()
. Функция возвращает порядковый номер строки из массива подстрок Б, удовлетворяющую условию.Рассмотрим пример - найти подстроку наибольшей длины (вариант 1).
Для работы с исходным массивом подстрок
char** a
вводим указательchar **s
. Для данной задачи помимо результата - переменнойmax
- необходимо хранить и временное значениеd
, в котором хранится длина максимальной строки. Это позволяет не пересчитывать её каждый раз.Сам по себе порядковый номер строки - это разница между указателем на неё и указателем на первую строку из списка подстрок.
Данный алгоритм превращается в вариант 2 с минимальными модификациями.
Для остальных вариантов (кроме 5 и 9) данный алгоритм поиска является костяком, на который следует навесить дополнительную логику. Однако следует учитывать один момент.
У алгоритмов поиска минимума и максимума в массивах всегда был недостаток - экстремумом считается первый элемент, подошедший под условия. То есть, если у вас две строки длиной 1 символ, то минимальной по длине будет считаться первая из них.
В то же время, у вас может не найтись например максимальной по длине строки содержащей двойки так как в исходном массиве Б не будет никаких подстрок, содержащих 2. Тогда ваша функция
Варианты 5 и 9 стоят особняком и требуют отдельного решения.
Для варианта 9 достаточно в цикле обхода массива подстрок вернуть первую подстроку, для который результат
strchr
не равенNULL
. Если же ни одна строка не содержит символ, то следует продумать какое значение вернуть обратно в функциюmain
.Для варианта 5 следует прописать модифицированный алгоритм поиска минимума в массиве подстрок. Нужно хранить порядковый номер строки и символ, чья величина минимальна по значение. Для каждой строки необходимо пройтись по всем элементам и сравнить их значения с минимальным символом.
Для сравнения используйте следующее:
Где *p - указатель на символ рассматриваемой подстроки
4. Модификация строки
Если прочитать условия, то всё сходится к следующим вариантам:
В рамках этих трёх строк происходят различные операции замены, удаления или вставки.
В группу 1 входит только вариант 6.
В группу 2: 1, 3, 7, 8.
В группу 3: 2, 4, 5
Группа 1
Вводите с клавиатуры два символа: старый и новый.
Затем следует простой цикл.
Группа 2
При удалении символа ваша задача - сдвинуть весь остаток строки так, чтобы закрыть удаляемый символ. Вариантов сдвига два: либо "руками", то есть прописывая сдвиг каждого символа, либо через strcpy. Второй вариант лучше подходит под задачу удаления нескольких подряд идущих символов, но в задании у вас такого нигде не требуется.
Пример универсальной функции для удаления заданного символа из строки:
В функции remove два указателя
src
иdest
идут с начала строки до её конца.src
перебирает все символы исходной строки, adest
указывает на ту позицию, куда следует перенести откопированный символ.Группа 3