Определить количество положительных элементов в тех строках, которые содержат хотя бы один нулевой элемент - C (СИ)
Формулировка задачи:
Решение задачи: «Определить количество положительных элементов в тех строках, которые содержат хотя бы один нулевой элемент»
#include <stdio.h>
#include <math.h>
#define EPSILON_DOUBLE 0.000000001
#define EPSILON_FLOAT 0.00001f
#define M 3
#define N 4
int PositiveIntPredicate(const void* n)
{
return (*(int*)n > 0);
}
int PositiveDoublePredicate(const void* d)
{
return (*(double*)d > EPSILON_DOUBLE);
}
int PositiveFloatPredicate(const void* f)
{
return (*(float*)f > EPSILON_FLOAT);
}
int IsZeroInt(const void* n)
{
return (*(int*)n == 0);
}
int IsZeroDouble(const void* d)
{
return (fabs(*(double*)d) <= EPSILON_DOUBLE);
}
int IsZeroFloat(const void* f)
{
double temp = *(float*)f * 1.0;
return IsZeroDouble(&temp);
}
/*
Returns the number of elements in the range [first,last) for which predicate is true.
*/
size_t count_if(const void* first, const void* last, const size_t elementSize,
int (*predicate)(const void* elem))
{
size_t count = 0;
while (first != last)
{
if (predicate(first)) count++;
first = (char*)first + elementSize;
}
return count;
}
/*
Returns true if pred returns true for any of the elements in the range [first,last), and false otherwise.
*/
int any_of(const void* first, const void* last, const size_t elementSize,
int (*predicate)(const void* elem))
{
while (first != last)
{
if (predicate(first)) return 1;
first = (char*)first + elementSize;
}
return 0;
}
void TestInts(void)
{
int a[M][N] = {
{1, 2, 3, 4},
{1, 0, 2, 3},
{0, 0, 1, 2}
};
size_t i, j;
size_t positiveCount = 0;
printf("=== INTEGER TEST ===\n");
for (i = 0; i < M; i++)
{
for (j = 0; j < N; j++)
{
if (j == N - 1) printf("%3d\n", a[i][j]);
else printf("%3d ", a[i][j]);
}
}
for (i = 0; i < M; i++)
{
if (any_of(&a[i], &a[i] + 1, sizeof(int), IsZeroInt))
{
positiveCount = count_if(&a[i], &a[i] + 1, sizeof(int), PositiveIntPredicate);
printf("At line %lu: count = %lu\n", i, positiveCount);
}
}
printf("=== END TEST ===\n\n");
}
void TestDoubles(void)
{
double a[M][N] = {
{-1.0, 0.0, 0.0, 1.0},
{2.99, 0.0, 0.0, 3.0},
{1.0, 2.0, 3.0, 4.0}
};
size_t i, j;
size_t positiveCount = 0;
printf("=== DOUBLES TEST ===\n");
for (i = 0; i < M; i++)
{
for (j = 0; j < N; j++)
{
if (j == N - 1) printf("%+.4f\n", a[i][j]);
else printf("%+.4f ", a[i][j]);
}
}
for (i = 0; i < M; i++)
{
if (any_of(&a[i], &a[i] + 1, sizeof(double), IsZeroDouble))
{
positiveCount = count_if(&a[i], &a[i] + 1, sizeof(double), PositiveDoublePredicate);
printf("At line %lu: count = %lu\n", i, positiveCount);
}
}
printf("=== END TEST ===\n\n");
}
void TestFloats(void)
{
float a[M][N] = {
{0.0f, 0.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f, -3.0f},
{1.0f, 2.0f, 3.0f, 0.0f}
};
size_t i, j;
size_t positiveCount = 0;
printf("=== FLOATS TEST ===\n");
for (i = 0; i < M; i++)
{
for (j = 0; j < N; j++)
{
if (j == N - 1) printf("%+.4f\n", a[i][j]);
else printf("%+.4f ", a[i][j]);
}
}
for (i = 0; i < M; i++)
{
if (any_of(&a[i], &a[i] + 1, sizeof(float), IsZeroDouble))
{
positiveCount = count_if(&a[i], &a[i] + 1, sizeof(float), PositiveFloatPredicate);
printf("At line %lu: count = %lu\n", i, positiveCount);
}
}
printf("=== END TEST ===\n\n");
}
int main(void)
{
TestInts();
TestDoubles();
TestFloats();
return 0;
}
Объяснение кода листинга программы
В данном коде определены функции-предикаты для проверки нулевых значений и положительных чисел для типов данных int, double и float. Также определены функции count_if и any_of для подсчета числа элементов, удовлетворяющих условию, и проверки наличия такого элемента в диапазоне. В функции TestInts массив a[M][N] содержит значения {1, 2, 3, 4}, {1, 0, 2, 3}, {0, 0, 1, 2}. При итерации по этому массиву выводится каждое значение. Затем проверяется наличие нулевого значения в каждой строке. Если такое значение найдено, то подсчитывается количество положительных значений в этой строке и выводится на экран. Аналогично работает функция TestDoubles, но с массивом double и немного другими значениями. Функция TestFloats работает также, но использует функцию IsZeroDouble для проверки нулевых значений в float. В функции main вызываются все три функции для тестирования.