Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Функция для подсчёта количества элементов, Казалось бы, простая задача . . . 
:(
    Опции темы
ANTON_AL
Дата 16.7.2008, 13:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 292
Регистрация: 27.1.2007

Репутация: нет
Всего: нет



Доброго дня!

Есть картинка, представленная в виде двумерного массива. Эта картинка играет роль маски в операции по обработке изображений.
Если значение пикселя == 0, следовательно - элемент не учитывается, иначе, если > 0 - то учитывается. Возникает задача подсчитать элементы маски, которые > 0.


Вот код
Код

#include <conio.h>
#include <iostream>
using namespace std;


typedef unsigned char BYTE;

//Calculate number of elements, equals to specified value
template< class T >
int count( T *pSrc, int width, int height, int pitch, int step, T val )
{
    int count = 0;

    for ( int y = 0; y < height; y++ )
        for ( int x = 0; x < width; x++ )
        {
            T a = pSrc[y*pitch + x * step];
            T b = val;
            if ( a == b )
                count++;
        }

    return count;
}



void main( )
{
    BYTE test[] = {    0, 0, 0, 0,
                0, 255, 255, 0,
                0, 1, 1, 1,
                0, 0, 0, 0 };

    #if 1 // the result must be 5, but actually, we get 3
        std::cout << count<bool>( (bool*)test, 4, 4, 4, 1, true );
    #else
        std::cout << count<BYTE>( (BYTE*)test, 4, 4, 4, 1, 255 );
    #endif


    getch( );
}


Казалось бы, ничего подозрительного, но выражение
Код

T a = pSrc[y*pitch + x * step];
T b = val;
if ( a == b )
    count++;

 . . . работает не так, как хотелось бы.

Необходимо, чтобы функция была именно такой, как представлена, т.е., чтобы выполнялось поэлементное сравнение.
Как видно из кода, указатель на BYTE преобразуется в указатель на bool, что и является причиной ошибки.

Вот в этом и вопрос - как написать универсальную функцию, которая подсчитывает количество элементов с указанным значением ?
Основное требование: если в неё подать массив типа BYTE, то она должна подсчитать количество ненулевых значений ( с шаблонным параметром - bool )

Это сообщение отредактировал(а) ANTON_AL - 16.7.2008, 13:27
PM MAIL   Вверх
Ulysses4j
Дата 16.7.2008, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 304
Регистрация: 6.6.2007
Где: Ростов-на-Дону

Репутация: 4
Всего: 10



Я так понял, функция написана в предположении, что bool ~ 1 биту, это не так, размеры всех встроенных типов кратны char.  Чтобы анализировать битовое представление, нужно использовать арифметические операции % и /.


--------------------
Communication is critical to the job of a programmer.
C. Jazdzewski. Fatherly Advice To New Programmers
PM MAIL WWW   Вверх
vinter
Дата 16.7.2008, 14:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Код

 (bool*)test

так ты приводишь указатель, 255 от этого не станет равным true, который в свою очередь равен 1(скорее всего)


--------------------
Мой блог
PM MAIL WWW   Вверх
Lazin
Дата 16.7.2008, 14:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



в функции count, вместо переменной step, нужно использовать sizeof(T)

а вместо 
Код

T a = pSrc[y*pitch + x * step];

правильнее будет написать:
Код

T a = pSrc[y*width + x];


Добавлено через 57 секунд
в общем параметры step и pitch являются лишними
PM MAIL Skype GTalk   Вверх
Ulysses4j
Дата 16.7.2008, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 304
Регистрация: 6.6.2007
Где: Ростов-на-Дону

Репутация: 4
Всего: 10



Цитата(vinter @  16.7.2008,  15:07 Найти цитируемый пост)
так ты приводишь указатель, 255 от этого не станет равным true

Да что ж такое, так и не начал стандарт читать:
Цитата
An rvalue of arithmetic, enumeration, pointer, or pointer to member type can be converted to an rvalue of type bool. A
zero value, null pointer value, or null member pointer value is converted to false any other value is converted to true.

ISO/IEC 14882:1998, 4.12.


--------------------
Communication is critical to the job of a programmer.
C. Jazdzewski. Fatherly Advice To New Programmers
PM MAIL WWW   Вверх
ANTON_AL
Дата 16.7.2008, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 292
Регистрация: 27.1.2007

Репутация: нет
Всего: нет



Lazin
Цитата

в общем параметры step и pitch являются лишними


Нет, параметр step требуется для обработки отдельного канала изображения (чтобы шагать через 3 байта).
Вообще, вопрос у меня не в этом. Не смотрите на pitch и step. . .

Ulysses4j, 
Цитата

Я так понял, функция написана в предположении, что bool ~ 1 биту

нет, не было такого предположения. Я знаю, сколько занимает каждый тип данных.

Если прогнать программу в отладчике, то он будет показывать "верные" значения. ( см. приложение).

Тут причина в том, что если берем значение a по указателю
Код

T a = pSrc[y*pitch + x * step];

то не происходит конверсии в тип bool. ( это и понятно ), происходит лишь интрерпретация куска памяти как bool.

Операция == выполняется побитово. Из за этого и получается
Код

    BYTE a = 255;
    BYTE b = 1;
    if ( *(bool*)&a == *(bool*)&b )
        std::cout << "true";
    else
        std::cout << "false"; //попадём сюда

    if ( (bool)a == (bool)b )
        std::cout << "this will be ok";




А вообще, на 90 % уверен, что такая задача не решаема универсальным способом.

Это сообщение отредактировал(а) ANTON_AL - 16.7.2008, 14:33

Присоединённый файл ( Кол-во скачиваний: 10 )
Присоединённый файл  capture.JPG 157,82 Kb
PM MAIL   Вверх
Lazin
Дата 16.7.2008, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(Ulysses4j @  16.7.2008,  13:53 Найти цитируемый пост)
Я так понял, функция написана в предположении, что bool ~ 1 биту, это не так, размеры всех встроенных типов кратны char.  Чтобы анализировать битовое представление, нужно использовать арифметические операции % и /. 

вообще-то указателя на бит не бывает smile 
а что-бы анализировать битовое представление нужно использовать битовые операции >> << & | ~ smile 
PM MAIL Skype GTalk   Вверх
vinter
Дата 16.7.2008, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Код

#include <iostream>
int main()
{
    unsigned char test[] = {    0, 0, 0, 0,
        0, 255, 255, 0,
        0, 1, 1, 1,
        0, 0, 0, 0 }; 
    bool *test1 = (bool*)test;
    for(int i = 0; i < sizeof(test); ++i)
        std::cout << (test1[i] == true) << "\n";
    std::cin.get();
    return 0;
} 

vs2008 выводятся 3 еденицы
Цитата(Ulysses4j @  16.7.2008,  15:16 Найти цитируемый пост)
can be

ни о чем Вам не говорит?
Прежде чем чем то тыкать, проверяем  smile 



--------------------
Мой блог
PM MAIL WWW   Вверх
Lazin
Дата 16.7.2008, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



ANTON_AL, на скриншоте вызов count<bool> или count<BYTE>?
PM MAIL Skype GTalk   Вверх
Ulysses4j
Дата 16.7.2008, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 304
Регистрация: 6.6.2007
Где: Ростов-на-Дону

Репутация: 4
Всего: 10



Дело не в can be,  а в том что я перепутал преобразования (bool*)(·) и (bool)(·). Если вам не нравится, когда вам тыкают, прошу прощения, впредь буду более бережным к вашим чувствам.

Цитата(Lazin @  16.7.2008,  15:31 Найти цитируемый пост)
вообще-то указателя на бит не бывает  

А где я сказал, что бывают указатели на бит? Я сказал, что смотря на функцию складывается впечатление, что человек хотел проходить указателем по битам.
Цитата(Lazin @  16.7.2008,  15:31 Найти цитируемый пост)
а что-бы анализировать битовое представление нужно использовать битовые операции >> << & | ~

Можно эти, можно арифметические, как я сказал. Арифметические намного легче воспринимаются, имхо. Хотя от задачи тоже зависит.


--------------------
Communication is critical to the job of a programmer.
C. Jazdzewski. Fatherly Advice To New Programmers
PM MAIL WWW   Вверх
ANTON_AL
Дата 16.7.2008, 14:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 292
Регистрация: 27.1.2007

Репутация: нет
Всего: нет



Цитата

ANTON_AL, на скриншоте вызов count<bool> или count<BYTE>? 

count<bool>
PM MAIL   Вверх
Rififi
Дата 16.7.2008, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1254
Регистрация: 9.3.2008

Репутация: 11
Всего: 36



программа работать не будет, и это правильно, ибо у типа bool есть только 2 значения: true и false. всё остальное - кривизна. никакие 0, 1, 255, -999, 1000000 и прочие чудеса к bool неприминимы.

выход - написать отдельную шаблонную спецификацию для bool

T tmp = pSrc[y*pitch + x * step];
bool a = static_cast<bool>(tmp != 0);

кому же такая индексация по указателю приведет к UB при использовани двумерного динамического массива (BYTE**).


Это сообщение отредактировал(а) Rififi - 16.7.2008, 15:01
PM MAIL   Вверх
ANTON_AL
Дата 16.7.2008, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 292
Регистрация: 27.1.2007

Репутация: нет
Всего: нет



Rififi, да, я к этому и сколняюсь.



Я во втором ответе приводил пример, который демонстрирует интерпретацию памяти и побитовые свойства ==.
Код

    BYTE a = 255;
    BYTE b = 1;
    if ( *(bool*)&a == *(bool*)&b )
        std::cout << "true";
    else
        std::cout << "false";

    if ( (bool)a == (bool)b )
        std::cout << "this will be ok";


. . . но небольшая модификация меня смутила:
Код

    BYTE a = 255;
    BYTE b = 1;
    if ( (bool)*(bool*)&a == (bool)*(bool*)&b )
        std::cout << "true";
    else
        std::cout << "false"; //почему опять попадаем сюда ??

    if ( (bool)a == (bool)b )
        std::cout << "this will be ok";


Ведь, наскольно я понимаю, выражение
Код

(bool)*(bool*)&a

даёт уже приведение значения к типу bool, а не интерпретацию памяти. Но, на практике -  это не так. Что в таком случае происходит??

Это сообщение отредактировал(а) ANTON_AL - 16.7.2008, 15:29
PM MAIL   Вверх
Rififi
Дата 16.7.2008, 15:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1254
Регистрация: 9.3.2008

Репутация: 11
Всего: 36



Цитата(ANTON_AL @  16.7.2008,  15:14 Найти цитируемый пост)
//почему опять попадаем сюда ??

очевидно у компилятора другие соображения.
если посмотреть на ассемблерный листиг условия, то он выглядит так:

[nocode]
if ( (bool)*(bool*)&a == (bool)*(bool*)&b )
0055C18C  movzx       eax,byte ptr [a] 
0055C190  movzx       ecx,byte ptr  
0055C194  cmp         eax,ecx 
[/nocode]

то есть происходит именно [B]интерпретация
 памяти, даже несмотря на явный кастинг

Добавлено через 5 минут и 54 секунды
PS. как тут бишь отменить парсинг BB-кодов? что-то не нашел... ну и хрен с ними (:

Это сообщение отредактировал(а) Rififi - 16.7.2008, 15:58
PM MAIL   Вверх
mes
Дата 17.7.2008, 00:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(ANTON_AL @  16.7.2008,  13:23 Найти цитируемый пост)
Вот в этом и вопрос - как написать универсальную функцию, которая подсчитывает количество элементов с указанным значением ?
Основное требование: если в неё подать массив типа BYTE, то она должна подсчитать количество ненулевых значений ( с шаблонным параметром - bool )


Цитата(vinter @  16.7.2008,  14:07 Найти цитируемый пост)
так ты приводишь указатель, 255 от этого не станет равным true, который в свою очередь равен 1(скорее всего) 

для этого нужно перегрузить функцию сравнения, например так :
Код

template< class T >
int count( T *pSrc, int width, int height, int pitch, int step, T val , bool (cmp)(const T&, const T&))
{
    int count = 0;

    for ( int y = 0; y < height; y++ )
        for ( int x = 0; x < width; x++ )
        {
            T a = pSrc[y*pitch + x * step];
            T b = val;
            if ( cmp(a,b) )
            count++;
        }

    return count;
}

bool cmp_bool (const bool& lhs, const bool& rhs)
{
     return (lhs? 1:0) == (rhs? 1:0);
}

....

            std::cout << count<bool>( (bool*)test, 4, 4, 4, 1, true, cmp_bool );


естественно cmp_bool можно заменить на cmp<T> со специализацией под bool и дабавить ее по умолчанию в список параметров для count

Это сообщение отредактировал(а) mes - 17.7.2008, 00:22


--------------------
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1233 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.