代码之家  ›  专栏  ›  技术社区  ›  JMP

带有返回垃圾的字符指针的C++类

  •  3
  • JMP  · 技术社区  · 16 年前

    我创建了一个类“Entry”来处理字典条目,但是在main()中,我创建了Entry()并尝试cout char类型的公共成员,但是我得到了垃圾。当我在debugger中查看监视列表时,我看到正在设置值,但是一旦我访问这些值,就会出现垃圾。有人能详细说明我可能遗漏了什么吗?

    #include  <iostream>
    
    using  namespace  std;
    
    class Entry
    {
        public:
                Entry(const char *line);
                char *Word;
                char *Definition;
    };
    
    Entry::Entry(const char *line)
    {
        char tmp[100];
        strcpy(tmp, line);
    
        Word = strtok(tmp, ",") + '\0';
        Definition = strtok(0,",") + '\0';
    }
    
    int  main()
    {
        Entry *e = new Entry("drink,What you need after a long day's work");
        cout << "Word: " << e->Word << endl;
        cout << "Def: " << e->Definition << endl;
        cout << endl;
    
        delete e;
        e = 0;
    
        return  0;
    }
    
    4 回复  |  直到 13 年前
        1
  •  12
  •   Paul R    6 年前

    Word Definition 两者都指向 tmp

        2
  •  4
  •   crazyscot    16 年前

    strtok()将指针返回到其输入字符串中。您正在堆栈上向它传递一个缓冲区,在Entry::Entry返回后,该缓冲区将不再有效。

        3
  •  3
  •   Fabio Ceconello    16 年前

    另一件事是你不应该把这个字符添加到指针中。我假设您想在字符串中添加一个终止符,但在C/C++中情况并非如此。实际上,您是将ASCII值(零)作为偏移量添加到指针上,这不起任何作用。如果需要终止符,则需要更改指针所指向的字符,而不是更改指针本身。但是strtok已经在找到的每一个令牌的末尾放上了终结符,不管怎样-在这种情况下没有必要这样做。

    所以,我的建议是:

    #include  <iostream>
    
    using  namespace  std;
    
    class Entry
    {
        public:
                Entry(const char *line);
                char *Word;
                char *Definition;
    
        private:
                char buffer[100];
    
    
    };
    
    Entry::Entry(const char *line)
    {
        strncpy(buffer, line, sizeof buffer);
        buffer[sizeof buffer - 1] = '\0';
    
        Word = strtok(buffer, ",");
        Definition = strtok(0,",");
    }
    
    int  main()
    {
        Entry *e = new Entry("drink,What you need after a long day's work");
        cout << "Word: " << e->Word << endl;
        cout << "Def: " << e->Definition << endl;
        cout << endl;
    
        delete e;
        e = 0;
    
        return  0;
    }
    

    我将名称从tmp改为buffer,因为它不再是临时值。我还使用strncpy来防止缓冲区溢出。行缓冲区[sizeof buffer-1]='\0';这是因为如果行大于缓冲区,则在调用后不会有终止符。

        4
  •  1
  •   Fred Larson    16 年前

    实际上,如果在你的任务范围内,我建议你放弃 char* strtok() 赞成 string , istringstream getline()

    #include <string>
    #include <sstream>
    #include <iostream>
    
    using namespace std;
    
    class Entry
    {
      public:
        Entry(const string& line);
        string Word;
        string Definition;
    };
    
    Entry::Entry(const string& line)
    {
      istringstream iss(line);
      getline(iss, Word, ',');
      getline(iss, Definition, ',');
    }
    
    int main()
    {
      Entry e = Entry("drink,What comes between \"eat\" and \"be merry\"");
      cout << "Word: " << e.Word << endl;
      cout << "Def: " << e.Definition << endl;
      cout << endl;
    
      return  0;
    }