【问题标题】:how to read a particular string from a buffer如何从缓冲区中读取特定字符串
【发布时间】:2013-07-23 12:58:34
【问题描述】:

我有一个缓冲区

char buffer[size];

我用来存储流的文件内容(这里假设是 pStream)

HRESULT hr = pStream->Read(buffer, size, &cbRead );

现在我在缓冲区中有这个流的所有内容,它的大小(假设这里的大小)。现在我知道我有两个字符串

"<!doctortype html" and ".html>" 

它们存在于这个缓冲区的存储内容中的某个地方(我们不知道它们的位置),我只想从该位置存储缓冲区的内容

"<!doctortype html" to another string ".html>"  

进入另一个缓冲区2[SizeWeDontKnow]。

怎么做??? (实际上这两个位置的内容是 html 文件的内容,我想存储此缓冲区中存在的仅 html 文件的内容)。任何想法如何做到这一点??

【问题讨论】:

    标签: c++ c arrays string buffer


    【解决方案1】:

    您可以使用 strnstr 函数在缓冲区中找到正确的位置。找到开始和结束标记后,您可以使用 strncpy 提取中间的文本,如果性能有问题,也可以使用它。
    您可以根据标签的位置和第一个标签的长度来计算所需的大小
    nLength = nPosEnd - nPosStart - nStartTagLength

    【讨论】:

    • Visual c++ 是否支持 strnstr 函数,如果您知道吗?什么是 nStartTagLength ?据我了解,nLength 是总 html 内容的大小,而 nPosStart="" 我们只需要这个为什么你使用 nStartTagLength ???
    • visual c++ 没有 strnstr,但是如果您不确定 Read-function 是否给您一个以零结尾的字符串,您可以自己将终端零放入其中:char buffer[size+1]; ZeroMemory(buffer,size+1);nPosStart 和nPosEnd 是开始标签“”的位置。 nStartTagLength 是“
    • 那么你知道 Visual c++ 的等效函数吗?你认为我可以在这里使用 strtok() 来完成它吗? - while (pch != NULL) { pch = strtok (NULL, "!doctortype html" return 0; } 我能用这个得到 "!doctortype html" 的位置吗?
    • 如果缓冲区为零终止,您可以使用 strstr。如果不是,您可以将其设为零终止,就像我在之前的评论中解释的那样。
    • 查找 strstr 的 c++ 参考。它不像 strnstr 那样采用 size 参数。使用工具前请先学习。
    【解决方案2】:

    寻找 C/C++ 的 HTML 解析器。

    另一种方法是从缓冲区的开头获取一个字符指针,然后检查那里的每个字符。看看是否符合你的要求。

    【讨论】:

    • 我对第二个想法很感兴趣,但你能告诉我,通过从头开始做字符指针,我可以一次只比较一个字符,但我必须比较一个完整的字符串,它是大小等于 **"
    • &amp;buffer 是指向缓冲区的指针。现在创建另一个字符指针char *b = &amp;buffer。现在 b 指向缓冲区的开头,您可以移动它而不会丢失缓冲区。现在,如果缓冲区中的第一个字符是'*b 是'
    【解决方案3】:

    如果这是在您的应用程序中对 HTML 代码进行操作的唯一操作,那么您可以使用我在下面提供的解决方案(您也可以在线测试它 - here)。但是,如果您要进行一些更复杂的解析,那么我建议使用一些外部库。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    int main()
    {
        const char* beforePrefix = "asdfasdfasdfasdf";
        const char* prefix = "<!doctortype html";
        const char* suffix = ".html>";
        const char* postSuffix = "asdasdasd";
    
        unsigned size = 1024;
        char buf[size];
        sprintf(buf, "%s%sTHE STRING YOU WANT TO GET%s%s", beforePrefix, prefix, suffix, postSuffix);
    
        cout << "Before: " << buf << endl;
    
        const char* firstOccurenceOfPrefixPtr = strstr(buf, prefix);
        const char* firstOccurenceOfSuffixPtr = strstr(buf, suffix);
    
        if (firstOccurenceOfPrefixPtr && firstOccurenceOfSuffixPtr)
        {
            unsigned textLen = (unsigned)(firstOccurenceOfSuffixPtr - firstOccurenceOfPrefixPtr - strlen(prefix));
            char newBuf[size];
            strncpy(newBuf, firstOccurenceOfPrefixPtr + strlen(prefix), textLen);
            newBuf[textLen] = 0;
    
            cout << "After: " << newBuf << endl;
        }
    
        return 0;
    }
    

    编辑 我现在明白了:)。您应该使用strstr 来查找prefix 的第一次出现。我编辑了上面的代码,并更新了link

    【讨论】:

    • 在不知道前缀和后缀位置的情况下,我无法获取它们之间的数据,因此“您想要获取的字符串”是不可能的,我认为您仍然无法理解我的问题。跨度>
    • 是的,你是对的,我错过了这个细节。我刚刚更新了答案:)
    • 那么你知道在 Visual c++ 中获取位置吗?在 cwe 中可以使用 strnstr 但这里不行..有什么想法吗??
    • 代码还是一样的。 yourTextLen 应该这样计算:int nPosStart = strstr(buf,prefix) - buf; int nPosEnd = strstr(buf,suffix) - buf; int yourTextLen = nPosEnd - nPosStart - strlen(prefix);
    • 谢谢。在之前的编辑中,我只更新了链接,现在代码也更新了。
    【解决方案4】:

    你仅限于使用 C,还是可以使用 C++?

    在 C 库参考中有很多有用的方法来标记字符串和比较匹配项 (string.h):

    http://www.cplusplus.com/reference/cstring/

    使用 C++ 我会执行以下操作(使用代码中的缓冲区和大小变量):

        // copy char array to std::string
        std::string text(buffer, buffer + size);
    
        // define what we're looking for
        std::string begin_text("<!doctortype html");
        std::string end_text(".html>");
    
        // find the start and end of the text we need to extract
        size_t begin_pos = text.find(begin_text) + begin_text.length();
        size_t end_pos = text.find(end_text);
    
        // create a substring from the positions
        std::string extract = text.substr(begin_pos,end_pos);
    
        // test that we got the extract
        std::cout << extract << std::endl;
    

    如果您需要 C 字符串兼容性,您可以使用:

    char* tmp =  extract.c_str();
    

    【讨论】:

    • 我正在使用 Visual C++。你认为 strtok 对我有好处吗,因为我必须搜索“”的位置,然后存储它们之间的内容。你有什么建议?
    • 我已经用我使用 g++ 编译器测试过的 C++ 示例更新了我的答案:g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-3)。让我知道它是否适合你
    • 很高兴你得到了答案,非常感谢,西蒙。
    • 如果你想看到你可以去这个链接我已经写了解决方案来找到包含特定文件“.html”在缓冲区/流stackoverflow.com/questions/17920081/…中的文件,它可能对你有用未来
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-26
    • 1970-01-01
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多