views:

184

answers:

6

Hi,

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?

+1  A: 
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;
}
anon
You can't pass a `char[]` to `char*`.
Martijn Courteaux
@Mart: sure you can, it's called array-to-pointer decay.
FredOverflow
@Martijn: What makes you say that?
sbi
@sbi: I tried it, and I got a compilation error.
Martijn Courteaux
Martijn Courteaux
@FredOverflow: thanks for the term "array-to-pointer decay".
Martijn Courteaux
+3  A: 

Simply:

char c;
cin >> c;
cout << c;
Didier Trosset
`if(cin >> c)`, dammit!
sbi
Does not do what the OP asked.
anon
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
@sbi: What does that?
Martijn Courteaux
@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
@sbi: Thanks! I made a grammar error: What does that do?
Martijn Courteaux
@Neil: Little question: What does OP mean?
Martijn Courteaux
@Matijn: "Original Posting" or "Original Poster" - a term that, I think, comes from Usenet.
sbi
@sbi,@Didier: with "char c = 0;" all is ok. It's a POD, need to be initialized.
Nikko
@Nikko: that's wrong. See my last comment to your answer.
sbi
@Neil: Why do you think this is not what the OP is asking for?
Martin York
@Martin He was asking about calling his own println() function. I seem to be the only person who actually answered that. Sigh.
anon
@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
@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
A: 

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
`<sigh>` 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
Ok I forgot to initialize the char :) If std::cin fail it does not change the input.
Nikko
@Nikko: 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
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
+2  A: 

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
POD should be initialized anyway :P
Nikko
@Nikko: No, why? It's value will be overridden in the very next statement (if the input succeeds). What good would it be to set it to some value before that?
sbi
its value won't be if std::cin fail :)
Nikko
@Nikko: That's why it's value isn't accessed (in this case: printed) if input fails.
sbi
+2  A: 
Kotti
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.
Nathan Adams
Thanks, it is what I thought. Does this cause a memory leak.
Martijn Courteaux
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.
Kotti
@Nathan Probably, yes, but I don't think it should excuse people who are doing evil things like that.
Kotti
@Nathan: It is so __very__ likely that the process owns the memory behind a stack variable, it is almost certain.
sbi
@Kotti Completely agree, just want to paint the bigger picture. And I mean "memory" not "member". I haven't had my coffee yet :P.
Nathan Adams
A: 
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