Использование статической строки с вектором - PullRequest
0 голосов
/ 29 января 2011

Моя история с программированием на C и CPython. Пожалуйста, потерпите меня здесь.

Чтобы помочь мне выучить C ++, я конвертирую одну из моих старых программ на C в ООП C ++, но она работает не так, как я хочу, чтобы она работала. Меня не волнует скорость. Я просто забочусь об обучении.

Вот мой старый C-код, который я хочу поместить в класс Checksum:

    //This is the standard CRC32 implementation
    //"rollingChecksum" is used so the caller can maintain the current 
    //checksum between function calls
    unsigned int CalculateChecksum(unsigned char* eachBlock, int* sbox, long lengthOfBlock, unsigned int rollingChecksum)
    {
       int IndexLookup;
       int blockPos;

       for(blockPos = 0; blockPos < lengthOfBlock; blockPos++)
       {
         IndexLookup = (rollingChecksum >> 0x18) ^ eachBlock[blockPos];
         rollingChecksum = (rollingChecksum << 0x08) ^ sbox[IndexLookup];
       }
       return rollingChecksum;
    }

Итак, вот как я перевел это на код C ++:

 void Checksum::UpdateStream(std::vector<unsigned char> binaryData)
 {
   unsigned int indexLookup;
   unsigned int blockPos;

   for(blockPos = 0; blockPos < binaryData.size(); blockPos++)
   {
      indexLookup = (this->checksum >> 0x18) ^ binaryData[blockPos];
      this->checksum = (this->checksum << 0x08) ^ this->sbox[indexLookup];
   }
 }

Но тогда, когда я пытаюсь использовать это:

int main(int argc, char* argv[])
{
 Checksum Test;
 Test.UpdateStream("foo bar foobar");
 std::cout << Test.getChecksum() << std::endl;
}

Я получаю эту ошибку:

1>main.cpp(7) : error C2664: 'Checksum::UpdateStream' : cannot convert parameter 1 from 'const char [15]' to 'std::vector<_Ty>'
1>        with
1>        [
1>            _Ty=unsigned char
1>        ]
1>        No constructor could take the source type, or constructor overload resolution was ambiguous

Я решил использовать вышеупомянутый векторный контейнер вместо строкового класса из-за , как этот вопрос оказался в StackOverflow и потому что я хочу использовать двоичные данные здесь.

ЖЕЛАЕМЫЙ РЕЗУЛЬТАТ: Как я могу передать и строки, и двоичные данные этому методу для вычисления его контрольной суммы? Нужно ли перегрузить его или ввести строку в main? Я полностью потерян.

Ответы [ 4 ]

3 голосов
/ 29 января 2011

Вы можете скопировать содержимое массива char в вектор, используя std::copy:

std::vector< char > vector;
char str[] = "foo bar foobar";
vector.resize( sizeof(str)-1 ); // thanks to Alf (see comments)
std::copy( str, str+sizeof(str)-1, vector.begin() );

или даже лучше, используя std::vector конструктор:

char str[] = "foo bar foobar";
std::vector< char > vector( str, str+sizeof(str)-1 );

Обратите внимание, что этот код будет копировать всю строку , но завершающую \0 (снова, см. Комментарии для более подробной информации).

1 голос
/ 29 января 2011

Ваш класс контрольной суммы обрабатывает необработанные байтовые данные, которые могут поступать откуда угодно, поэтому базовый интерфейс не должен навязывать преобразование, например, в. std::vector.

т.е. unsigned char const* формальный тип аргумента исходного кода на C был и в порядке.

Однако вы можете предоставить оболочки более высокого уровня для распространенных типов вызывающих абонентов, таких как строковый литерал, std::vector, назовите его.

Если вы абсолютно хотите иметь std::vector в качестве формального типа аргумента для фундаментальной функции, то вы можете скопировать строковый литерал в нее следующим образом:

char const  s[] = "blah blah";
std::vector<unsigned char> const v( s, s + strlen( s ) );

Приветствия & hth.,

0 голосов
/ 29 января 2011

В C ++ строковый литерал в этом контексте преобразуется в указатель на первый символ, и не существует неявного конструктора, делающего вектор из указателя на символ.Также unsigned char и char являются различными типами, и, хотя между ними существуют неявные правила преобразования, между указателем на неподписанный символ и указателем на символ не существует.

Мое предложение не пытатьсяизучать C ++, экспериментируя, потому что C ++ - сложный язык с долгой историей эволюции ... он был разработан многими разными умами и даже формальными комитетами.Во многих местах C ++ далеко не интуитивен или логичен, потому что некоторые правила являются результатом эволюции, эффекта комитета или обратной совместимости с вещами, которых больше не существует.

Добавьте к этой проблеме, что когда вы делаетеошибка в C ++: вы легко получаете демоны UB вместо ангелов ошибок времени выполнения, и вы поймете, что экспериментирование - это просто неправильный путь к C ++.Независимо от того, насколько умным может быть кто-то, нет никакого способа сделать вывод об истории, используя логические рассуждения.История должна быть изучена.

Сделайте себе одолжение, возьмите «Язык программирования C ++» и прочитайте его от начала до конца: есть много вещей, которые для человека с сильным опытом в Си будет легкопонять, как только вы поместите их в рамки и контекст.Другие книги, которые мне очень понравились, и которые, по мнению IMO, также легко читаются, это "Часто задаваемые вопросы по C ++" Маршалла Клайна и серия "Effective" от Скотта Мейерса.

C ++ - хороший язык, но легко может стать вашим худшим кошмаромесли подойти к нему не с той стороны.

0 голосов
/ 29 января 2011

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

std::string tmp = "foo bar foobar"
Test.UpdateStream(std::vector<unsigned char>(tmp.begin(), tmp.end()));

Вы также можете обновить свою подпись UpdateStream, чтобы использовать (const std::vector<unsigned char>& binaryData), чтобы избежать копирования, поскольку вам не нужно изменять его.

Чтобы сократить код, вы можете предоставить перегрузку UpdateStream для строки:

void Checksum::UpdateStream(const std::string& str) {
    UpdateStream(std::vector<unsigned char>(str.begin(), str.end()));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...