1

I am trying to build my overall expertise in C++ coming from VBA, so please forgive any glaring issues with my code... Using this simple program below, I am getting unexpected output.

#include <iostream>

int main() {
char f[]="", c[]="";
std::cin >> f;
std::cout << f << std::endl;
std::cin >> c;
std::cout << f << std::endl;
return 0;
}

When run, this is my result:

ABC (input)
f - ABC (output)
DEF (input)
f - EF (output)

Also tried as:

ABC DEF (input)
f - ABC (output)
f - EF (output)

I would expect that the output would be the same for both lines, since I THINK I'm only reading into f once. Moreover, if I am taking the cin and applying it to f, why does the first attempt read the entire string (ABC) while the second attempt is missing the D?

I tried also printing the result using this code, but the same problem occurs, so I'm assuming here that it's a problem with the cin and not cout.

for (j=0;j<3;j++) {
    std::cout << f[j];
}
std::cout << std::endl;

Doing some research, I found this question, which looked promising, but when I changed my declaration from char f[] to char *f, I ended up with SEGFAULTs on the cin, while const char *f wouldn't even compile.

I am fumbling blindly here and would appreciate some guidance on how to correctly use cin and/or char arrays.

To reiterate my question: Why does the output std::cout << f << std::endl;, while not explicitly reassigning a value, vary in this way?

Community
  • 1
  • 1
Gaffi
  • 4,307
  • 8
  • 43
  • 73
  • If you want this behaviour, use `std::string`. For a char array, it needs to be long enough to hold the input. – chris Jul 08 '12 at 06:01
  • 1
    Never use `istream::operator>>` with char arrays, it is inherently unsafe. (unless you are using a stream where you know the max size of the data, such as a stringstream which you passed the string to yourself) – Benjamin Lindley Jul 08 '12 at 06:03
  • @BenjaminLindley Would it be preferred then to cin>>string, then use string.c_str()? – Gaffi Jul 08 '12 at 06:07
  • @Gaffi: To the first, yes. To the second, I don't see why `c_str()` has to come into it. Are you interfacing with a C library? – Benjamin Lindley Jul 08 '12 at 06:11
  • @BenjaminLindley No, I am merely trying to iterate over the characters of the string, and figured `char[]` was a good fit for that. I saw some resources online use `c_str` as a means to convert from one to the other. Is there a better way to do this? – Gaffi Jul 08 '12 at 06:13
  • 1
    You can iterate over the characters of a `std::string` in the same way you can over a char array, using `operator[]`, which is overloaded for `std::string`. There are other ways too, such as `std::string::iterator`. – Benjamin Lindley Jul 08 '12 at 06:15

3 Answers3

9
char f[]="", c[]="";

is equivalent to

char f[1]="", c[1]="";

i.e. it declares both f and c as arrays of one character (namely NUL or \0, the null terminator).

In other words, you're reading into both arrays past their end, which could work perfectly, could do very strange things (like you're seeing), could crash, or could make purple elephants erupt from your monitor next Tuesday.

John Calsbeek
  • 35,947
  • 7
  • 94
  • 101
  • Is it preferred then to use `f[256]` or some other larger value? I tried this, and it looks like it works, but there are other suggestions in the comments indicating I shouldn't even be using `char[]` in the first place. – Gaffi Jul 08 '12 at 06:11
  • 1
    @Gaffi: Right: any number you pick, the user can enter a string that's larger. This is a textbook example of a buffer overflow vulnerability. If you read into an `std::string`, you can write out that `std::string` without ever putting anything into a `char[]`. Otherwise, you probably need to figure out how big the input string is and dynamically allocate an array to fit it. – John Calsbeek Jul 08 '12 at 06:12
0

It looks like you should use the getline function. There are two versions of it...

One is in the C++ standard library and is used this way:

std::string s;
// the following returns the stream that you give
// (the cast is non-functional, it's there to show the type)
(istream&)getline(cin, s);

The string object is nice for this because it dynamically sizes itself to hold whatever you receive.

The other getline is in the standard C library, at least on Mac OS X (run man 3 getline for more) and it uses FILE* instead of streams. That version is capable of dynamically reallocating a char array if you want it to, but you don't have to use it that way.

Kevin Grant
  • 5,363
  • 1
  • 21
  • 24
  • 1
    Lose the cast, otherwise this is great advice. – Ben Voigt Jul 08 '12 at 06:25
  • The second getline you are referring to is not part of the standard C library. There is another (c++ standard) getline though, the [istream member function](http://en.cppreference.com/w/cpp/io/basic_istream/getline) version. – Benjamin Lindley Jul 08 '12 at 06:25
0
#include < iostream >

int main() {
    char f[]="";
    char c[]="";

Try these, it solve the problem for me ;D

Jonathan
  • 1,542
  • 3
  • 16
  • 24