subject en:

Assignment name  : union
Expected files   : union.c
Allowed functions: write
--------------------------------------------------------------------------------

Write a program that takes two strings and displays, without doubles, the
characters that appear in either one of the strings.

The display will be in the order characters appear in the command line, and
will be followed by a \\n.

If the number of arguments is not 2, the program displays \\n.

Example:

$>./union zpadinton "paqefwtdjetyiytjneytjoeyjnejeyj" | cat -e
zpadintoqefwjy$
$>./union ddf6vewg64f gtwthgdwthdwfteewhrtag6h4ffdhsd | cat -e
df6vewg4thras$
$>./union "rien" "cette phrase ne cache rien" | cat -e
rienct phas$
$>./union | cat -e
$
$>
$>./union "rien" | cat -e
$
$>

subject ru:

Название задания  : union
Ожидаемые файлы   : union.c
Разрешенные функции: write
--------------------------------------------------------------------------------

Напишите программу, которая принимает две строки и отображает без повторений
символы, которые появляются в любой из строк.

Отображение будет происходить в том порядке, в котором символы отображаются
в командной строке, и за ними будет следовать \\n.

Если количество аргументов не равно 2, программа отображает \\n.

Пример:
$>./union zpadinton "paqefwtdjetyiytjneytjoeyjnejeyj" | cat -e
zpadintoqefwjy$
$>./union ddf6vewg64f gtwthgdwthdwfteewhrtag6h4ffdhsd | cat -e
df6vewg4thras$
$>./union "rien" "cette phrase ne cache rien" | cat -e
rienct phas$
$>./union | cat -e
$
$>
$>./union "rien" | cat -e
$
$>

Решение:

#include <unistd.h>

int		main(int argc, char **argv)
{
	int	ascii[255] = {0};
	int	i, j;

	if (argc == 3)
	{
		i = 1;
		while (i < 3)
		{
			j = 0;
			while (argv[i][j])
			{
				if (ascii[(unsigned char)argv[i][j]] == 0)
				{
					ascii[(unsigned char)argv[i][j]] = 1;
					write(1, &argv[i][j], 1);
				}
				j++;
			}
			i++;
		}
	}
	write(1, "\\n", 1);
	return (0);
}

Разбор решения :

#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

Суть решения состоит в том, что если буква хоть раз встретилась мы добавляем её в виртуальную таблицу ascii

ascii[(int)argv[i][j]] = 1;

и тут же выводим эту букву в консоль

write(1, &argv[i][j], 1);

Благодаря условию if (ascii[(int)argv[i][j]] == 0) мы никогда не распечатаем тот символ который уже встречался.