user963241
user963241

Reputation: 7048

Get size of input in console

How would you get the size input string to console or size of valid characters in buffer?

char buffer[100];
cin >> buffer;

I'm looking to put the '\0' where the input ends.

Upvotes: 2

Views: 24377

Answers (4)

WotJ Project
WotJ Project

Reputation: 1

Another option is to use gcount(), which is included in any istream subclass. It will return the length in bytes of the last input grabbed by istream, so you can then use it to index into the buffer and place a terminator.

char buffer[100] = {0};
std::cin >> buffer;

int length = std::cin.gcount();
buffer[length] = '\0';

However, this won't eliminate the risk of buffer overflow when using a char array- if you want to do that without using a string or other dynamic array, the easiest way is to encase it in a struct or class, and provide an operator overload that checks the length and breaks early if it gets too long, like so:

struct FixedBuffer {
    char buffer[100] = {0};  //initializes the buffer with/as null

    //note this ONLY works for this operator, not = or any other assignment method.
    friend std::istream& operator>>(std::istream& stream){
        size_t i = 0;

        while(i<99 && !stream.eof()){
            stream >> buffer[i];

            //failsafe return early if you've reached a terminator, but eof() isn't triggered.
            if(!buffer[i])
                return stream;

            i++;  //increment last, so the index below works without additional operations
        }
        stream.ignore();  //discards any input that wasn't grabbed (optional)
        buffer[i] = '\0';

        return stream;
    }
};

FixedBuffer fix;  //Instantiate it like this.
fix.buffer;  //Call it like this

This will store only up to 99 bytes into the buffer, and will always ensure the first byte after input is a terminator.

The way I prefer to do fixed strings like this is to write it with the terminator as a constant, like so:

struct {
    char buffer[99] = {0};
    const char terminator = '\0';
};

That way I will always get a compiler error if I accidentally overwrite it, which makes debugging easier. Note that in some situations, the entire struct may be placed in constants memory by the compiler. This shouldn't be an issue in practice if you're properly bounds-checking, but depending on your project, you may want to avoid it since it's Undefined Behavior.

You can build on this to add many more checks and safeguards to make a "safe" string class, which I think is a great project for anyone learning C++!

Upvotes: -1

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361812

Prefer using std::string, instead of char* or char[]. That makes such things easy! The problem with char buffer[100] is that if the size of input string is more than 100, then your cin >> buffer would invoke undefined behavior, as it would attempt to write beyond the array. This problem can easily be avoided if you use std::string.

std::string input;
cin >> input; //this can read string of any unknown size!
cout << "length of input string : " << input.size()<< endl;

You can also use input.length() instead of input.size(). They return the same value.

Online Demo : http://www.ideone.com/Wdo31

Upvotes: 9

selbie
selbie

Reputation: 104589

The question is moot. When the user types more than 100 characters, you have a buffer overrun. You may crash. If not, you got a security issue at best. You shouldn't do this. Read the input a character at a time, or use a safer string library. gets_s comes to mind if it's supported on your platform.

But in answer to your question, this might be what you need:

char buffer[100] = {}; // zero-init the entire array
int length = 0;
cin >> buffer;
length = strlen(buffer); // length is the length of the string

Upvotes: 3

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272822

You don't need to (and quite possibly, can't). Instead, use a std::string instead of a char buffer.

Upvotes: 2

Related Questions