我正在开发一个将句子拆分为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(对不起,如果拼写错误)
我想要的不是简单地修复我的代码,我想要一些解释,因为我想学习这些东西。
答案 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++。
阅读你的代码,我可以猜到你想要的一些步骤:
sscanf
为什么不一个一个地尝试一下呢? (注意函数和参数的名称,在我看来更清楚)。
您可以从一个简单的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
}
测试它,确保你理解它的工作原理。现在,您可以进入下一步。
好吧,你想为每个单词分配一个缓冲区,所以我们需要知道每个单词的大小(我不会讨论这是否是一个很好的解决分句问题的方法..)。这不是在前一步计算的,所以我们现在可以这样做。
// 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()中分配的缓冲区。当您将此逻辑移动到您的函数时,此解除分配将由函数的调用者执行,因为它可能会在删除之前使用缓冲区。
我认为你明白了。分配单词并将逻辑移动到分离的函数。如果您仍有问题,请使用Minimal, Complete, and Verifiable example更新您的问题。
我知道这是一个Q&amp; A论坛,但我认为这已经是OP和其他可能通过这里的人的健康答案。如果我的回答不同,请告诉我。