1

I am trying to achieve the following:

User enters 100 numbers and then the numbers are printed in 3 columns.

This is what I have so far, it works but it does not print the last value of the array.

What am I doing wrong?

    static void Main(string[] args)
    {
        int digit = 0;
        const int LIMIT = 100;
        int[] row = new int[LIMIT];

        for (int i = 0; i < row.Length; i++)
        {
            Console.WriteLine("Geef getal nummer " + (i + 1) + " in: ");
            digit = int.Parse(Console.ReadLine());

            row[i] = digit;
        }

        for (int i = 0; i < row.Length - 2; i+=3)
        {               
           Console.WriteLine(row[i] + "\t" + row[i + 1] + "\t" + row[i + 2]);
        }
    }
7
  • i += 3 might be a problem. Since 99 < 100 - 2 will false. Commented May 28, 2014 at 8:14
  • Try printing out the numbers individually and inserting a line break on every third number (use a temporary counter). Another hint: 3 doesn't go into 10 evenly. Commented May 28, 2014 at 8:15
  • do you really want to enter 100 numbers (by the way, not fool-proof) manually just to print them out again? Why not 2 numbers? Why the magic number, and why not forget about loops? Commented May 28, 2014 at 8:17
  • 1
    @DmitryLedentsov I imagine the reason Sam's not "forget[ting] about loops" is because OP is a novice who is learning the basics. Commented May 28, 2014 at 8:20
  • yeah on my local machine I am using 10 as LIMIT, just that I do not have to insert 100 number :P Commented May 28, 2014 at 8:26

8 Answers 8

1

Use this print instead

for (int i = 0; i < row.Length; i++)
{
   Console.Write(row[i] + "\t");
   if (i % 3 == 2)
       Console.WriteLine();
}
Sign up to request clarification or add additional context in comments.

1 Comment

@Sam i % 3 produces the number of the current column (starting with 0 for the first column). If there are 3 columns, then the last column would be column 2, and you should add a newline each time you reach the last column. Personally, I would recommend storing the number of columns as a constant const int numCols = 3 and instead of i % 3 == 2, use i % numCols == numCols - 1.
0

Your issue is that you don't simply use Console.Write, and try to write your lines in one shot.

In fact, it would be even cleaner to use a StringBuilder here.

Replace

for (int i = 0; i < row.Length - 2; i+=3)
{               
   Console.WriteLine(row[i] + "\t" + row[i + 1] + "\t" + row[i + 2]);
}

by

StringBuilder sb = new StringBuilder();
int count = 0;
for (int i = 0; i < row.Length; i++)
{
    count++;
    if (count == 3)
    {
        sb.AppendLine(row[i])
        count = 0;
    }
    else
        sb.Append(row[i]).Append('\t');
}

Console.WriteLine(sb.ToString());

I think it's pretty explicit, but if you need clarifications, feel free to ask. Of course, the use of count here is pretty scholar, a real program could use % operator, like shown in other answers.

Comments

0

You have wrong condition in for loop. If you don't mind LINQ, you can use the following:

foreach (string s in row.Select((n, i) => new { n, i })
                        .GroupBy(p => p.i / 3)
                        .Select(g => string.Join("\t", g.Select(p => p.n))))
    Console.WriteLine(s);

If you're not ok with LINQ, you can do this:

int colIndex = 0;
foreach (int n in row)
{
    Console.Write(n);
    if (colIndex == 2)
        Console.WriteLine();
    else
        Console.Write('\t');
    colIndex = (colIndex + 1) % 3;
}

Comments

0

jonavo is correct. after 96+3 = 99 and you have done row.length-2, change it to row. length+2. and in print dont print if the i+1 or I+2 >= max

1 Comment

for (int i = 0; i < row.Length - 2; i+=3) { Console.WriteLine(row[i] + "\t" + row[i + 1] + "\t" + row[i + 2]); }
0

It doesn't print it because 100 is not evenly divisible by 3 and your for-loop increases the variable by 3 on each iteration, so the last element wil be skipped.

Maybe this after the loop:

int rest = row.Length % 3;
if(rest > 0)
   Console.WriteLine(row[row.Length - rest] + "\t" + row.ElementAtOrDefault(row.Length - rest + 1));

1 Comment

