Home > Software engineering >  How would I write a program that reads from a standard input and outputs only 6 characters to a line
How would I write a program that reads from a standard input and outputs only 6 characters to a line

Time:09-30

For example if the input was:

My name is Alex and
I also love coding

The correct output should be:

1:My nam  
1:e is A
1:lex an
1:d
2:I also 
2: love 
2:coding                         

So far I have this

int  main () {
  string i;
  i.substr(0,6);
  while (getline(cin, i)) {
    cout << i << endl;
  }
}

CodePudding user response:

Using ranges, what you ask is almost as easy as

    auto result = view | split('\n') | transform(chunk(6));

where view represents somehow the input, | split('\n') splits that input in several lines, and | transform(chunk(6)) transforms each line by splitting it in chunks of 6 chars. The result is therefore a "range of ranges of chunks", on which you can loop with a double nested for.

Here's a full example:

#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/chunk.hpp>
#include <range/v3/view/istream.hpp>
#include <range/v3/view/split.hpp>
#include <range/v3/view/transform.hpp>

// Comment/uncomment the line below
//#define FROM_FILE

using namespace ranges;
using namespace ranges::views;

int main() {
    // prepare a path-to-file or string buffer
#ifdef FROM_FILE
    std::string path_to_file{"/path/to/file"};
#else
    std::basic_stringbuf<char> strbuf{"My name is Alex and\nI also love coding"};
#endif

    // generate an input stream from the file or the string buffer
#ifdef FROM_FILE
    std::ifstream is(path_to_file);
#else
    std::istream is(&strbuf);
#endif

    // prevent the stream from skipping whitespaces
    is >> std::noskipws;

    // generate a range view on the stream
    ranges::istream_view<char> view(is);

    // manipulate the view
    auto out_lines = view | split('\n') // split at line breaks
                          | transform(chunk(6)); // split each in chunks of 6

    // output
    int index{};
    for (auto line : out_lines) {
          index;
        for (auto chunk_of_6 : line) {
            std::cout << index << ':'
                      << (chunk_of_6 | to<std::string>)
                      << std::endl;
        }
    }
}

CodePudding user response:

First I suggest that you give your variables meaningful names. i isn't good for a variable you use to read lines from std::cin. I've changed that name to line in my example below.

You are on the right track with i.substr(0,6); but you've placed it outside of the loop where i is empty - and you don't print it.

You are also supposed to prepend each line with the line number but that part is completely missing.

You have also missed that you should print the next 6 characters of the read line on the next line until you've printed everything that you read.

Here's an example how that could be fixed:

#include <iostream>
#include <string>

int main() {
    unsigned max_len = 6;

    std::string line;

    for(unsigned line_number = 1; std::getline(std::cin, line);   line_number) {

        // loop until the read line is empty:
        while(!line.empty()) {

            // print max `max_len` characters and prepend it with the line number:
            std::cout << line_number << ':' << line.substr(0, max_len) << '\n';

            // if the line was longer than `max_len` chars, remove the first
            // `max_len` chars:

            if(line.size() > max_len) {
                line = line.substr(max_len);
            } else {                         // otherwise, make it empty
                line.clear();
            }
        }
    }
}
  •  Tags:  
  • c 11
  • Related