You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用重载运算符时控制台输出文本异常的问题排查

问题:C++自定义text类输出乱码

我实现了一个带有word缓冲区的text类,通过重载+运算符追加传入的字符串。程序基本能运行,但控制台输出会出现乱码字节,无法定位问题。

我尝试过修改构造函数和重载的+运算符,分别在word缓冲区的开头和末尾添加'\0',但问题仍未解决。

原代码

#include <cstdlib>
#include <iostream>
using namespace std;

class text {
   const char *word;
   int size;
   public:
   text(int sz);
   text(const text &cpytxt);
   ~text() { delete [] word; }
   text &operator+(const char *str);
   void operator!();
   void operator--();
};

text::text(int sz = 80) {
   if(sz <= 0) {
      cout << "Error: sz <= 0" << '\n';
      exit(1);
   }

   size = sz;
   word = new char[sz];
}

text::text(const text &cpytxt) {
   if(cpytxt.size <= 0) {
      cout << "Error: cpytxt.size <= 0" << '\n';
      exit(1);
   }

   size = cpytxt.size;
   word = new char[cpytxt.size];
}

text &text::operator+(const char *str) {
   char *tmpstr = (char *) str; // Saves constant direction into non-constant direction for later usage
   char *tmpwrd = (char *) word; // Same with the object buffer
   
   int i = 0; // Creates 'i' iterator

   while(*tmpwrd) { // Sets word direction and 'i' poiting to the last empty byte
      ++tmpwrd;
      ++i;
   }

   // Assigns each char from the string to the last empty byte of word and consecutive empty bytes
   for(; i < size && *tmpstr; ++i, ++tmpwrd, ++tmpstr) { 
      if(i == size - 1) *tmpwrd = '\0';
      else *tmpwrd = *tmpstr;
   }

   return *this; // Returns invoking object
}

void text::operator!() { 
   cout << word;
}

void text::operator--() {
   char *tmpwrd = (char *) word;

   for(int i = 0; i < size; ++i, ++tmpwrd) {
      *tmpwrd = '\0';
   }
}

int main() {
   
   text myTxt(1000);

   myTxt + "Hello World!" + " This is an example!";
   !myTxt;
   --myTxt;
   myTxt + "GOODBYE!";
   !myTxt;
   --myTxt;

   system("pause");
   return 0;
}

问题根源及修复方案

1. 缓冲区未初始化导致乱码

构造函数中new char[sz]分配的内存是未初始化的,里面是随机垃圾值。第一次调用operator+时,while(*tmpwrd)会一直读取随机内存,直到遇到某个恰好是'\0'的字节,这会导致越界访问、写入位置错误,最终输出乱码。

修复:构造时用值初始化语法将缓冲区设为全'\0':

text::text(int sz = 80) {
   if(sz <= 0) {
      cout << "Error: sz <= 0" << '\n';
      exit(1);
   }

   size = sz;
   // 值初始化自动将所有字节设为0
   word = new char[sz]();
}

2. 拷贝构造函数未复制内容

当前拷贝构造函数只分配了内存,没有复制原对象的word内容,若后续用到拷贝构造(比如对象赋值、传参)会导致数据丢失或错误。

修复:添加内容复制逻辑:

#include <cstring> // 需包含strncpy的头文件

text::text(const text &cpytxt) {
   if(cpytxt.size <= 0) {
      cout << "Error: cpytxt.size <= 0" << '\n';
      exit(1);
   }

   size = cpytxt.size;
   word = new char[size]();
   // 复制原对象内容,预留一个位置给终止符
   strncpy((char*)word, cpytxt.word, size-1);
}

3. operator+逻辑缺陷

原operator+中,当填充到size-1位置时直接设'\0',但如果字符串未写完会截断;且循环结束后没有确保缓冲区末尾一定有'\0',可能导致输出时读取到垃圾值。

修复:调整逻辑,确保无论是否填满都添加终止符:

text &text::operator+(const char *str) {
   if(!str) return *this; // 空字符串直接返回

   char *tmpwrd = (char *) word;
   const char *tmpstr = str; // 无需强制转非const,仅读取

   // 定位到当前字符串末尾
   while(*tmpwrd) {
      ++tmpwrd;
   }

   // 计算剩余可写入空间(留一个位置给'\0')
   int remaining = size - (tmpwrd - (char*)word) - 1;
   if(remaining <= 0) return *this;

   // 复制字符串内容
   while(remaining > 0 && *tmpstr) {
      *tmpwrd++ = *tmpstr++;
      remaining--;
   }
   // 强制添加终止符
   *tmpwrd = '\0';

   return *this;
}

4. 优化清空操作

原operator--用循环清空缓冲区,可替换为更高效的memset:

void text::operator--() {
   char *tmpwrd = (char *) word;
   memset(tmpwrd, 0, size);
}

修复后完整代码

#include <cstdlib>
#include <iostream>
#include <cstring>
using namespace std;

class text {
   const char *word;
   int size;
   public:
   text(int sz = 80);
   text(const text &cpytxt);
   ~text() { delete [] word; }
   text &operator+(const char *str);
   void operator!();
   void operator--();
};

text::text(int sz) {
   if(sz <= 0) {
      cout << "Error: sz <= 0" << '\n';
      exit(1);
   }

   size = sz;
   word = new char[sz]();
}

text::text(const text &cpytxt) {
   if(cpytxt.size <= 0) {
      cout << "Error: cpytxt.size <= 0" << '\n';
      exit(1);
   }

   size = cpytxt.size;
   word = new char[size]();
   strncpy((char*)word, cpytxt.word, size-1);
}

text &text::operator+(const char *str) {
   if(!str) return *this;

   char *tmpwrd = (char *) word;
   const char *tmpstr = str;

   while(*tmpwrd) {
      ++tmpwrd;
   }

   int remaining = size - (tmpwrd - (char*)word) - 1;
   if(remaining <= 0) return *this;

   while(remaining > 0 && *tmpstr) {
      *tmpwrd++ = *tmpstr++;
      remaining--;
   }
   *tmpwrd = '\0';

   return *this;
}

void text::operator!() { 
   cout << word << endl;
}

void text::operator--() {
   char *tmpwrd = (char *) word;
   memset(tmpwrd, 0, size);
}

int main() {
   
   text myTxt(1000);

   myTxt + "Hello World!" + " This is an example!";
   !myTxt;
   --myTxt;
   myTxt + "GOODBYE!";
   !myTxt;
   --myTxt;

   system("pause");
   return 0;
}

内容的提问来源于stack exchange,提问作者Tobías Milano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 23:43:11