This will throw an exception if LIMIT is divisible by 3.
0

Its because of your index. Your running index i goes from

0,      3,      6,      9,       ...   96,       99

So this would output the array positions:

0,1,2   3,4,5   6,7,8   9,10,11  ...   96,97,98  99,100,101 (index out of bounds)

row.Length equals 100, so your loop-condition (i < row.Length - 2) is correct, but even better would be (i < row.Length - 3).

So your problem is how to print the last number... You see, you have 3 columns for 100 digits. This makes 33 rows and than there is one digit left.

Maybe you just add some Console.WriteLine(row[row.Length-1]); beneeth your loop.

Comments

0

Looks like you've got a lot of options at your disposal. Here's an approach using nested loops:

int numCols = 3;
for (int i = 0; i < row.Length; i += numCols)
{               
    for (int j = i; j < i + numCols && j < row.Length; j++)
    {
        Console.Write(row[j] + "\t");
    }
    Console.WriteLine();
}

Comments

0

Try this code.

Using this loop you can also change the number of rows/columns without code changes. Also, using the temporary buffer you output to the console an entire row at a time.

    static void Main(string[] args)
    {
        int digit = 0;
        const int LIMIT = 10;
        const int COLS = 3;
        int[] row = new int[LIMIT];

        for (int i = 0; i < row.Length; i++)
        {
            Console.WriteLine("Geef getal nummer " + (i + 1) + " in: ");
            // Re-try until user insert a valid integer.
            while (!int.TryParse(Console.ReadLine(), out digit))
                Console.WriteLine("Wrong format: please insert an integer number:");
            row[i] = digit;
        }

        PrintArray(row, COLS);

        // Wait to see console output.
        Console.ReadKey();
    }

    /// <summary>
    /// Print an array on console formatted in a number of columns.
    /// </summary>
    /// <param name="array">Input Array</param>
    /// <param name="columns">Number of columns</param>
    /// <returns>True on success, otherwise false.</returns>
    static bool PrintArray(int[] array, int columns)
    {
        if (array == null || columns <= 0)
            return false;
        if (array.Length == 0)
            return true;

        // Build a buffer of columns elements.
        string buffer = array[0].ToString();
        for (int i = 1; i < array.Length; ++i)
        {
            if (i % columns == 0)
            {
                Console.WriteLine(buffer);
                buffer = array[i].ToString();
            }
            else
                buffer += "\t" + array[i].ToString();
        }

        // Print the remaining elements
        if (array.Length % columns != 0)
            Console.WriteLine(buffer);

        return true;
    }

Just for completeness

Note that int.Parse(Console.ReadLine()) can throw an Exception if unexpected characters are typed. It's better to use int.TryParse() as documented here. This method don't throw an exception but return a boolean that report a successful conversion.

while (!int.TryParse(Console.ReadLine(), out digit))
    Console.WriteLine("Wrong format: please insert an integer number:");

This code tell the user that the typed string can't be interpreted as an integer and prompt again until a successful conversion is done.

9 Comments

Although it's an edge case, I would suggest having this handle the case when LIMIT is 0. Currently, it will throw an exception in that situation.
When asked LIMIT is a constant so it is a value known a priori by the coder. A LIMIT of 0 make all the code unneded. For this reason I not checked against LIMIT value. Again, this is clearly a coding exercise and I wanted to answer in the clearest possible way.
I don't think it's that hard to imagine a situation where the code is refactored so that LIMIT is a varying parameter that is passed in from somewhere. Or maybe the first half of the code is changed so that instead of taking in a pre-decided number of values, it takes in user input until the user indicates a stop value (and the user could stop before entering any values). Well-written code should not be vulnerable to changes of this nature, and if you do proper bounds-checking, other parts of the code can change without breaking your part. None of the other answers here has this flaw.
@JLRishe no, is not hard but it's not what was originally asked for (the for loop problem).
Of course it's not what was originally asked for, because it's a problem that you created! You fixed one issue and introduced a new one. OP's question is about how to print an array in three columns, and from that more general perspective, your code is broken because it will crash if it is run on an empty array. We happen to know in this specific case that the array will be nonempty, but we shouldn't assume that. I advise you to think outside of the box and provide answers that are applicable to a broader context and not just the specific parameters of the original question.
|

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.