Get an Istream from a Char*

Get an istream from a char*

Here's a non-deprecated method found on the web, has you derive your own std::streambuf class, but easy and seems to work:

#include <iostream>
#include <istream>
#include <streambuf>
#include <string>

struct membuf : std::streambuf
{
membuf(char* begin, char* end) {
this->setg(begin, begin, end);
}
};

int main()
{
char buffer[] = "I'm a buffer with embedded nulls\0and line\n feeds";

membuf sbuf(buffer, buffer + sizeof(buffer));
std::istream in(&sbuf);
std::string line;
while (std::getline(in, line)) {
std::cout << "line: " << line << "\n";
}
return 0;
}

Which outputs:

line: I'm a buffer with embedded nullsand line
line: feeds

converting unsigned char* to std::istream* C++

You can use an std::stringstream from <sstream>, which supports both istream and ostream interface. So you can write data through the ostream-interface and pass it then as an istream-argument:

#include <sstream>
#include <iomanip>
#include <iostream>

void prints(istream &is) {
unsigned char c;
while (is >> c) {
std::cout << "0x" << std::hex << (unsigned int)c << std::endl;
}
}

int main()
{
unsigned char x[6] = { 0x2, 0x10, 0xff, 0x0, 0x5, 0x8 };
std::stringstream xReadWrite;
xReadWrite.write((const char*)x, 6);
prints(xReadWrite);
}

Reading a character in an istream pointer

When you are using ch, it is of the wrong type (As you mentioned in the comments); std::basic_istream::get expects a value of type char (Since that is what std::basic_istream::char_type is defined as), but passing it a value with type unsigned char creates the error. Change the type to char to solve your problem.

Here is some minimal code that exhibits the example working:

#include <iostream>

using namespace std;

void foo(istream* is){
char ch;
while(is->get(ch)){
// do something
break;
}
}

int main()
{
istream is(cin.rdbuf());
foo(&is);
}

On a side note, I would make the recommendation that you avoid using pointers in this case, and instead use references, since that achieves the same purpose, except that it looks cleaner.

Use unsigned char* as istream

std::stringstream should do what you want....

#include <sstream>

BYTE *imageBuffer1;
// where N is the desired number if bytes
std::stringstream minutiaeBuffer1(
std::string(reinterpret_cast<char*>(imageBuffer1),N));

prepared_statemet->setBlob(1, &minutiaeBuffer1);

EDIT: Restricted length of input buffer to N

c++ using std::copy to copy an istream to a char* buffer

No problem to copy provided enough storage is allocated upfront:

#include <sstream>
#include <algorithm>
#include <iterator>
#include <vector>
int main()
{
std::vector<char> vec(6); //note what happens here!
std::istringstream ss("foobar");
std::copy(std::istream_iterator<char>(ss), std::istream_iterator<char>
(), vec.data());
}

istream and cin.get()

First off, "pressing enter" has no special meaning to the IOStreams beyond entering a newline character (\n) into the input sequence (note, when using text streams the platform specific end of line sequences are transformed into a single newline character). When entering data on a console, the data is normally line buffered by the console and only forwarded to the program when pressing enter (typically this can be turned off but the details of this are platform specific and irrelevant to this question anyway).

With this out of the way lets turn our attention to the behavior of s.get(buffer, n) for an std::istream s and a pointer to an array of at least n characters buffer. The description of what this does is quite trivial: it calls s.get(buffer, n, s.widen('\n')). Since we are talking about std::istream and you probably haven't changed the std::locale we can assume that s.widen('\n') just returns '\n', i.e., the call is equivalent to s.get(buffer, n, '\n') where '\n' is called a delimiter and the question becomes what this function does.

Well, this function extracts up to m = 0 < n? n - 1: 0 characters, stopping when either m is reached or when the next character is identical to the delimiter which is left in the stream (you'd used std::istream::getline() if you'd wanted the delimiter to be extracted). Any extracted character is stored in the corresponding location of buffer and if 0 < n a null character is stored into location buffer[n - 1]. In case, if no character is extracted std::ios_base::failbit is set.

OK, with this we should have all ingredients to the riddle in place: When you entered at least one character but less than 5 characters the first call to get() succeeded and left the newline character as next character in the buffer. The next attempt to get() more characters immediately found the delimiter, stored no character, and indicated failure by setting std::ios_base::failbit. It is easy to verify this theory:

#include <iostream>

int main()
{
char buffer[5];
for (int count(0); std::cin; ++count) {
if (std::cin.get(buffer, 5)) {
std::cout << "get[" << count << "]='" << buffer << "'\n";
}
else {
std::cout << "get[" << count << "] failed\n";
}
}
}

If you enter no character, the first call to std::cin.get() fails. If you enter 1 to 4 characters, the first call succeeds but the second one fails. If you enter more than 4 characters, the second call also succeeds, etc. There are several ways to deal with the potentially stuck newline character:

  1. Just use std::istream::getline() which behaves the same as std::istream::get() but also extracts the delimiter if this is why it stopped reading. This may chop one line into multiple reads, however, which may or may not be desired.
  2. To avoid the limitation of a fixed line length, you could use std::getline() together with an std::string (i.e., std::getline(std::cin, string)).
  3. After a successful get() you could check if the next character is a newline using std::istream::peek() and std::istream::ignore() it when necessary.

Which of these approaches meets your needs depends on what you are trying to achieve.



Related Topics



Leave a reply



Submit