1

When I read one char* from std::cin and I want to write it to std::cout, it prints until it finds a \0 in memory. So what did was:

char c;
cin >> c;
char* pChar = &c;
pChar++;
*pChar = '\0';
println(&c); // My own method: void println(char * str) { cout << str << endl; }

But I don't think this is a safe action.

Is there a safer way to do this?

Daniel Trebbien
  • 38,421
  • 18
  • 121
  • 193
Martijn Courteaux
  • 67,591
  • 47
  • 198
  • 287
  • 1
    I'd like to find out what you are trying to achieve before answering. Your code looks much too complicated if you are just trying to copy from cin to cout. – Thorsten79 Jun 02 '10 at 13:07
  • 3
    Your code is Undefined Behavior. You are creating a variable in the stack, then creating a pointer to it and finally overwritting an address beyond the reserved space. Your code is not only unsafe, it is wrong. – David Rodríguez - dribeas Jun 02 '10 at 13:12

6 Answers6

4

Simply:

char c;
cin >> c;
cout << c;
Didier Trosset
  • 36,376
  • 13
  • 83
  • 122
  • Does not do what the OP asked. –  Jun 02 '10 at 13:10
  • So the problem is that I pass it as a `char*` which cout << ... handles as a char sequence. And if I make a method println(char c) it would work? – Martijn Courteaux Jun 02 '10 at 13:11
  • @Martijn: It checks whether inputting succeeded. There isn't much that could go wrong when reading a character, but any input operation will also fail if previous input operations failed and the input stream still in a bad state. Didier's code will then print a random character. – sbi Jun 02 '10 at 13:14
  • @Neil: Little question: What does OP mean? – Martijn Courteaux Jun 02 '10 at 13:20
  • 1
    @Matijn: "Original Posting" or "Original Poster" - a term that, I think, comes from Usenet. – sbi Jun 02 '10 at 13:21
  • @sbi,@Didier: with "char c = 0;" all is ok. It's a POD, need to be initialized. – Nikko Jun 02 '10 at 13:24
  • 1
    @Neil: Why do you think this is not what the OP is asking for? – Martin York Jun 02 '10 at 13:29
  • @Martin He was asking about calling his own println() function. I seem to be the only person who actually answered that. Sigh. –  Jun 02 '10 at 13:31
  • @Neil: I'm not really sure what the question was, but the title is: "C++: Print only one char". It seems he made his own function because he had a problem. – Nikko Jun 02 '10 at 13:34
  • 1
    @Neil: Martijn wrote "I read one char* from std::cin and I want to write it to std::cout", and only in his code there was a `println()` function, which I (and, apparently, others) took as artifacts of his struggle to get this to work. – sbi Jun 02 '10 at 13:35
2

The right thing to do when you want to print a character, of course, is to print that character:

char ch;
if(std::cin >>ch) 
  std::cout << ch;
else
  // handle input error

And if you, for whatever reason, want a newline behind every character, then do just that:

std::cout << char << '\n';

Note: You will also see std::endl used for outputting a newline, but std::endl does two things: it outputs a '\n' and flushes the output buffer. While the latter isn't a problem when outputting to the console (it's still faster than a human will be able to read it), I have seen applications becoming to slow (on file output) due to the use of std::endl instead of '\n'. So you'd better learn from the beginning to pay attention whether you need those buffers flushed or not.


Note that, where you're doing

pChar++;
*pChar = '\0';

you're invoking the dreaded Undefined Behavior: With pChar++ you are incrementing the pointer to point behind your variable (which is fine), and with *pChar = ... you are writing to whatever memory happens to be behind your variable.
In practice, this will likely corrupt your stack, hopefully making your application crash in the very next moment. In theory, however, this invokes undefined behavior, which, according to the C++ standard, might do anything (including the often cited possibility that it might format your disk).
Do not write to memory that you don't own.
It is hard for beginners to get pointers right, so just avoid them wherever you can. You can do a lot with C++ without ever manually fiddling with pointers.

sbi
  • 219,715
  • 46
  • 258
  • 445
2

