【问题标题】:Read CString from buffer with unknown length?从长度未知的缓冲区中读取 CString?
【发布时间】:2013-07-23 07:46:03
【问题描述】:

假设我有一个文件。我将所有字节读入一个无符号字符缓冲区。从那里我试图在不知道它的长度的情况下读取一个 c 字符串(以空结尾)。

我尝试了以下方法:

char* Stream::ReadCString()
{
    char str[0x10000];
    int len = 0;
    char* pos = (char*)(this->buffer[this->position]);
    while(*pos != 0)
        str[len++] = *pos++;
    this->position += len+ 1;
    return str;
}

我认为我可以在遍历时填充 str 数组中的每个 char,检查 char 是否为空终止。这是行不通的。有什么帮助吗?

this->buffer = 字节数组
this->position = 在数组中的位置

还有其他方法可以做到这一点吗?我想我可以通过实际缓冲区的地址来运行它: str[len++] = *(char*)(this->buffer[this->position++])?

更新: 我的新功能:

char* Stream::ReadCString()
{
    this->AdvPosition(strlen((char*)&(this->buffer[this->position])) + 1);
    return (char*)&(this->buffer[this->position]);
}

并调用它:

printf( "String: %s\n", s.ReadCString()); //tried casting to char* as well just outputs blank string

示例文件:

【问题讨论】:

  • 你正在尝试返回一个局部变量
  • 正确,例如:printf("%s\n", Stream.ReadCString());
  • 不太明白,假​​设你的缓冲区是 [0,0,0,'H','E','L','L',O',0] 并且位置是3 为什么你不返回 &(buffer[position]) ?和位置 += strlen(&buffer[位置])
  • @Alexis 我已经试过了,也许我打错了。我再试一次。
  • @Alexis 它现在会读过去,但由于某些奇怪的原因它不会显示它。

标签: c++ buffer cstring


【解决方案1】:

检查一下:

#include <cstring>
#include <iostream>

class   A
{
  unsigned char buffer[4096];
  int   position;

public:
  A() : position(0)
  {
    memset(buffer, 0, 4096);
    char        *pos = reinterpret_cast<char*>(&(this->buffer[50]));
    strcpy(pos, "String");
    pos = reinterpret_cast<char*>(&(this->buffer[100]));
    strcpy(pos, "An other string");
  }

   const char *ReadString()
  {
    if (this->position != 4096)
      {
        while (std::isalpha(this->buffer[this->position]) == false && this->position != 4096)
               this->position++;
        if (this->position == 4096)
          return 0;
        void    *tmp = &(this->buffer[this->position]);
        char    *str  = static_cast<char *>(tmp);
        this->position += strlen(str);
        return (str);
      }
    return 0;
  }

};

reintrepret_cast 仅用于 init,因为您正在从文件中读取

int     main()
{
  A     test;

  std::cout << test.ReadString() << std::endl;
  std::cout << test.ReadString() << std::endl;
  std::cout << test.ReadString() << std::endl;
}

http://ideone.com/LcPdFD

编辑我已经更改了结尾 ReadString()

【讨论】:

  • 我尝试使用 reinterpret_cast 失败了,这与常规转换有什么区别?
  • 检查这个新版本和演员:stackoverflow.com/questions/332030/…。但是 reinterpret_cast 比 static_cast 更强(并且更接近于演员 C)
  • 虽然我喜欢你对我的旧方法的回答,但这似乎更合适: char* Stream::ReadCString() { this->AdvPosition(strlen((char*)&(this->buffer[这个->位置])) + 1);返回 (char*)&(this->buffer[this->position]);有没有办法使用这种方法显示字符串?
  • 你的回答基本上和我的一样,除了你不移动位置而是AdvPosition。如果你不能显示任何东西是你返回错误的地址或类似的东西。而你在 C++ 中尽量避免使用 printf :)
  • tbh printf 比 std::cout imo 更容易使用哈哈
【解决方案2】:

str 是本地 c 字符串。任何指向 str 外部函数的引用指针都是未定义的行为:Undefined, unspecified and implementation-defined behavior,它可能会或可能不会导致显着问题。

【讨论】:

  • 这就解释了为什么,现在我必须找到一个解决方法哈哈
  • @Jakes625 如果你喜欢,哈哈。
【解决方案3】:

只要您小心,Null 终止可能是最好的方法,但它不适合您的原因很可能是因为您正在返回已在堆栈上分配的内存。一旦你点击返回,这个内存就会被释放,因此会导致未定义的行为。相反,在堆上分配你的字符:

char* str = new char[0x10000];

当调用者不再需要它时释放内存。

【讨论】:

  • 文件中的字符串已经以空值结尾。所以我想我可以得到当前位置的地址。我现在只是无法显示。
  • 从第一个 pos 的地址到空终止符,是的。我仍然很难理解你想要做什么:P 但祝你好运!
  • 我正在读取文件的所有内容并将其存储在一个字节数组(无符号字符*)中,然后我开始读取其中的数据。这是我的文件puu.sh/3JC0B/f69dc57519.png。我正在尝试显示“entry_n”并将位置推进到它之后的字节。我可以成功推进位置,但字符串不会显示 printf("%s\n", stream.ReadCString());
【解决方案4】:

可以通过以下方法修复。我正在推进职位,然后返回地址。

char* Stream::ReadCString()
{
    u64 str_len = strlen((char*)&(this->buffer[this->position])) + 1;
    this->AdvPosition(str_len);
    return (char*)&(this->buffer[this->position - str_len]);
}

希望这对任何人都有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-13
    相关资源
    最近更新 更多