0

I know that there are already several questions answered about this topic but none of them could help me solve my problem. Please, have in mind that I have just started learning C++ Programming.

I am creating a program that reads a text and then displays it in N rows x M columns (entered by the user). So, if the user writes HarryPotter and wants it to be displayed in a 3 x 4 array it should look something like this:

H a r r
y P o t
t e r

I have already manage to do so with this code:

cout << "Number of rows: ";
cin >> nr;
cout << "Number of columns: ";
cin >> nc;
cout << "Type in text: ";
cin >> text;

char letters[100][100];

for (int row = 0; row < nr; row++)
{
    for (int col = 0; col < nc; col++)
    {
        letters[row][col]= text [i];
        i++;
    }   
}

cout << "Print array: " << endl;
for (int row = 0; row < nr; row++)
    {
        for (int col = 0; col < nc; col++)
        {
            cout << letters[row][col];
        }

    cout << "\n";
    }

And it works fine until the user writes more than one word. For example instead of HarryPotter he writes Harry Potter (I think that the blank spaces between the words is what creates the problem). Do you know why this happens and how can I solve it? Thank you very much.

4
  • 1
    How is the variable text defined? And what to do iif the total elements of the two dimensional array is greater than the number of characters in text? Commented Nov 13, 2016 at 21:37
  • you should also add null terminated to to the end of the input text Commented Nov 13, 2016 at 21:40
  • I suspect std::getline will soon be in your future. Commented Nov 13, 2016 at 21:41
  • 1
    you should use cin.getline() like here Commented Nov 13, 2016 at 21:42

3 Answers 3

1

The problem is that the operator >> stops entering a string when a white space character is encountered in the stream. You should use standard function std::getline instead.

Take into account that to display a string there is no need to define an array. The task can be done without using an array.

Here is a demonstrative program.

#include <iostream>
#include <string>
#include <limits>
#include <algorithm>

int main() 
{
    while ( true )
    {
        std::cout << "Number of rows (0 - exit): ";

        unsigned int rows;
        if ( not ( std::cin >> rows ) or ( rows == 0 ) ) break;

        std::cout << "Number of columns (0 - exit): ";

        unsigned int cols;
        if ( not ( std::cin >> cols ) or ( cols == 0 ) ) break;

        std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );

        std::cout << "Type in text: (Enter - exit): ";

        std::string text;
        std::getline( std::cin, text );
        if ( text.empty() ) break;

        std::cout << std::endl;

        std::string::size_type n = text.size();

        n = std::min<std::string::size_type>( n, cols * rows );

        for ( std::string:: size_type i = 0; i < n; i++ )
        {
            std::cout << text[i];

            std::cout << ( ( i + 1 ) % cols == 0 ? '\n' : ' ' );
        }

        std::cout << std::endl;
    }

    return 0;
}

Its output might look like

Number of rows (0 - exit): 3
Number of columns (0 - exit): 4
Type in text: (Enter - exit): HarryPotter

H a r r
y P o t
t e r

Number of rows (0 - exit): 2
Number of columns (0 - exit): 6
Type in text: (Enter - exit): HarryPotter

H a r r y P
o t t e r 

Number of rows (0 - exit): 6
Number of columns (0 - exit): 2
Type in text: (Enter - exit): HarryPotter

H a
r r
y P
o t
t e
r 

Number of rows (0 - exit): 4
Number of columns (0 - exit): 4
Type in text: (Enter - exit): Antonella Masini 

A n t o
n e l l
a   M a
s i n i

Number of rows (0 - exit): 0

You may substitute this statement

if ( not ( std::cin >> rows ) or ( rows == 0 ) ) break;

for this statement

if ( !( std::cin >> rows ) || ( rows == 0 ) ) break;

if the compiler does not compile the first statement. If you use MS VC++ then in the properties of the project you should switch off using of the language extensions (C++, language), and the statement will be compiled.

Sign up to request clarification or add additional context in comments.

6 Comments

Hi, thank you for the response but when I put it in my code it says that it doesn't identify the variable not...
@AntonellaMasini What compiler do you use?
@AntonellaMasini In any case you can just write if ( !( std::cin >> rows ) || ( rows == 0 ) ) break;
Just one more question (if you don't mind) what is this for? cin.ignore(numeric_limits<streamsize>::max(), '\n'); And do you think that over this code I could build some lines that will allow the user to replace a word in the text they have previously typed?
And what does this mean? cout << ((i + 1) % cols == 0 ? '\n' : ' '); sorry for so many questions!
|
1

cin will consider the space between Harry and Potter as a delimiter and only save Harry in text.

With cin.getline, the entire line is read until the Enter key is pressed. Therefore, with cin.getline(text, sizeof(text)), Harry Potter will be saved in text.

3 Comments

Thank you for the answer but do I just need to replace my "cin >> text;" with "cin.getline(text, sizeof(text));" ? Because I tried that and it doesn't let me run the program because it says that "no instance of overloaded function... matches the argument list"...
You can use getline(cin , string) as well.
cin.getline(czTmp, row * col) that you have used should be fine. czTmp should ideally be allocated (row*col) bytes.
0

you can use a dynamic array of characters so it is sized at run-time as the user input of rows and columns:

#include <iostream>
using namespace std;

int main()
{
    int row, col;

    cout << "Row: ";
    cin >> row;
    cout << "Col: ";
    cin >> col;

    char** cText = new char*[row];
    for(int i(0); i < row; i++)
        cText[i] = new char[col];

    cin.sync(); // clearing the input buffer
    cout << "Text: ";

    char czTmp[100];
    cin.getline(czTmp, row * col); // getting user input text which fits to our 2d array of chars

    int k = 0;
    for(int i = 0; i < row; i++)
    {
        for(int j = 0; j < col; j++)
        {
            cText[i][j] = czTmp[k]; // inputting our array
            k++;
        }
    }

    cText[row - 1][col - 1] = '\0'; // adding a null-terminator because it is not added automatically

    // printing our array
    for(int i = 0; i < row; i++)
    {
        for(int j(0); j < col; j++)
            cout << cText[i][j];
        cout << endl;
    }

    // don't forget to free memory created by new

    for(int i(0); i < row; i++)
        delete[] cText[i];
    delete[] cText;
    cout << endl << endl;
    return 0;
} 

1 Comment

Thank you for the answer but when I used your code it crashed after I entered the number of columns, do you know why this is?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.