const char* as a buffer?

I want to use a const char* as a buffer. I am reading values from a file and adding them to a buffer. How to extract the values is simple enough. I am reading through a filestream, reading each character into a char pointer and progressing that char pointer every time. I have another char pointer marking the start positon

eg.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
char *mychar = new char;
char *char1 = new char;
char *char2 = new char;
const char *constchar ;

char2 = char1;

while(filestream.read(mychar,1)
{
*char1 = *mychar;
++char1;
}

// The I get this problem
constchar = mychar; // const char* = char*.
//constchar does not catch all the data in other words.

// At some stage some data is lost due to zeros in the data..  How can I put //values into a const char and get around this problem?
//The const char* will //only record everything up until the first zero.






Last edited on
¿could you show what you are actually using?
`++char1;' invalidates the pointer
`constchar = mychar;' would only get the last character

All seems unnecessary complicated.
At the beginning I should have had char2 = char1. So char2 is still pointing to the original address. I've fixed that now.

++char1 does invalidate the pointer but it moves it to the next position in memory, so char1 is pointing to the next position. char2 is still pointing to the original position. This generally works but for the case where there is a 0 which is interpreted as a null termination.

Getting back to the original need, I have to use a const char* as a buffer and I can't have it end where an ASCII 0 is encountered.



char1 is a pointer to a single char, so as @ne555 stated ++char1 will invalidate the pointer. Do you mean to have a pointer to a char array? I think you do.
> I have to use a const char* as a buffer and I can't have it end where an ASCII 0 is encountered.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <fstream>
#include <iomanip>

int main()
{
    const char* const file_name = "test.bin" ;

    // create a test file, put some bytes (including zeroes) into it
    {
        std::ofstream file( file_name, std::ios::binary ) ;
        for( int i = 0 ; i < 300 ; ++i ) file << char( i%7 ) ;
    }

    // read the contents of the file into a string
    std::string str ;
    {
        std::ifstream file( file_name, std::ios::binary ) ; // open file for input
        
        // copy the contents of the file to a to a C++ string 
        char c ;
        while( file.get(c) ) str += c ; 
    }

    const char* buffer = str.c_str() ; // pointer to first char in the string
    const auto nchars = str.size() ; // number of bytes that were read

    // print out the values of the bytes in the buffer
    for( std::size_t i = 0 ; i < nchars ; ++i )
    {
        std::cout << std::setw(2) << int( buffer[i] ) << ' ' ;
        if( i%40 == 39 ) std::cout << '\n' ;
    }
    std::cout << '\n' ;
}

http://coliru.stacked-crooked.com/a/c8878fd5da9078b6
Allow me to clarify some things.

A "buffer" is a block of memory. IE, if you want to be able to have 100 characters... then you'll need a buffer that is at least 100 characters large.

A "pointer" is not a buffer. A pointer is merely a variable that holds an address. That address may or may not be the address of a buffer, depending on where/how you got the address.

That said...
Using the new keyword (char* x = new char;) does 2 things:
1) creates a single unnamed char variable. We'll call this variable 'foo'
2) returns a pointer to that unnamed char and assigns it to our 'x' pointer.

Therefore... at the end of this.. 'x' will point to 'foo'. But 'foo' is only large enough to hold a single character since that's all you allocated.



On the other hand...
Using the new[] keyword (char* x = new char[100];) does the same 2 things, slightly differently:
1) Creates an unnamed buffer of 100 chars.
2) Returns a pointer to the first char in that buffer and assigns it to 'x'.

So this time... foo is a proper buffer capable of holding no more than 100 chars. And 'x' will properly point to that buffer.



Keep in mind that anything you allocate with new needs to be unallocated with delete. Likewise anything allocated with new[] needs to be unallocated with delete[].

And really... you should avoid dynamic allocation unless you absolutely need it. You are doing a lot of unnecessary allocation in your original post which leads me to believe you have some horrible misunderstanding about how C++ works.


For academic purposes... you could rewrite your original code to use dynamically allocated memory like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
char* buffer = new char[100];  // buffer large enough to hold 100 characters

char* p = buffer; // 'p' point to the first character in that buffer
   // 'p' will change to point to other chars in the buffer...
   // whereas we want 'buffer' to always point to the first char...
   //
   //  p effectively points to the 'next' character in the buffer

while(filestream.read(p,1)) // <- read a character into the next spot in the buffer
{
  ++p;  // and increment 'p' to point to the next character
}

// at this point... 'buffer' will contain the contents of the file
//  (but note that if the file was larger than 100 characters, you'll have memory corruption
//    which is BAD BAD BAD)

// since the buffer 'buffer' points to was dynamically allocated.  We need to delete[] it
//  when we're done with it to avoid memory leaks
delete[] buffer;



Of course.... this is largely unnecessary. There is no value in reading 1 character at a time. read() can read any number of characters all at once. So instead... let's have a look at this:

1
2
3
4
5
6
7
8
9
10
11
12
13
// same business as before, except let's get rid of 'p' because we don't need it
char* buffer = new char[100];

filestream.read(buffer,100); // <- just read 100 characters into 'buffer' directly


// That's it.  No loop or pointer math required.
//  But note we still can only read 100 characters (the max size of the buffer)
//  and we STILL need to delete[] because we used new[].

// so when you're done with this string data, don't forget to delete it:

delete[] buffer;





But EVEN THIS can be simplified. If we always want a buffer that's 100 characters long... we don't need to dynamically allocate it. Therefore we can save the new[]/delete[] headaches and just make the buffer directly:

1
2
3
4
5
6
// don't use new[].  Just make the buffer directly:
char buffer[100];

filestream.read(buffer,100); // <- just read 100 characters into 'buffer'

// that's it!  No need to delete[] anything because nothing was new[]'d 




Though this would be a lot easier if you could use strings. Any reason why you have to use char buffers?
Last edited on
I hope you don't use strcpy() or other C functions to manipulate that buffer, be it allocated on the stack or heap, and wonder why it "stops" at first NUL character. You haven't show us what you want to do.
Topic archived. No new replies allowed.