0

In high school I've studied basic C/C++ (it basically was C with cin and cout - those were the only C++ things, so I'd rather say I've been studying C in my high school time)

Now that I'm in college, I have to transition to C#.

I'm currently trying to make this C program in C#.

int main()
{
    int array[100];
    for (int i = 0; i < 5; i++)
    {
        cin >> array[i];
    }
    for (int i = 0; i < 5; i++)
    {
        cout << array[i] << " ";
    }
}

Here is how I tried to write it using C#:

using System;
using System.Linq;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] array = new int[100];
            for (int i = 0; i < 3; i++)
            {
                array[i] = Convert.ToInt32(Console.ReadLine());
            }
            for (int i = 0; i < 3; i++)
            {
                Console.WriteLine(array[i]);
            }
        }
    }
}

and it's kind of similar but it has a problem that I don't know how to fix.

In C, building that program, I could've entered data like this: c-photo In C#, I can't, because I'm getting an exception: c#-photo

I kind of understand what's happening - in C#, using Console.ReadLine() reads that line as a string, and then it tries to convert into an integer.

That does fail because of the spaces between the digits - "1 2 3".

But in C this works, because cin works differently, I guess. (I don't know how though and at this point I don't care anymore, I probably won't be using C/C++ anymore).

How can I replicate this behavior of the C program in the C# program so I can enter data as I did in the pic?

TylerH
  • 20,799
  • 66
  • 75
  • 101
  • 1
    Use `String.Split` to convert your string into an array of strings and then use `Int.Parse` on each individual string to convert to an int. – Matt Burland Oct 12 '20 at 12:53
  • And what happens if the user enters each number on a different line? In C I didn't have to take care of those situation separately (if the numbers are entered on each line, or all of them on all line, ect.). That's the behavior I want here. –  Oct 12 '20 at 12:56
  • this could help you [enter link description here](https://stackoverflow.com/questions/24443827/reading-an-integer-from-user-input) – Liz Oct 12 '20 at 12:58
  • 2
    Correct me if I'm wrong, but doesn't `cin >> array[i]` put the next `char` at `array` offset `i`? Because if so, then `cin >> ...` is more equivalent to `var ... = Console.ReadKey().KeyChar` which returns the individual character pressed, which you can then convert to an int with [`int.TryParse`](https://learn.microsoft.com/en-us/dotnet/api/system.int32.tryparse?view=netcore-3.1) to ignore newlines – MindSwipe Oct 12 '20 at 13:00
  • `ReadLine` reads _a line_. I.e. it reads up to a LF. If you want to read multiple lines, then you'd need to `ReadLine` multiple times and you'd have to have some kind of control that lets your program know when the user is done entering data. It's not clear to me how your C program actually did this. (actually, I guess it's just that it stops after five, got it) – Matt Burland Oct 12 '20 at 13:00
  • 1
    Take a look at the [`Console.ReadKey-Method`](https://learn.microsoft.com/en-gb/dotnet/api/system.console.readkey?view=netcore-3.1). This ready the input one by one. Then pair it with a `Int32.TryParse(...)` and you can get each digit seperately like in C. – Chrᴉz remembers Monica Oct 12 '20 at 13:02
  • It would probably be helpful if you more fully specify what this program is _supposed_ to do. Because in your screen shots of both programs you are only typing numbers on a single line. If it's supposed to support entering numbers on different lines, then your question should probably specify that. – Matt Burland Oct 12 '20 at 13:02
  • But as @MindSwipe and @Chriz both suggest, you could use `ReadKey`. Then you could just filter (ignore) any non-numeric characters (spaces, line feeds, etc) – Matt Burland Oct 12 '20 at 13:05

2 Answers2

1

The main problem here is that you're using Console.ReadLine instead of Console.ReadKey. cin >> array[i] will attempt to get the next int from stdin (thanks @UnholySheep), not the next line, so the equivalent of it would be Console.ReadKey().KeyChar with manual type conversion.

Now, there are multiple ways of converting a char to an int in C#, but casting isn't one as it would result in wrong conversions (in C# (int) '1' == 49, proof). My preferred way is int.TryParse(char.ToString(), out int number), but some people use different methods.

Edit: This will only handle single digit input correctly. If you need multi digit input, see the end of the answer.
This means, your code turns into this:

var array = new int[5];
for (var i = 0; i < 5; i++)
{
    var read = Console.ReadKey().KeyChar.ToString();
    if (int.TryParse(read, out var number))
        array[i] = number;

    Console.Write(" ");
}

foreach (var element in array)
{
    Console.Write("${element} ");
}

Note that I emulated the space between your input by writing an empty space in between every Console.ReadKey call. I also decided to foreach over the array as well as used string interpolation ($"{...} ...") to print the element with a space next to it.
If you want to manually enter the spaces, you can leave out the Console.Write(" ");, but then be aware that the array will contain a number only every other element, and the rest will contain 0 (default value of int)


To correctly handle multi digit input, you can either:

  1. Use Console.ReadLine and live with the fact that multiple inputs need to come on different lines
    or
  2. Use some botched together method to read the next int from the Console. Something like this:
public static int GetNextInt()
{
    var totalRead = new List<char>();

    while(true)
    {
        var read = Console.ReadKey().KeyChar;
        if (!char.IsDigit(read))
        {
            if (totalRead.Count > 0)
                break;
        }
        else
            totalRead.Add(read);
    }

    if (totalRead.Count == 0)
        return -1;

    return int.Parse(new string(totalRead.ToArray()));
}

This will try it's hardest to get the next int. Some test cases are:

+---------+-------------------+
|  Input  |    Parsed int     |
+---------+-------------------+
| "123\n" | 123               |
| "123a"  | 123               |
| "a123a" | 123               |
| "a\n"   | Continues parsing |
| "\n"    | Continues parsing |
+---------+-------------------+

There is currently some redundant code, but you can remove on or the other line depending on what you want.

  1. Do you want the current functionality?
    Then you can safely remove if (totalRead.Count == 0) return -1;

  2. Do you want the method to return -1 if the first entered character isn't a number?
    The you can safely remove if (totalRead.Count > 0) but keep the break.

My goal with this wasn't to 1:1 copy the C++ functionality of std::cin >> ..., but to come close to it.

MindSwipe
  • 7,193
  • 24
  • 47
  • *"`cin` gets the next character from `stdin`*" - that is not really correct. `std::cin` (more precisely `std::istream`) overloads `operator>>` to call specific functions depending on the type of the parameter: https://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt. For `int` it will attempt to extract an integer from the user input – UnholySheep Oct 12 '20 at 13:23
  • Thanks @UnholySheep, I'm not very well versed in C/C++ and couldn't find the reference when I searched for it – MindSwipe Oct 12 '20 at 13:35
  • Mind you that with this information your solution is not correct. Your code only handles single-digit numbers, while the C++ code also handles integer numbers that have more than one digit. I'm not sure if there is a simple built-in library method in C# that is exactly equivalent to C++'s `std::cin` functionality though – UnholySheep Oct 12 '20 at 13:42
  • I noticed that too, after posting the answer. I'm currently working on something that will work with multi digit numbers – MindSwipe Oct 12 '20 at 13:50
  • So there is no built-in method equivalent with C++'s cin. Thanks for your answer. –  Oct 12 '20 at 15:53
0

This does exactly what you want, what you need is Console.Read() function :

    public static void Main(string[] args)
    {
        int[] array = new int[100];
        int index = 0;

        for (int i = 0; i < 3; i++)
        {
            string word = string.Empty;
            bool isNew = true, assigned = false;
            while (isNew)
            {
                char read = (char)Console.Read();

                if (!char.IsDigit(read))
                {
                    if (isNew && assigned)
                    {
                        array[index++] = int.Parse(word);
                        isNew = false;
                    }
                }
                else
                {
                    word += read;
                    assigned = true;
                }
            }
        }

        for (int i = 0; i < 3; i++)
        {
            Console.Write(array[i] + " ");
        }

        Console.WriteLine();
    }

You can also take a look at :

https://nakov.com/blog/2011/11/23/cin-class-for-csharp-read-from-console-nakov-io-cin/

AnGG
  • 679
  • 3
  • 9
  • It works only for one digit numbers, unfortunately :( –  Oct 12 '20 at 15:52
  • @OctavianNiculescu are you sure ? for me it works for any input , for example 1 2 3 works, 1 2 3 4 5 works – AnGG Oct 12 '20 at 17:01
  • It doesn't work for numbers such as 10 10 10. That's what I mean by one digit number :) If the number is greater than 9, it doessns't work properly. –  Oct 12 '20 at 17:57
  • Now its works for integers and i think as same as in c++ – AnGG Oct 13 '20 at 09:54