如何从超长的C++字符串中生成char*kmers

How to make char* kmers from an extremely long C++ string

本文关键字:char kmers 字符串 C++      更新时间:2023-10-16

我有一个非常长的字符串对象,我想引用其中的窗口[0,19],[1,20]。。。。。,[9801000]作为char x[20]

让我们把我们的字符串称为foo。我试过

x = &foo[i]

和迭代,但我得到了一个不兼容的类型错误,因为&foo[i]的类型是char *

如何使用char x[20]引用字符串foo的20个字符的内存块?

更哲学地说,如果char *xchar 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* xchar 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]中删除"与"号即可。请注意,[]已经取消了对指针的引用,因此不需要额外的&