坏指针? - C++

发布于 2024-08-20 15:11:38 字数 2053 浏览 6 评论 0原文

我正在为 C++ 作业编写一个使用指针的字符串标记化程序。然而,当我跑步时调试一下,它说我的指针pStart无效。我有一种感觉,我的问题出在我的参数构造函数中,我在下面包含了构造函数和对象创建。

如果您能告诉我为什么在我调试它时说 pStart 是一个坏指针,我将不胜感激。

谢谢!

StringTokenizer::StringTokenizer(char* pArray, char d)
{
pStart = pArray;
delim = d;
}

// create a tokenizer object, pass in the char array
// and a space character for the delimiter
StringTokenizer tk( "A test char array", ' ' );

完整的 stringtokenizer.cpp:

#include "stringtokenizer.h"
#include <iostream>
using namespace std;

StringTokenizer::StringTokenizer(void)
{
pStart = NULL;
delim = 'n';
}

StringTokenizer::StringTokenizer(const char* pArray, char d)
{
pStart = pArray;
delim = d;
}

char* StringTokenizer::Next(void)
{
char* pNextWord = NULL;

while (pStart != NULL)
{
    if (*pStart == delim)
    {
        *pStart = '\0';
        pStart++;
        pNextWord = pStart;

        return pNextWord;
    }
    else
    {
        pStart++;
    }
}
    return pNextWord;
}

函数 Next 应该返回指向 char 数组中下一个单词的指针。目前尚未完成。 :)

完整的 stringtokenizer.h:

#pragma once

class StringTokenizer
{
public:
StringTokenizer(void);
StringTokenizer(const char*, char);
char* Next(void);
~StringTokenizer(void);
private:
char* pStart;
char delim;
};

完整的 main.cpp:

const int CHAR_ARRAY_CAPACITY = 128;
const int CHAR_ARRAY_CAPCITY_MINUS_ONE = 127;

// create a place to hold the user's input
// and a char pointer to use with the next( ) function
char words[CHAR_ARRAY_CAPACITY];
char* nextWord;

cout << "\nString Tokenizer Project";
cout << "\nyour name\n\n";
cout << "Enter in a short string of words:";
cin.getline ( words, CHAR_ARRAY_CAPCITY_MINUS_ONE );

// create a tokenizer object, pass in the char array
// and a space character for the delimiter
StringTokenizer tk( words, ' ' );

// this loop will display the tokens
while ( ( nextWord = tk.Next ( ) ) != NULL )
{
    cout << nextWord << endl;
}


system("PAUSE");
return 0;

I'm writing a string tokenization program for a homework assignment in C++, that uses pointers. However, when I run & debug it, it says that my pointer pStart, is invalid. I have a feeling that my problem resides in my param'ed constructor, I've included both the constructor and the object creation below.

I would appreciate it if you might tell me why it says that pStart is a bad pointer when I debug it.

Thanks!

StringTokenizer::StringTokenizer(char* pArray, char d)
{
pStart = pArray;
delim = d;
}

// create a tokenizer object, pass in the char array
// and a space character for the delimiter
StringTokenizer tk( "A test char array", ' ' );

Full stringtokenizer.cpp:

#include "stringtokenizer.h"
#include <iostream>
using namespace std;

StringTokenizer::StringTokenizer(void)
{
pStart = NULL;
delim = 'n';
}

StringTokenizer::StringTokenizer(const char* pArray, char d)
{
pStart = pArray;
delim = d;
}

char* StringTokenizer::Next(void)
{
char* pNextWord = NULL;

while (pStart != NULL)
{
    if (*pStart == delim)
    {
        *pStart = '\0';
        pStart++;
        pNextWord = pStart;

        return pNextWord;
    }
    else
    {
        pStart++;
    }
}
    return pNextWord;
}

The function Next is supossed to return a pointer to the next word in the char array. It's currently not finished. :)

Full stringtokenizer.h:

#pragma once

class StringTokenizer
{
public:
StringTokenizer(void);
StringTokenizer(const char*, char);
char* Next(void);
~StringTokenizer(void);
private:
char* pStart;
char delim;
};

Full main.cpp:

const int CHAR_ARRAY_CAPACITY = 128;
const int CHAR_ARRAY_CAPCITY_MINUS_ONE = 127;

// create a place to hold the user's input
// and a char pointer to use with the next( ) function
char words[CHAR_ARRAY_CAPACITY];
char* nextWord;

cout << "\nString Tokenizer Project";
cout << "\nyour name\n\n";
cout << "Enter in a short string of words:";
cin.getline ( words, CHAR_ARRAY_CAPCITY_MINUS_ONE );

// create a tokenizer object, pass in the char array
// and a space character for the delimiter
StringTokenizer tk( words, ' ' );

// this loop will display the tokens
while ( ( nextWord = tk.Next ( ) ) != NULL )
{
    cout << nextWord << endl;
}


system("PAUSE");
return 0;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

人间☆小暴躁 2024-08-27 15:11:38

您无法在分词器中修改 pStart,因为 C 和 C++ 中的文字字符串不可修改,它的类型为 const char *。当您在构造函数中进行赋值时

pStart = pArray;