There already are some answers on how to do what you want to do, but I would like to explain what actually beneath those pchar++ in your code and why it's evil.

C-style casting grants flexibility, but allows you to shoot yourself in the foot. You've allocated char c on the stack (that means you have exact amount of memory reserved for it, and it equals sizeof(char), which is exactlye 1 byte).

Then you take a memory address of your variable (that's ok), so you have your char variable and a pointer to the memory where this char is located. But your next step is completely evil, because you (when doing *(pchar + 1) = 0) are actually corrupting the stack.

As I've told earlier the compiler reserved exactly one byte for your char memory, but what you do means explicitly traversing to the next byte in that memory (which could even belong to other program's stack) and rewriting it with your own values.

This behaviour could be also described with the following example:

Think that you have to alter the contents of some concrete file (a.file) on your hard disk. Do you think it's ok to rewrite the contents of files that sequentially follow a.file, for example, increase the size of that a.file?

M. Williams
  • 4,945
  • 2
  • 26
  • 27
  • In theory, at least from what I know, most modern OSes will prevent a process from writing to memory it doesn't own (unless of course it is explicitly shared member). While I do agree with the fact it will corrupt the stack, BUT in most modern OSes it won't because the OS will block the process. – Natalie Adams Jun 02 '10 at 13:31
  • Thanks, it is what I thought. Does this cause a memory leak. – Martijn Courteaux Jun 02 '10 at 13:31
  • Try understanding what does a *memory leak* mean. I know, this could be hard when porting yourself from Java to C or C++, but you should know what does it stand for. – M. Williams Jun 02 '10 at 13:33
  • @Nathan Probably, yes, but I don't think it should excuse people who are doing evil things like that. – M. Williams Jun 02 '10 at 13:38
  • 1
    @Nathan: It is so __very__ likely that the process owns the memory behind a stack variable, it is almost certain. – sbi Jun 02 '10 at 13:38
  • @Kotti Completely agree, just want to paint the bigger picture. And I mean "memory" not "member". I haven't had my coffee yet :P. – Natalie Adams Jun 02 '10 at 15:20
1
char c;
cin >> c;
char pChar[2] = {0};
pChar[0] = c;;
println(pChar); 

Or if you want to be more C++ like, overload the functions:

void println( const char * s ) {
   cout << s << endl;
}

void println( char  c ) {
   cout << c << endl;
}

Or even template:

template <typename T >
void println( T t ) {
   cout << t << endl;
}
0

Print the character you entered:

char c = 0;
std::cin >> c;
std::cout << c;

Get the character in a string and get the first character:

char c = 0;
std::cin >> c;
std::string str;
str += c;

std::cout << str.at(0) << std::endl;

EDIT

Or maybe you asked for this? :

std::string str;
std::cin >> str;

std::cout << str;

I'm not really sure what is really the problem.

Nikko
  • 4,182
  • 1
  • 26
  • 44
  • `` And if input fails, your code prints a random character. (That annoys your fellow-workers to no ends of it happens to be a `0x7`.) – sbi Jun 02 '10 at 13:11
  • Ok I forgot to initialize the char :) If std::cin fail it does not change the input. – Nikko Jun 02 '10 at 13:22
  • And now, if input fails, it silently prints nothing at all. I'm sorry to say, but I don't really see this as an improvement. – sbi Jun 02 '10 at 13:25
  • Because it's just a simple example? And it's not really the point to see why it is needed if I don't initialize the char and why I don't need it for a std::string that has a constructor... the OP being I think a beginner.. – Nikko Jun 02 '10 at 13:27
0
char c;
std::cin >> c;
if (std::cin) {
    std::cout << c << std::flush;
}

That code prints "only one char". std::cout << c << std::endl prints two: c and '\n'.

You can also use your println function if you wanted:

char str[2] = {'\0', '\0'};
std::cin >> str[0];
if (std::cin) {
    println(str);
}

Note that if (std::cin) causes the compiler to invoke the operator void*() const member of the std::ios class, which std::istream extends, in order to evaluate std::cin as a boolean.

Daniel Trebbien
  • 38,421
  • 18
  • 121
  • 193