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;