Как сделать char * kmers из очень длинной строки C ++ - PullRequest
0 голосов
/ 26 января 2012

У меня есть строковый объект, который очень длинный, и я хотел бы сослаться на окна в нем [0, 19], [1, 20], ....., [980, 1000] как char x[20] .

Давайте назовем нашу строку foo. Я пробовал

x = &foo[i]

и итерация, но я получаю ошибку несовместимого типа, потому что &foo[i] имеет тип char *.

Как я могу сослаться на этот 20-символьный блок памяти нашей строки foo, используя char x[20]?

Если говорить более философски, в чем разница между char *x и char x[20], если более поздняя версия не обнуляется?

Одна цель - не иметь вдвое большего объема памяти, создавая совершенно новые блоки памяти для всех новых символов.

Ответы [ 4 ]

1 голос
/ 20 июля 2012

char * p - указатель на память где-то, которая должна содержать символы.Там нет конца данных подразумевается.char a[100] - это раздел из 100 символов памяти.Конец a известен компилятору для доступа к многомерным массивам и для параметров функции проверки ошибок.& a [0] или просто a (адрес элемента 0 of a) в основном совпадает с char *.

Пользователь a или p должен как-то знать длину:

1) aПараметр длины предоставляется дополнительно.Пример: sizeof(a) (в байтах).Мне также нравится использовать numof(a), который может содержать элементы вместо размера байта, добавив: #define numof(X) (sizeof(X)/sizeof(*X)) Вместо длины, вы также можете использовать другой указатель на конец, чтобы остановиться на.

2) некоторый контентили правило, которое сообщает пользователю p, когда остановиться.Пример: *p == 0 (NULL)

Это мощный источник гибкости в C / C ++ (а также опасность при неправильном использовании).


a) Изменить пользователя массива также можноограничение длины или указатель до конца, чтобы остановиться на.Вам также может понадобиться проверка нулевого завершения в случае, если последний блок меньше размера.

b) Обрабатывать данные только по одному блоку за раз.Тогда вы только новый 1 дополнительный массив из 20 символов.Или, если вы можете гарантировать, что другие потоки не будут использовать массив одновременно, вы можете временно изменить нулевое завершение:

// array is assumed to be a multiple of 20 plus 1 more for null
char * ptr = array;
while ( ptr < array + sizeof(array)-1 )
{
  char * end = ptr + 20; // we will stop here
  char save_char = *end; // save the character there
  *end = 0; // put in temporary null
  ProcessBlock( ptr ); // now null terminated !
  *end = save_char; // restore the array
  ptr = end; // end of this block is start of next
}
1 голос
/ 26 января 2012

Взгляните на класс StringRef от llvm. По сути, он просто содержит два указателя, начало и конец. Вы можете сделать что-то вроде этого, например:

std::string source = "... something really long ...";
const char * b = source.c_str();
llvm::StringRef window(b + 100, 20);

window теперь является сущностью, которая относится к части source. Вы можете вызвать begin() и end(), чтобы получить итераторы. Вы можете напечатать его как обычную строку, например:

std::cout << window;

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

0 голосов
/ 26 января 2012

Причина, по которой вы получили «ошибку несовместимого типа», заключается в том, что x и &foo[i] относятся к разным типам. Учтите это:

  • foo имеет тип char[] (то есть массив char)
  • поэтому foo[i] относится к типу char
  • поэтому &foo[i] имеет тип char* (то есть указатель на char)

Разница между char* x и char x[20] заключается в том, что в первом случае x является указателем на символ, а во втором случае это массив char. В первом случае вы можете указать указатель на любой char в памяти вашего процесса. Во втором случае x часто может вести себя как указатель, но он всегда указывает на начало массива.

Предполагая, что размер foo кратен размеру окна, вы можете перебирать окна следующим образом:

char foo[FOO_SIZE];
for (unsigned i = 0; i < FOO_SIZE; i += WINDOW_SIZE) {
    char first_char = foo[i];
    char last_char = foo[i + WINDOW_SIZE - 1]; // Warning: if foo size is not multiple of window size, this may exceed foo in the last window
}

Кроме того, ваш собственный код, вероятно, в порядке, просто удалите амперсанд из &foo[i]. Обратите внимание, что [] уже разыменовывает указатель, поэтому нет необходимости в дополнительных &.

0 голосов
/ 26 января 2012

Просто сделай

int window_size = 20;
for (size_t i = 0; i < foo.size() - window_size; ++i)
{
    const char* x = foo.data() + i;
    // Do something with x[0] to x[window_size - 1]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...