Newbie : Reading input into character buffer (am I doing this right?)

D

deech

Hi all,
I am reading characters from input using 'cin' into a character
buffer. I want to do it dynamically and I wrote some code to do so,
and it seems to work, but I am concerned that I am doing something
that is undefined. Here is the code :
int main () {
char * buffer = new char;
char * iterator = buffer;
int buffer_length = 0;
while ((*iterator = cin.get()) != EOF) {
iterator++;
buffer_length++;
}
*iterator = '\0';
cout << "Buffer Contents : " << buffer << endl;
cout << "Buffer length : " << strlen(buffer) << endl;
}

All the examples I've seen ask you to predetermine the number of
characters that are going to be entered, and store them in a fixed-
size char array. But this seems to work, and is more flexible. K&R
tells me that modifying the contents of a pointer leads to undefined
behavior.

Is this a good way of doing what I want?
thanks ...
-deech
 
V

Victor Bazarov

deech said:
I am reading characters from input using 'cin' into a character
buffer. I want to do it dynamically and I wrote some code to do so,
and it seems to work, but I am concerned that I am doing something
that is undefined.

Unfortunately, yes.
> Here is the code :
int main () {
char * buffer = new char;

So, you allocate only *one* char. Not ten, not a hundred, not a
thousand. One.
char * iterator = buffer;

You make your 'iterator' point to the only char you've allocated.
int buffer_length = 0;
while ((*iterator = cin.get()) != EOF) {
iterator++;

You increment your iterator. Now where does it point? And on the next
iteration, where will the character you read be stored?
buffer_length++;
}
*iterator = '\0';

Again, you've moved past the boundaries of the memory you have
allocated, and you're trying to store something there. Undefined behaviour.
cout << "Buffer Contents : " << buffer << endl;
cout << "Buffer length : " << strlen(buffer) << endl;
}

All the examples I've seen ask you to predetermine the number of
characters that are going to be entered, and store them in a fixed-
size char array.

And for a good reason, too.
> But this seems to work, and is more flexible.

Flexible? Like using-ropes-for-aircraft-wings flexible?
> K&R
tells me that modifying the contents of a pointer leads to undefined
behavior.

I don't know what you're referring to, and I don't think K&R ever wrote
much about C++.
Is this a good way of doing what I want?

No. See 'std::getline' function. And if you don't yet grok dynamic
memory and the responsibility that comes with its use, don't use it.

V
 
G

Gert-Jan de Vos

Hi all,
I am reading characters from input using 'cin' into a character
buffer.

How many characters do you want to read? A fixed number, up to the
next whitespace, up to the next end of line. Up to end of file?
I want to do it dynamically and I wrote some code to do so,
and it seems to work, but I am concerned that I am doing something
that is undefined. Here is the code :
int main () {
  char * buffer = new char;

You allocate a single character here.
  char * iterator = buffer;
  int buffer_length = 0;
  while ((*iterator = cin.get()) != EOF) {
    iterator++;

Oops! Here you increment your buffer pointer past the single
allocated character. This triggers undefined behavior and will
normally result in a crash sooner or later.
    buffer_length++;
  }
  *iterator = '\0';
  cout << "Buffer Contents : " << buffer << endl;
  cout << "Buffer length : " << strlen(buffer) << endl;

}

You can read up to the end of line like this:

std::string line;
std::getline(cin, line);

Or the entire file like this:

std::string text;
std::copy(std::istream_iterator<char>(cin),
std::istream_iterator<char>(), std::back_inserter(text));

Note that the string class now takes care of buffer management for
you.
 
D

deech

How many characters do you want to read? A fixed number, up to the
next whitespace, up to the next end of line. Up to end of file?

Until I hit Ctrl-D (on Linux).

You can read up to the end of line like this:

std::string line;
std::getline(cin, line);

Or the entire file like this:

std::string text;
std::copy(std::istream_iterator<char>(cin),
std::istream_iterator<char>(), std::back_inserter(text));

Note that the string class now takes care of buffer management for
you.

I didn't use C++ string facility because I was trying to understand
dynamic memory a little better.

I appreciate you explaining my mistake.

-deech
 
D

deech

And they certainly never said that modifying the contents of a
pointer leads to undefined behavior.

I may have misread, but I saw it on pg104 in the 4th paragraph
starting with "amessage is an array ..."

-deech
 
D

Default User

deech said:
I may have misread, but I saw it on pg104 in the 4th paragraph
starting with "amessage is an array ..."

Here's the full text:

There is an important difference between these definitions:

char amessage[] = "now is the time"; /* an array */
char *pmessage = "now is the time"; /* a pointer */

amessage is an array, just big enough to hold the sequence of
characters and '\0' that initializes it. Individual characters within
the array may be changed but amessage will always refer to the same
storage. On the other hand, pmessage is a pointer, initialized to point
to a string constant; the pointer may subsequently be modified to point
elsewhere, but the result is undefined if you try to modify the string
contents.



What is undefined is trying to modify a string literal (they called it
a constant).

Something like:

char *pmessage = new char[20];

pmessage[0] = 'A';


Would be fine.



Brian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top