如何从超长的C++字符串中生成char*kmers
How to make char* kmers from an extremely long C++ string
我有一个非常长的字符串对象,我想引用其中的窗口[0,19],[1,20]。。。。。,[9801000]作为char x[20]
。
让我们把我们的字符串称为foo
。我试过
x = &foo[i]
和迭代,但我得到了一个不兼容的类型错误,因为&foo[i]
的类型是char *
。
如何使用char x[20]
引用字符串foo的20个字符的内存块?
更哲学地说,如果char *x
和char x[20]
不是null终止的,那么两者之间有什么区别?
一个目标是不必通过为所有新字符创建全新的内存块来获得2倍的内存需求。
看看llvm中的StringRef类。从本质上讲,它只包含两个指针,一个开始,一个结束。你可以这样做,例如:
std::string source = "... something really long ...";
const char * b = source.c_str();
llvm::StringRef window(b + 100, 20);
CCD_ 8现在是指代CCD_ 9的一部分的实体。您可以在上面调用begin()
和end()
来获得迭代器。你可以像打印普通字符串一样打印它,比如:
std::cout << window;
正如您在文档中看到的,它还附带了各种其他常见的字符串操作。
char * p
是指向应该包含字符的内存的指针。数据没有尽头。char a[100]
是一个100个字符的存储器部分。编译器可以访问多维数组并对函数参数进行错误检查。&a[0]或只是a(a的元素0的地址)基本上与char*相同。
a或p的用户必须以某种方式知道长度:
1) 另外提供的长度参数。例如:sizeof(a)
(以字节为单位)。我还喜欢使用numof(a)
,它可以是元素,而不是字节大小,添加:#define numof(X) (sizeof(X)/sizeof(*X))
您也可以使用另一个指向末尾的指针来停止。
2) 告诉p用户何时停止的某些内容或规则。例如:*p == 0
(NULL)
这是C/C++中灵活性的强大来源(如果误用,也会带来危险)。
a) 将数组的用户更改为也有长度限制或指针指向要停止的末尾。如果最后一个块尺寸过小,您可能还需要进行空终止检查。
b) 一次只处理一个数据块。然后您只需要添加1个额外的20个字符的数组。或者,如果您可以确保没有其他线程同时使用该数组,则可以临时更改null终止:
// 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
}
只需进行
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]
}
收到"不兼容类型错误"的原因是x
和&foo[i]
的类型不同。考虑一下:
foo
的类型为char[]
(即char
的阵列)- 因此
foo[i]
属于char
型 - 因此
&foo[i]
是char*
类型(即指向char
的指针)
char* x
和char x[20]
之间的区别在于,在第一种情况下,x
是指向char的指针,在第二种情况下是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]
中删除"与"号即可。请注意,[]
已经取消了对指针的引用,因此不需要额外的&
。