-2

I am trying to read user entered data from the stream and then store it in a custom String class.

To my best knowledge, std::getline() can route data only to std::string , that is why I need to come up with something else, as my project is not allowed to use std::string class.

My code looks like this:

String street();
std::cout << "Street: "; std::cin >> std::noskipws;
char c='\0';
while(c!='\n'){
    std::cin >> c;
    street=street+c;
}std::cin >> std::skipws;
    
int bal=0;
std::cout << "Balance: "; std::cin >> bal;
nebulator0
  • 85
  • 8
  • If you read the documentation on [`std::noskipws`](https://en.cppreference.com/w/cpp/io/manip/skipws), you probably wouldn't have needed to ask this question. It won't skip leading whitespace and that's it. Just use `std::getline()`. You are claiming that `std::getline()` is out of play because of something you did. Undo that, and use the right tool for the job. – sweenish May 13 '22 at 16:30
  • @sweenish My project is not allowed to use std::string. To my best knowledge, std::getline() can route data only to std::string , that is why I need to come up with something else. – nebulator0 May 13 '22 at 16:54
  • So why in the world did you phrase your inability to use `std::getline()` the way you did? It's misleading at best. – sweenish May 13 '22 at 17:03
  • Edited my post. – nebulator0 May 13 '22 at 17:05
  • 1
    This doesn't address the question, but note that `String street();` declares a function named `street` that takes no arguments and returns a `String`. Just like `int f();`. – Pete Becker May 13 '22 at 17:19
  • 1
    The `std::cin >> c; street=street+c;` loop is a huge waste of time.. THat's simply a bad practice they shouldn't teach you do. How about declaring your own operator>> for `String`? `std::istream::getline` available for `cin` doesn't use `string`, it uses a character pointer, so you can create operator which uses that – Swift - Friday Pie May 13 '22 at 18:34
  • @Swift-FridayPie Thank you! This approach solves my issue! – nebulator0 May 14 '22 at 08:55

2 Answers2

2

To my best knowledge, std::getline() can route data only to std::string , that is why I need to come up with something else, as my project is not allowed to use std::string class.

Note that std::getline and std::istream::getline are two separate functions. The former will work with std::string while the latter will work with C-style strings (i.e. sequences of characters that are terminated by a null character).

Therefore, if you are not allowed to use std::string, then you can still use std::istream::getline, for example like this:

char line[200];
String street;

std::cout << "Street: ";

if ( std::cin.getline( line, sizeof line ) )
{
    //the array "line" now contains the input, and can be assigned
    //to the custom String class
    street = line;
}
else
{
    //handle the error
}

This code assumes that your custom class String has defined the copy assignment operator for C-style strings.

If it is possible that the lines will be larger than a fixed number of characters and you want to support such lines, then you could also call std::istream::getline in a loop:

char line[200];
String street;

std::cout << "Street: ";

for (;;)
{
    std::cin.getline( line, sizeof line );

    street += line;

    if ( std::cin.bad() )
    {
        //TODO: handle error and break loop, for example by
        //throwing an exception
    }

    if ( !std::cin.fail() || std::cin.eof() )
        break;

    std::cin.clear();
}

This code assumes that operator += is defined for class String.

This loop will continue forever until

  1. getline succeeds (i.e. it is able to extract (but not store) the newline character), or

  2. end-of-file is reached (eofbit is set), or

  3. an error occurs (badbit is set).

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • The downside to this approach is that it limits the max line length. If you need to handle variable-length lines with no max, like `std::getline()` does, then consider using `std::istream::get()` instead of `operator>>` to read individual characters until `'\n'` is reached. To avoid unnecessary memory reallocations, you can read into an intermediate `char[]` buffer, flushing that to the `String` object whenever the `char[]` fills up or `'\n'` is reached. – Remy Lebeau May 13 '22 at 18:43
  • @RemyLebeau: In my experience, reading one character at a time is rather inefficient. I have therefore added a solution which calls `getline` in a loop, instead. – Andreas Wenzel May 13 '22 at 20:28
1

You can use the C function "getchar()" to read a single character from standard input. This link describes it: https://www.ibm.com/docs/en/i/7.3?topic=functions-getc-getchar-read-character.

Here is my code:

String street=();
std::cout << "Street: ";
char c='\0';
while(c!='\n'){
    c = getchar();
    street=street+c;
}

int bal=0;
std::cout << "Balance: "; std::cin >> bal;
cout << street << endl;

I hope this will help you, and I recommend you make an independent function that will read line from standard input and whose return type will be "String". You can declare it as:

String readLine();

And I also recommend you to pay attention to that while loop because string that is obtained from that loop will have character '\n' at the end of it.

DimitrijeCiric
  • 446
  • 1
  • 10
  • You are linking to [platform](https://en.wikipedia.org/wiki/Computing_platform)-specific documentation of the function `getchar`, which contains information that does not apply to most other platforms. It would probably be better to refer to platform-neutral documentation, such as [this one](https://en.cppreference.com/w/c/io/getchar). – Andreas Wenzel May 13 '22 at 17:36
  • 3
    I am not sure if it is a good idea to mix C-style I/O with C++-style I/O, because this will only work when [std::ios_base::sync_with_stdio](https://en.cppreference.com/w/cpp/io/ios_base/sync_with_stdio) is true, unless the input stream is used exclusively for C-style I/O. It may be better to use [std::istream::get](https://en.cppreference.com/w/cpp/io/basic_istream/get) if you want to read a single character. – Andreas Wenzel May 13 '22 at 17:42