pStart 现在指向不可修改的内存。这很可能是你的问题。如果不是这种情况,您将需要发布更多代码。

编辑:查看您的编辑后,您似乎已将代码更改为使用数组。那挺好的。我没有太详细地查看您的代码,但至少有一个错误:

while (pStart != NULL)

应该是:

while (pStart != NULL && *pStart)

这是因为您想在遇到终止 '\0' 时停止循环你的字符串。

我不知道为什么你在 C++ 中使用 C 风格的字符串。这是你家庭作业中的要求吗?

You can't modify pStart in your tokenizer, because a literal string in C and C++ is not modifiable, it has a type const char *. When you do the assignment

pStart = pArray;

in your constructor, pStart is now pointing to a non-modifiable memory. Most likely that is your problem. You will need to post more code if that's not the case.

Edit: After looking at your edit, looks like you have changed your code to use an array. That's good. I haven't looked at your code in too much detail, but there is at least one error:

while (pStart != NULL)

should be:

while (pStart != NULL && *pStart)

This is because you want to stop your loop when you hit the terminating '\0' in your string.

I am not sure why you're using C-style strings in C++. Is this a requirement in your homework?

苍风燃霜 2024-08-27 15:11:38

更改

StringTokenizer::StringTokenizer(char* pArray, char d)

StringTokenizer::StringTokenizer(const char * pArray, char d)

字符串文字始终是 const char * const 变量,并且由于 C++ 自动将非 const 转换为 const,因此它无法将 const 转换为非 const。

您还可以创建不同的构造函数,但我认为您不需要它,只要您只读取 pArray 字符串即可。

你可以使用这样的东西:

TokenList& StringTokenizer::StringTokenizer(const char* pArray, char d){
  TokenList lst();
  size_t i=0;
  char buffer[100]; //hardcoded limit, just an example, you should make it grow dinamically, or just use a std::string
  while((*pArray)){
    if(*pArray == d){
      buffer[i] = 0; //string ending character, 0 = '\0';
      lst.add(buffer);
      i=0;
    }
    pArray++;
  }
  //Last token in the input string won't be ended by the separator, but with a '\0'.
  buffer[i] = 0;
  lst.add(buffer);

  return lst;
}

Change

StringTokenizer::StringTokenizer(char* pArray, char d)

to

StringTokenizer::StringTokenizer(const char * pArray, char d)

A string literal is always a const char * const variable, and since C++ automatically casts a non const to const, it can't cast a const to non const.

You can also make different constructors, but I don't think you'll need it, as long as you just read the pArray string.

You could use something like this:

TokenList& StringTokenizer::StringTokenizer(const char* pArray, char d){
  TokenList lst();
  size_t i=0;
  char buffer[100]; //hardcoded limit, just an example, you should make it grow dinamically, or just use a std::string
  while((*pArray)){
    if(*pArray == d){
      buffer[i] = 0; //string ending character, 0 = '\0';
      lst.add(buffer);
      i=0;
    }
    pArray++;
  }
  //Last token in the input string won't be ended by the separator, but with a '\0'.
  buffer[i] = 0;
  lst.add(buffer);

  return lst;
}
如何视而不见 2024-08-27 15:11:38

将 StringTokenizer 类中的 pStart 从 char* 更改为 const char*,并对构造函数进行相同的更改。

Change pStart in the StringTokenizer class from char* to const char*, and make the same change to the constructor.

醉南桥 2024-08-27 15:11:38

在我看来,您应该更改 StringTokenizer 的构造函数和析构函数:

StringTokenizer::StringTokenizer(char* pArray, char d)
{
    pStart = str = strdup( pArray );
    delim = d;
}

StringTokenizer::~StringTokenizer()
{
    free( str );
}

现在您可以按照您正在使用的方式使用 pStart:修改字符串,添加零以标记单词等。您只需要添加一个“char * str” StringTokenizer 的私有属性。

这里的技巧是,您正在创建自己的字符串副本,因此您可以以任何您想要的方式进行操作,前提是您在析构函数中释放它。唯一的缺点是您需要内存来存储副本(因此每个字符串需要两倍的内存)。

您的解决方案不起作用的原因是文字是或可以存储在只读内存中,因此它们被正确标记为 const char*,“不可能”写入它们。

请注意,在 C++ 中,您可以使用 std::string ,这要多得多比普通的 C 字符串实用。

In my opinion, you should change the constructor and destructor of StringTokenizer:

StringTokenizer::StringTokenizer(char* pArray, char d)
{
    pStart = str = strdup( pArray );
    delim = d;
}

StringTokenizer::~StringTokenizer()
{
    free( str );
}

Now you can use pStart in the way you are using it: modifying the string, putting zeroes in order to mark words, etc. You do only need to add a "char * str" private attribute to StringTokenizer.

The trick here is that you are creating your own copy of the string, thus you can manipulate anyway you want, provided you free it in the destructor. The only downside is that you need memory in order to store the copy (so you need twice memory for each string).

The reason your solution didn't work is that literals are or can be stored in read-only memory, so they are correctly marked as const char*, being "impossible" to write to them.

Note that in C++ you have std::string available, which is much more practical than plain C strings.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文