【问题标题】:Howto read chunk of memory as char in c++如何在c ++中将内存块读取为char
【发布时间】:2010-10-13 21:53:56
【问题描述】:

您好,我有一块包含位(位字面量)的内存(使用 malloc() 分配),我想将其读取为 char 数组,或者,更好的是,我想打印出 ASCII内存中连续 8 位的值。

我已将他的内存分配为 char *,但我无法以比评估每个位更好的方式取出字符,将值添加到 char 并在循环中左移 char 的值,但我一直在寻找更快的解决方案。 谢谢

我现在写的是这样的:

分配:

char * bits = (char*) malloc(1);

写给内存:

ifstream cleartext;
cleartext.open(sometext);
while(cleartext.good())
{
     c = cleartext.get();
     for(int j = 0; j < 8; j++)
     {  //set(index) and reset(index) set or reset the bit at bits[i]
        (c & 0x80) ? (set(index)):(reset(index));//(*ptr++ = '1'):(*ptr++='0');
         c = c << 1;
     }..
}..

直到现在我还无法恢复字符,我只能使用以下方式打印出位:

printf("%s\n" bits);

我正在尝试做的一个例子是:

input.txt 包含字符串“AAAB”

我的程序必须将“AAAB”作为“01000001010000010100000101000010”写入内存 (AAAB 的 ASCII 值是 65656566 位)

那我希望它有把内存内容改写成文件的功能。

因此,如果内存再次包含“01000001010000010100000101000010”,它将写入输出文件“AAAB”。

【问题讨论】:

  • “包含位”。你是说字节还是什么?
  • c++ 不允许你分配一次分配整个字符的“位”(通常是字节)。
  • 我使用 malloc() 是因为我认为它会更快,并且因为我认为有一种更快(甚至更糟)的方式来读取和写入字符和位
  • 我认为您对加载文件的含义感到非常困惑。在计算机中,一切都是二进制的。它只是在将字符串打印到屏幕上时将它们视为字母,以方便我们必须阅读它的人。如果您加载了一个角色,那么您“也”加载了这些位。
  • 好吧,我感到困惑的是什么是快速访问内存中加载的文件位的最佳方法,如果它取决于我用来加载文件的数据类型,如果我可以可以快速访问它们中的每一个,而不是通过迭代

标签: c++ malloc char


【解决方案1】:
int numBytes = 512;
char *pChar = (char *)malloc(numBytes);
for( int i = 0; i < numBytes; i++ ){
   pChar[i] = '8';
}

由于这是C++,你也可以使用“new”:

int numBytes = 512;
char *pChar = new char[numBytes];
for( int i = 0; i < numBytes; i++ ){
   pChar[i] = '8';
}

【讨论】:

  • 如果我需要调整大小,“new”是否比“realloc”更好?还是我必须复制写入的字节?
  • 如果您需要在使用“new”分配后调整大小,则必须复制写入的字节。在这种情况下,使用 C 风格的 malloc/realloc/free 可能会更有效。
【解决方案2】:

如果你想访问内存块中的每一个bit,看起来你需要std::bitset

char* pChunk = malloc( n );
// read in pChunk data

// iterate over all the bits.
for( int i = 0; i != n; ++i ){
    std::bitset<8>& bits = *reinterpret_cast< std::bitset<8>* >( pByte );
    for( int iBit = 0; iBit != 8; ++iBit ) {
        std::cout << bits[i];
    }
}

