使用char指针在单词中拆分句子

时间:2017-04-22 13:26:48

标签: c++ pointers char

我正在开发一个将句子拆分为2D指针的系统。

我不想使用任何类型的库或其他类似字符串的方式,因为我想练习指针并学习它们。

char** sscanf(char* hstring)
{
    int count = 0;
    char* current = hstring;
    while (*current)
    {
        if (*current == ' ')
        {
            count++;
        }
        while (*current == ' ')
        {
            current++;
        }
        if (*current)
            break;
        current++;
    }
    char** result = new char*[count];
    current = hstring;
    char* nstr = new char;
    int c = 0, i = 0;
    while (*current)
    {
        if (!*current) break;
        cout << "t1";
        if (*current == ' ')
        {
            *(++result) = nstr;

            nstr = nullptr;
            nstr = new char;
        }
        cout << "t2";
        while (*current != '/0' && *current == ' ')
        {
            current++;
        }
        cout << "t3";
        while (*current != '/0' && *current != ' ')
        {
            if (!*current) break;
            *(++nstr) = *current;
            current++;
        }
        cout << "t4";
        *nstr = '/0';
        cout << "t5";
    }
    return result;
}

但它很奇怪,有时会将我重定向到

static size_t __CLRCALL_OR_CDECL length(_In_z_ const _Elem * const _First) _NOEXCEPT // strengthened
        {   // find length of null-terminated string
        return (_CSTD strlen(_First));
        }

有错误:访问违规,其他时候,选择一个随机行并称之为Acces Breakout(对不起,如果拼写错误)

我想要的不是简单地修复我的代码,我想要一些解释,因为我想学习这些东西。

1 个答案:

答案 0 :(得分:3)

首先,一些建议

我知道你正在将这个功能作为练习,但是作为C ++,我想警告你new char*[count]之类的事情是不良做法,这就是为什么{{1} }或std::vector已创建。

您似乎对动态分配的工作方式感到困惑。语句std::array将在堆内存中只创建一个字节(char),并且不保证与它相邻。这意味着char* nstr = new char;是一个“无效”操作,我的意思是,它将++nstr指向分配的一个后的下一个字节,这可能是一些随机的无效位置。

您的代码中还有很多其他危险的操作,比如多次调用nstr(保留内存)而在您没有时调用new更长时间使用保留的内存(也就是内存泄漏)。话虽如此,我强烈建议您研究这个主题,例如从ISO C++ FAQ on memory management开始。

此外,在深入研究指针和动态分配之前,您应该更加容易使用语句和流控制。我这样说是因为我看到了一些明显的误解,比如:

delete

while (*current) { if (!*current) break; ... } 语句中的检查肯定是错误的,因为if检查在它之前执行并保证相反的条件为真。这意味着这个while永远不会被评估为真,而且它完全没用。

另一个评论是:不要将您的功能命名为标准库if已经被采用,选择另一个(更有意义的)。这将为您节省一些令人头疼的问题;用于正确命名自己的功能。

指导性解决方案

我心情很好,所以我会在这里做一些步骤。无论如何,如果有人正在寻找优化且随时可用的解决方案,请参阅Split a String in C++

0。定义步骤

阅读你的代码,我可以猜到你想要的一些步骤:

sscanf

为什么不一个一个地尝试一下呢? (注意函数和参数的名称,在我看来更清楚)。

1。计算单词

您可以从一个简单的main()开始,测试您的解决方案。这是我的(对不起,我不能只适应你的)。对于那些优化上瘾的人来说,这不是一个优化的解决方案,而是一个简单的OP片段。

char** split_string(char* sentence)
{
    // Count the number of words in the sentence
    // Allocate memory for the answer (a 2D buffer)
    // Write each word in the output
}

测试它,确保你理解它的工作原理。现在,您可以进入下一步。

2。分配缓冲区

好吧,你想为每个单词分配一个缓冲区,所以我们需要知道每个单词的大小(我不会讨论这是否是一个很好的解决分句问题的方法..)。这不是在前一步计算的,所以我们现在可以这样做。

// I'll be using this header and namespace on the next snippets too.
#include <iostream>
using namespace std;

int main()
{
    char sentence[] = " This is    my sentence  ";

    int n_words = 0;
    char *p = sentence;
    bool was_space = true; // see logic below

    // Reading the whole sentence
    while (*p) {
        // Check if it's a space and advance pointer
        bool is_space = (*p++ == ' ');
        if (was_space && !is_space)
            n_words++;        // count as word a 'rising edge'
        was_space = is_space;
    }

    cout << n_words;
}

请注意,我正在删除main()中分配的缓冲区。当您将此逻辑移动到您的函数时,此解除分配将由函数的调用者执行,因为它可能会在删除之前使用缓冲区。

3。将每个单词分配给其缓冲区

我认为你明白了。分配单词并将逻辑移动到分离的函数。如果您仍有问题,请使用Minimal, Complete, and Verifiable example更新您的问题。

我知道这是一个Q&amp; A论坛,但我认为这已经是OP和其他可能通过这里的人的健康答案。如果我的回答不同,请告诉我。