subject en:
Assignment name : inter
Expected files : inter.c
Allowed functions: write
--------------------------------------------------------------------------------
Write a program that takes two strings and displays, without doubles,
the characters that appear in both strings, in the order they
appear in the first one.
The display will be followed by a \\n.
If the number of arguments is not 2, the program displays \\n.
Examples:
$>./inter "padinton" "paqefwtdjetyiytjneytjoeyjnejeyj" | cat -e
padinto$
$>./inter ddf6vewg64f gtwthgdwthdwfteewhrtag6h4ffdhsd | cat -e
df6ewg4$
$>./inter "nothing" "This sentence hides nothing" | cat -e
nothig$
$>./inter | cat -e
$
subject ru:
Название задания : inter
Ожидаемые файлы : inter.c
Разрешенные функции: write
--------------------------------------------------------------------------------
Напишите программу, которая принимает две строки и отображает
без повторений символы, которые появляются в обеих строках, в том
порядке, в котором они появляются в первой.
За отображением будет следовать символ \\n.
Если количество аргументов не равно 2, программа отображает \\n.
Примеры:
$>./inter "padinton" "paqefwtdjetyiytjneytjoeyjnejeyj" | cat -e
padinto$
$>./inter ddf6vewg64f gtwthgdwthdwfteewhrtag6h4ffdhsd | cat -e
df6ewg4$
$>./inter "rien" "cette phrase ne cache rien" | cat -e
rien$
$>./inter | cat -e
$
Решение 1:
#include <unistd.h>
int
main(int argc, char **argv)
{
int ascii[255] = {0};
int i, j;
if (argc == 3)
{
i = 2; // для захода на вторую фразу
while (i > 0) // после первой фразы i станет нулем, и мы выйдем из цикла
{
j = 0; //зануляем j для первой буквы
while (argv[i][j])
{
if (i == 2 && ascii[(unsigned char)argv[i][j]] == 0) //если в массиве ascii будет 0 - заходим, 1 - не заходим
ascii[(unsigned char)argv[i][j]] = 1;
else if (i == 1 && ascii[(unsigned char)argv[i][j]] == 1)
{
write(1, &argv[i][j], 1);
ascii[(unsigned char)argv[i][j]] = 2;
}
j++;
}
i--;
}
}
write(1, "\\n", 1);
return (0);
}
Решение 2:
#include <unistd.h>
int ft_check(char *argv1, char c, int index)
{
int i;
i = 0;
while (i < index) // пока i < indexa
{
if (argv1[i] == c) // если до этого момента символы совпадут, вернуть 0 (все бесполезно), если проверка прошла и символ не совпал - работаем дальше
return (0);
i++;
}
return (1);
}
void ft_inter(char *argv1, char *argv2)
{
int i;
int j;
i = 0;
while (argv1[i]) // пока существует argv1
{
if (ft_check(argv1, argv1[i], i) == 1) // если проверяемый символ до индекса i ещё не встречался
{
j = 0;
while (argv2[j]) // пока существует argv2
{
if (argv1[i] == argv2[j]) // если в argv2 найден искомый(проверяемый символ) из argv1
{
write (1, &argv1[i], 1); // печатаем и выходим из цикла
break;
}
j++;
}
}
i++;
}
}
int main(int argc, char **argv)
{
if (argc == 3) // проверяем, что число аргументов 3
{
ft_inter(argv[1], argv[2]); // если так, то переходим в функцию
}
write (1, "\\n", 1); // и в конце в любом случае \\n
return (0);
}
Разбор решения 1:
#include <stdio.h>
int main(int argc, char **argv)
{
printf("ARGV[1]: %s\\n", argv[1]);
printf("ARGV[2]: %s\\n", argv[2]);
return (0);
}
Печатаем вторую букву из первой фразы и первую буквы из второй фразы
#include <stdio.h>
int main(int argc, char **argv)
{
printf("ARGV[1]: %c\\n", argv[1][1]);
printf("ARGV[2]: %c\\n", argv[2][0]);
return (0);
}
Печатаем те же символы в виде цифр из таблицы ascii
#include <stdio.h>
int main(int argc, char **argv)
{
printf("ARGV[1]: %d\\n", argv[1][1]);
printf("ARGV[2]: %d\\n", argv[2][0]);
return (0);
}
Создаем “виртуальный” массив ascii и кладем в каждый его элемент ноль
int ascii[255] = {0};
И распечатаю его
#include <stdio.h>
int main(int argc, char **argv)
{
int ascii[255] = {0};
int n;
printf("ARGV[1]: %d\\n", argv[1][1]);
printf("ARGV[2]: %d\\n", argv[2][0]);
printf("Virtual ASCII\\n");
n = 0;
while (n <= 255)
{
printf("ARGV[%d]: %d\\n", n, ascii[n]);
n++;
}
return (0);
}
Буква b по таблице ascii равна 98
Буква c по таблице ascii равна 99
При встрече этих букв будем записывать в виртуальную таблицу ascii единицу вместо нуля.
#include <stdio.h>
int main(int argc, char **argv)
{
int ascii[255] = {0};
int n;
printf("ARGV[1]: %d\\n", argv[1][1]);
printf("ARGV[2]: %d\\n", argv[2][0]);
ascii[argv[1][1]] = 1;
ascii[argv[2][0]] = 1;
printf("Virtual ASCII\\n");
n = 0;
while (n <= 255)
{
printf("ARGV[%d]: %d\\n", n, ascii[n]);
n++;
}
return (0);
}
Меняем вторую букву в первой фразе и первую букву во второй фразе
gcc inter_v2.c && ./a.out aZc Ybd
Консольный вывод поменяется соответствующим образом
ARGV[88]: 0 ARGV[89]: 1 ARGV[90]: 1 ARGV[91]: 0
Концепция решения inter состоит в том, что мы сначала проверяем вторую фразу
i = 2; ...
if (i == 2 ...)
И при встрече любой буквы, отмечаем её в виртуальном массиве ascii.
Второе условие в if - !used[argv[i][j]])
позволяет пропустить уже записанную букву в массив, тем самым исключаем повторения.
Так мы записываем каждую буквы из второй фразы, переходя на следующую букву с помощью j++;
После выхода из первого вложенного цикла, переключаемся на первую фразу с помощью i--;
и теперь мы будем попадать в первую фразу через условие
else if (i == 1 && ...)
второе условие used[argv[i][j]] == 1 позволяет войти в if, если буква уже встречалась во второй фразе.
Если звезды сошлись, то выводим в консоль нужную букву write(1, &argv[i][j], 1);
и убираем единицу из виртуальной таблицы ascii командой - ascii[argv[i][j]] = 2;