【讨论】:

    【解决方案3】:

    我想打印出内存中连续 8 位的 ASCII 值。

    任何位的可能值是 0 或 1。您可能至少需要一个字节。

    char * bits = (char*) malloc(1);

    在堆上分配 1 个字节。一个更高效、更轻松的事情是在堆栈上创建一个对象,即:

    char bits; // a single character, has CHAR_BIT bits
    

    ifstream 明文;

    cleartext.open(sometext);

    上面没有写任何东西给内存。它尝试以输入模式打开文件。

    它有ascii字符和常见的eof或\n,或类似的东西,输入只会是一个文本文件,所以我认为它应该只包含ASCII字符,如果我错了,请纠正我。

    如果您的文件只有 ASCII 数据,您不必担心。您需要做的就是读入文件内容并将其写出。编译器管理数据的存储方式(即为您的字符使用哪种编码以及如何用二进制表示它们,系统的字节序等)。读取/写入文件的最简单方法是:

    // include these on as-needed basis
    #include <algorithm>
    #include <iostream>
    #include <iterator>
    #include <fstream>
    
    using namespace std;
    // ...
    
    /* read from standard input and write to standard output */
    copy((istream_iterator<char>(cin)), (istream_iterator<char>()),
                      (ostream_iterator<char>(cout)));
    /*-------------------------------------------------------------*/
    
    /* read from standard input and write to text file */
    copy(istream_iterator<char>(cin), istream_iterator<char>(),
             ostream_iterator<char>(ofstream("output.txt"), "\n") );
    /*-------------------------------------------------------------*/
    
    /* read from text file and write to text file */
    copy(istream_iterator<char>(ifstream("input.txt")), istream_iterator<char>(),
             ostream_iterator<char>(ofstream("output.txt"), "\n") );
    /*-------------------------------------------------------------*/
    

    剩下的最后一个问题是:你想用二进制表示做点什么吗?如果没有,那就算了。否则,请再次更新您的问题。

    例如:处理字符数组以使用分组密码对其进行加密

    /* a hash calculator */
    struct hash_sha1 {
     unsigned char operator()(unsigned char x) {
        // process
        return rc;
      }
    };
    
    /* store house of characters, could've been a vector as well */
    basic_string<unsigned char> line;
    
    /* read from text file and write to a string of unsigned chars */   
    copy(istream_iterator<unsigned char>(ifstream("input.txt")),
                                         istream_iterator<char>(),
                                          back_inserter(line) );
    
    /* Calculate a SHA-1 hash of the input */   
    basic_string<unsigned char> hashmsg;
    transform(line.begin(), line.end(), back_inserter(hashmsg), hash_sha1());
    

    【讨论】:

    • 写入内存步骤是您引用之后的循环(即 set(index) 和 reset(index) 写入内存,它们是我没有在这里复制的函数,抱歉)
    • input.txt 文件能否包含 ASCII/可打印字符以外的任何内容?
    • 它有ascii字符和常见的eof或\n,或类似的东西,输入只会是一个文本文件,所以我认为它应该只包含ASCII字符,如果我错了请纠正我
    • 对不起,我以为我还没有写过它,是的,我需要二进制表示来使用一些加密功能,这就是为什么我需要从文本到比特的翻译,反之亦然,谢谢你
    • 只需将 char 数组传递给您的加密函数。我会使用无符号字符来阅读。
    【解决方案4】:

    这样的?

    char *buffer = (char*)malloc(42);
    // ... put something into the buffer ...
    printf("%c\n", buffer[0]);
    

    但是,既然您使用的是 C++,我想知道您为什么要打扰 malloc 之类的...

    【讨论】:

    • 你还有什么其他的建议吗?我需要将文本文件作为位存储在内存中以用于加密功能,一旦我加密,我想重新打印生成的字符,malloc 是我想到的第一个也是最快的东西,但我愿意更好的选择...
    • std::vector 允许您访问单个位并将它们有效地打包到内存中。如果您使用的是固定块大小,std::bitset 可能是更好的选择。
    • 我不认为尺寸是固定的,至少现在,我正在启动这个项目,所以不知道它会如何发展:D
    • 好吧,更好的方法是 new char[size] 而不是 malloc。
    • 我可能记错了,但 std::vector 并不比 std::vector 高效。两者都使用每个元素 1 个字节。请考虑使用 std::vector
    【解决方案5】:
    char* ptr = pAddressOfMemoryToRead;
    
    while(ptr < pAddressOfMemoryToRead + blockLength)
    {
         char tmp = *ptr;
         // temp now has the char from this spot in memory
         ptr++;
    }
    

    【讨论】:

      【解决方案6】:

      这是你想要达到的目标吗:

      char* p = (char*)malloc(10 * sizeof(char));
      char* p1 = p;
      memcpy(p,"abcdefghij", 10);
      
      for(int i = 0; i < 10; ++i)
      {
          char c = *p1;
          cout<<c<<" ";
          ++p1;
      }
      cout<<"\n";
      free(p);
      

      【讨论】:

        【解决方案7】:

        您能否更详细地解释一下,也许包括代码?除非我完全误读了您的问题,否则您所说的毫无意义。你在做这样的事情吗?

        char * chunk = (char *)malloc(256);
        

        如果是这样,您可以通过将chunk 视为数组来访问任何字符的数据:chunk[5] 为您提供第 5 个元素等。当然,这些将是字符,这可能是您想要的,但是我不能从你的问题中完全看出...例如,如果chunk[5] 是 65,当你像cout &lt;&lt; chunk[5]; 一样打印它时,你会得到一个字母'A'。

        但是,您可能会问如何打印出实际的数字 65,在这种情况下您想要执行cout &lt;&lt; int(chunk[5]);。转换为 int 将使其打印为整数值而不是字符。如果您澄清您的问题,我或其他人可以进一步帮助您。

        【讨论】:

        • 是的,正如其他人所提到的,你为什么在 C++ 程序中使用 malloc() ?你应该使用“新”。我的例子的第一行是:char * chunk = new char[256];在 C++ 中。
        【解决方案8】:

        您是在问如何将任意结构的内存字节复制到 char* 数组中?如果是这样,这应该可以解决问题

        SomeType t = GetSomeType();
        char* ptr = malloc(sizeof(SomeType));
        if ( !ptr ) {
          // Handle no memory.  Probably should just crash
        }
        memcpy(ptr,&t,sizeof(SomeType));
        

        【讨论】:

          【解决方案9】:

          我不确定我是否完全理解您想要做的事情,但有几点建议:

          1) 使用 std::vector 代替 malloc/free 和 new/delete。它更安全,并且没有太多开销。

          2) 处理时,尝试使用块而不是字节。尽管流是缓冲的,但一次抓取一个块通常更有效。

          3) 有很多不同的方式来输出位,但同样你不希望为每个字符输出流。您可能想尝试以下方法:

          void outputbits(char *dest, char source)
          {
              dest[8] = 0;
              for(int i=0; i<8; ++i)
                  dest[i] = source & (1<<(7-i)) ? '1':'0';
          }
          

          将一个 char[9] 输出缓冲区和一个 char 输入传递给它,您将得到一个可打印的位串。体面的编译器会为此生成良好的输出代码...您需要多高的速度?

          【讨论】:

          • 这一步我真的不需要这么快,因为我希望要加解密的文件不要那么大...
          • 我需要二进制表示才能对位进行数学运算
          • 这听起来像是一个非常错误的处理问题的方法 - 你真的不需要位的 ascii 表示来对它们进行数学运算:)
          • 不,我需要表示的位来进行数学运算,但需要它们的 ascii 表示来 rpintout 对“加密”文本的评估。我错了吗?
          • 好吧,如果您需要以二进制形式打印,当然可以。就个人而言,我要么打印十六进制表示(或 BASE64),要么简单地处理原始字节值(不过,它是不可打印的)。
          猜你喜欢
          • 2012-04-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-05-07
          相关资源
          最近更新 更多