1

My book says that if I want to read a string with a maximum length of 40 characters, I have to declare a variable with a length of 41, but it doesn't say why.

char name[41];
cin >> name;
cout << name << endl;

I know this is a newbie question and indeed I'm a C++ newbie.

I hope you can help me. Thanks.

EDIT:

Thanks for the answers, I didn't expect so much great information in such short time.

  1. Who is in charge of inserting the NULL terminator at the end of the char array?

  2. What happens with the "\n" after I press Enter?

Thanks again.

Mark Renton
  • 101
  • 2
  • 7
  • Because you must have a `null` character at the end of your string. – Aliou Mar 28 '14 at 17:10
  • @Aliou, post that as the answer. Don't think there's much more to say. – Ben Mar 28 '14 at 17:12
  • `std::string` theoretically has no maximum. Don't use c-style strings in c++ – clcto Mar 28 '14 at 17:14
  • @MarkRenton: The answers are already provided, but I think the most important advice is missing: get a better (and perhaps newer) book. If it exposes you to char* before explaining std::string, then chances are it's from the 90s, when people often used, teached and learned "C with Classes" instead of C++ :) – Christian Hackl Mar 28 '14 at 17:55
  • string literals in C and C++ are always 0-terminated. You can get aroud it this way: `char notermination[4]="Damn";`, but that is seldom useful for anything. BTW: Ask a new question if you have need of more information. But preferably search this site with appropriate keywords first. Best of course would be figuring it out from the standard itself. – Deduplicator Mar 31 '14 at 14:36

4 Answers4

6

Use a std::string to read from cin. Then you do not need to know in advance how big your buffer needs to be.

std::string input;
cin >> input;
cout << intput;

If you need a C-style array you can do:

const char* cstyle = input.c_str();

If you use a C-style string, the last character is always the null terminator '\0' to indicate the end of the string. This is important to know where your sequence of characters ends.

Some example:

char* text = "hello"; // the compiler puts an extra '\0' at the end
std::string str("hello"); // does not have a null terminator! (before C++11)
str.c_str(); // this returns "hello\0" with a null terminator
Danvil
  • 22,240
  • 19
  • 65
  • 88
  • So, `std::string` is more convenient, but `char[]` is more performant. Before you decide on chucking abstractions for that reason, measure and provide an ironclad case. – Deduplicator Mar 28 '14 at 17:22
  • `std::string` does store a terminating 0, always, just so 'c_str()` can be constant. – Deduplicator Mar 28 '14 at 17:24
  • 1
    @Deduplicator: This is not true before C++11. See here: http://stackoverflow.com/questions/11752705/does-string-contain-null-terminator – Danvil Mar 28 '14 at 17:32
  • Thanks, but anyway: AFAIK no implementation ever used that leeway, and I don't want to think about what all would have broken if any did. – Deduplicator Mar 28 '14 at 17:38
  • Well it is/was quite important to not assume that `const char* p = str.begin();` gives a sequence with a null-terminator. But if you use `c_str()` you are safe. – Danvil Mar 31 '14 at 09:20
1

There are two ways of declaring a string in C++:

char name[41];

or

string name;

One main difference between these is that there is always a \0 character at the end of the character array to signify the end of it, so there is an extra cell required. Using string would be more convenient as you don't have to care about the length of the string. (And you can also use many build-in functions from the string library)

Check this out: Difference between string and char[] types in C++

Community
  • 1
  • 1
Pingu
  • 646
  • 1
  • 5
  • 19
  • Actually, even though C++ basicstring<> (string, wstring, ...) uses counted strings, they are also guaranteed to be null-terminated. – Deduplicator Mar 28 '14 at 17:19
  • std::basic_string does not use reference counting in MSVC, and even in GCC, the behaviour will perhaps change sooner or later due to C++11 practically forbidding reference-counted strings. – Christian Hackl Mar 28 '14 at 17:53
0

The answer is that strings stored in character arrays, raw strings, are terminated with the null character ('\0'). This control character signals the end of the string. This terminator is useful because the length of the string doesn't need to be stored explicitly. It's also useful because strings of any length that can fit in the array are allowed. In this situation, it's useful to have a marker for the end of the string. This question should prove useful in understanding the subject further.

batbrat
  • 5,155
  • 3
  • 32
  • 38
0

A C-style string is an array of chars, the end of which is marked by a NUL terminator (i.e. a char having all its bits set to 0).

So, the string "Hi" looks like this in memory:

+-----+-----+-----+
|  H  |  i  | NUL |
+-----+-----+-----+

As you can note, a string of 2 characters ("Hi") actually requires 3 (i.e. 2+1) characters, including the NUL terminator.

This is why a C-style string of 40 characters requires an array of 41 (i.e. 40+1) characters, because it must include room for the NUL terminator.


As a side note, I'd suggest using a robust and convenient string class in C++ (e.g. std::string), instead of raw C-style arrays of characters with a NUL terminator.
If you use a string class, you'll make your code simpler, and you'll help yourself avoiding several potential security problems (e.g. buffer overruns) that are more likely to happen with raw C-style strings.

This would work just fine for string input in C++:

#include <iostream> // For std::cin/std::cout
#include <string>   // For std::string

....

std::string name;
std::cin >> name;                // Input
std::cout << name << std::endl;  // Output
Mr.C64
  • 41,637
  • 14
  • 86
  • 162
  • Thanks for the answers, I didn't expect so much great information in such short time. Just 2 questions came up in my mind: Who is in charge of inserting the NULL terminator at the end of the string? What happens with the "\n" after I press Enter? Thanks again. – Mark Renton Mar 29 '14 at 05:17
  • @MarkRenton: You're welcome. The `NUL` terminator is set by C functions like `strcpy()` in the destination strings; the `NUL` terminator is managed by the `std::string` class if you use that; the `NUL` terminator is automatically inserted by the C/C++ compiler if you define the string as in `char s[] = "hello";`. When you read the string using `cin` as in `string s; cin >> s;`, the `'\n'` is discarded (it's not stored in the read string). – Mr.C64 Mar 29 '14 at 14:54
  • @MarkRenton: BTW: If you find the answers in this thread helpful, you may want to upvote all of them as a good StackOverflow citizen, and mark the best reply as answer. – Mr.C64 Mar 29 '14 at 14:55