Equivalent of this C/C++ program in C# - c#

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:
In C#, I can't, because I'm getting an exception:
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?

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:
Use Console.ReadLine and live with the fact that multiple inputs need to come on different lines
or
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.
Do you want the current functionality?
Then you can safely remove if (totalRead.Count == 0) return -1;
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.

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/

Related

Find lowest period of a string (given array of string) to create a substring and return an array of integers

So I was looking through interview questions that unfortunately didn't have any solutions, and one of them seemed interesting (mostly because I had no idea how to do it). However now I have hit a roadblock and am not sure how to proceed. The objective of the program is to take any amount of strings and spit out the periods of the lowest repeated characters to form the substring in an integer array.
Ex: "abbabbabba","abcdabcddabcdabc","aeiouuaeioouaei" would be 5, 8, 5.
I kind of looked at it as doing Indian runs. The first character runs to the front, if it equals the next character than continue running, etc.
This is the code I have compiled and I tried to take a look at the algorithm for finding periods as well (http://monge.univ-mlv.fr/~mac/REC/text-algorithms.pdf#page=345). I just can't seem to pinpoint the problem in the code
namespace Interview36{
public class PeriodicStrings
{
public static int[] process(string[] input)
{
if (input == null || input.Length == 0 || input[0].Length == 0)
{
Console.WriteLine("Result is null");
}
int length = 0;
int[] list = new int[input.Length];
for (int i = 0; i < input.Length; i++) {
while (i < input[i].Length)
{
if (input[i] == input[length])
{
length++;
list[i] = length;
i++;
}
else
{
if (length != 0)
{
length = list[length - 1];
}
else
{
list[i] = 0;
i++;
}
}
}
}
return list;
}
}
}
My best guess is that my logic is WAY off, or the loop isn't running through properly and I'm just not catching it in debug. Thank you in advance for any insight!

Current code to generate array filled with unique ints crashes

(this is a library)
The function GetUniqueInt is being called with (5, 5) as the variables.
Currently the code will stall unity to a complete halt, or crash my PC with a memory overflow error.
Does anyone have any ideas as to how I could prevent it from crashing or what is making it crash?
using UnityEngine;
namespace MajorSolution
{
public static class MajorMath
{
public static int[] GetUniqueInt(int intCount, int intLength)
{
int[] returnValue = new int[intCount];
int[] temp = new int[intLength];
for (int a = 0; a < intCount; a++)
{
string create = new string("create".ToCharArray());
switch (create)
{
case "create":
returnValue[a] = GetRandomInt(intCount);
goto case "check";
case "check":
bool alreadyTaken = false;
for (int c = 0; c < returnValue.Length - 1; c++)
{
if (returnValue[a] == returnValue[c])
{
// Already Taken!
alreadyTaken = true;
}
}
if (!alreadyTaken)
{
break;
}
else
{
goto case "create";
}
}
}
Debug.Log(returnValue);
return returnValue;
}
public static int GetRandomInt(int intCount)
{
int[] storage = new int[intCount];
int returnValue = 0;
for (int i = 0; i < intCount; i++)
{
storage[i] = (Mathf.FloorToInt(Random.Range(0, 9)) * (int)Mathf.Pow(10,i));
returnValue += storage[i];
}
return returnValue;
}
}
}
Edit I just realized I did not exactly answer the question of why it is bringing the PC to a halt because you have an infinite loop in the code.
The problem is occurring in the following lines of code, notice what is happening.
case "create":
returnValue[a] = GetRandomInt(intCount);
goto case "check";
In the above block of code you are generating a number and putting it in the returnValue array. Now you jump into your "check" block
case "check":
bool alreadyTaken = false;
for (int c = 0; c < returnValue.Length - 1; c++)
{
if (returnValue[a] == returnValue[c])
{
// Already Taken!
alreadyTaken = true;
}
}
In this block of code you are looping over the entire returnValue array including the value you just inserted in it. Basically you are looping over the array asking if a value that you just put in the array is in the array.
Without knowing exactly what you are trying to do with these methods, I will just make a simple fix suggestion with some minor cleanup
public static int[] GetUniqueInt(int count, int length)
{
var returnValue = new int[count];
var values = new HashSet<int>(); // Used to track what numbers we have generated
for (int i = 0; i < count; ++i)
{
// Generate the number and check to be sure we haven't seen it yet
var number = GetRandomInt(length);
while(values.Contains(number)) // This checks if the number we just generated exists in the HashSet of seen numbers
{
// We get here if the HashSet contains the number. If we have
// seen the number then we need to generate a different one
number = GetRandomInt(length);
}
// When we reach this point, it means that we have generated a new unique number
// Add the number to the return array and also add it to the list of seen numbers
returnValue[a] = number;
values.Add(number); // Adds the number to the HashSet
}
Debug.Log(returnValue);
return returnValue;
}
I did end up removing the using of intLength but from your posted code it was only used to declare a temp array which itself was never used. Based on that, I just removed it entirely.
Based on your comment I updated the fix to use intLength. I made one other minor change. I removed int from the variable names of count and length. Hungarian notation is a lot less common in C# code. Personally, I feel like the code is cleaner and easier to read without the Hungarian notation. The key is to use good variable names that express the intent or make it easier to follow. In this case count is the count (read total number) of numbers you want returned and length is the length of the number. You could consider maybe even renaming that to numberOfDigits to make it clearer that the idea is you are going to create a random number with that number of digits in it.

C# - HackerRank simpleArraySum

Now, I may get negative points because perhaps somewhere in vast internet there is already an answer to this but I tried to look for it and I simply couldnt find it.
The gist of the problem is that HackerRanks wants you to create an array with a size decided by the user, then have the user add its values (integers) and finally have the program sum its values.
There are plenty of ways to do it and I already know how to but my problem is that I just can't understand Hackerrank's code sample in C# it gave me. I commented the parts I don't understand, which is most of it:
static int simpleArraySum(int n, int[] ar) {
// Complete this function
int sum = 0;
foreach( var item in ar){
sum += item;
}
return sum;
}
static void Main(String[] args) {
//I know what this does
int n = Convert.ToInt32(Console.ReadLine());
//I am lost here, just why create a string array and add the split method?
string[] ar_temp = Console.ReadLine().Split(' ');
//I dont understand here neither, what is it converting? What is the parse for?
int[] ar = Array.ConvertAll(ar_temp,Int32.Parse);
//Why send the n when all you need is the array itself?
int result = simpleArraySum(n, ar);
Console.WriteLine(result);
}
I know some people hate HackerRank, and honestly, I do too but it does gives me some nice ways to test my limited skills in coding with c# and testing my logic. So, if there are better sites that helps you test your logic as a CS please share them with me.
Here is the code I made to solve this problem in Visual Studio but for some stupid reason Hackerrank wont accept it unless I make custom inputs:
//This code can be potentially shorter using the code commented further below.
//For practice's sake, it was made longer.
static int simpleArraySum(int[] arr_temp)
{
int total = 0;
foreach (var item in arr_temp)
{
total += item;
}
return total;
}
static void Main(String[] args)
{
int n = Convert.ToInt32(Console.ReadLine());
int[] arr_temp = new int[n];
for (int i = 0; i < n; i++)
{
arr_temp[i] = Convert.ToInt32(Console.ReadLine());
}
int result = simpleArraySum(arr_temp);
//int result = arr_temp.Sum();
Console.WriteLine(result);
Console.ReadLine();
}
You need to convert to string array since if you're on the main method, all it gets are string values from the argument list. To get the sum then you need to convert the string into a usable number / integer.
I agree that it doesn't make sense to send the first argument n in simpleArraySum because n is simply unused.
as for the part int[] ar = Array.ConvertAll(ar_temp,Int32.Parse); it simply tries to take in all the integers into the array. It is also risky because if you accidentally pass in a string then it will throw an error i.e. pass in "3 4 1 f" <- f will throw an exception, unless this is the desired behaviour.
Personally I think the main method should not be interested in getting involved too much with the data, the heavy lifting should be done in the methods. The better version perhaps would be to modify simpleArraySum and refactor that line in like:
static int simpleArraySum(string input)
{
String[] fields = input.Split(null);
List<int> vals = new List<int>();
foreach (string i in fields)
{
var j = 0;
if (Int32.TryParse(i, out j)) vals.Add(j);
}
int sum = 0;
foreach (var item in vals)
{
sum += item;
}
return sum;
}
I introduced the use of generic list because it's more readable if not cleaner, although the use of List might look overkill to some programmers and might not be as light weight as just using an array, hence on the other hand you can easily stick to using arrays except that it needs to be initialized with the length i.e. int[] vals = new int[fields.Length]; Roughly:
static int simpleArraySum(string input)
{
String[] fields = input.Split(null);
int[] vals = new int[fields.Length];
for (int i = 0; i < fields.Length; i++)
{
var j = 0;
if (Int32.TryParse(fields[i], out j)) vals[i] = j;
}
int sum = 0;
foreach (var item in vals)
{
sum += item;
}
return sum;
}
here my code i hope that helps
static int simpleArraySum(int[] ar,int count) {
if (count > 0 && count <= 10000)
{
if (count == ar.Length)
{
if (!ar.Any(item => (item < 0 || item >= 10000)))
{
return ar.Sum();
}
}
}
return 0;
}
and in main
int arCount = Convert.ToInt32(Console.ReadLine());
int[] arr = Array.ConvertAll(Console.ReadLine().Split(' '), arTemp => Convert.ToInt32(arTemp));
int result = simpleArraySum(arr, arCount);
Console.WriteLine(result);
since Array.ConvertAll() takes a string and convert it to one type array
int or float for example
For users still looking for a 100% C# solution: In above mentioned coding websites do not modify the main function. The aim of the test is to complete the function via the online complier.
using System.Linq;
public static int simpleArraySum(List<int> ar)
{
int sum = ar.Sum();
return sum;
}

How to base my Header on the Width of the Window W/O having to repeatedly write the same code

I'm about to pull my hair out. I've been trying to get this to work, but all I can come up with is a console screen that looks like this at the top:
+-------------------------------------------------------------------------------------------+
+
+
+
+
+
Are you ready to play Hangman? yes/no:
What I'm trying to do is have Pipes on the short sides of the rectangle at the top (6 rows in length) with '+' on each of the four corners, as well as "----" across the bottom (just as it is currently at the top). I've written this thing 40 different ways but I seem to keep getting the same result. And it seems like it should be easier than writing each stinking line.
So here's my code (I have hidden the unnecessary portions of the code):
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hangman
{
class Program
{
protected static int firstColumn;
protected static int firstRow;
protected static void headerWindow( string border, int posX, int posY)
{
try
{
Console.SetCursorPosition(firstColumn + posX, firstRow + posY);
Console.Write(border);
}
catch(ArgumentOutOfRangeException error)
{
Console.Clear();
Console.Write(error.Message);
}
}
//I created a method to perform this, so that I can have the program stay open for either 1) a new game or 2) just to see if I could do it. It works!
private static void printWord()
{
String[] myWordArrays = File.ReadAllLines("WordList.txt");
Random randomWord = new Random();
//int lineCount = File.ReadLines("WordList.txt").Count();
int activeWord = randomWord.Next(0, myWordArrays.Length);
string userSelection = "";
Console.WriteLine("Are you Ready to play Hangman? yes/no: ");
userSelection = Console.ReadLine();
if(userSelection == "yes")
{
//This runs through the randomly chosen word and prints an underscore in place of each letter - it does work
foreach(char letter in myWordArrays[activeWord])
{
Console.Write("_ ");
}
//This prints to the console "Can you guess what this 'varyingLength' letter word is?" - it does work.
Console.WriteLine("\n \nCan you guess what this "+ myWordArrays[activeWord].Length +" letter word is?");
Console.ReadLine();
}
else if(userSelection=="no")
{
Console.WriteLine("I'm sorry you feel that way. Press Enter to Exit the program!");
Console.ReadLine();
}
}
private static void headerFile()
{
Console.Clear();
firstColumn = Console.CursorLeft;
firstRow = Console.CursorTop;
int columnNumber = Console.WindowWidth - 1;
var xcoord = 0;
var ycoord = 0;
if(xcoord==0 && ycoord==0)
{
headerWindow("+",xcoord,ycoord);
Console.Write("");
xcoord++;
}
}
static void Main(string[] args)
{
headerFile();
printWord();
}
}
}
I need to point out that if you see multiples of the same thing, it's because I have commented and hid the long lines of code (in case I want to use it later). It was supposed to stay hidden, but apparently Ctrl+A,C copies even the collapsed text in the IDE.
Try this code out, I think it does what you need:
for(int i = 0; i < columnNumber; i++) // Loop across long length
{
headerWindow("-", i, 0); // Top line
headerWindow("-", i, 6); // Bottom line
}
for(int i = 0; i < 6; i++) // Loop across short length
{
headerWindow("|", 0, i); // Left side
headerWindow("|", columnNumber, i); // Right side
}
// Draw over corners with "+"
headerWindow("+", 0, 0);
headerWindow("+", 0, 6);
headerWindow("+", columnNumber, 0);
headerWindow("+", columnNumber, 6);
Output:
+------------------------------------------------------------------------------+
| |
| |
| |
| |
| |
+------------------------------------------------------------------------------+
It is intended to go in headerFile(). Also you should replace 6 with a constant called HEADER_HEIGHT or something similar for easy modification and readability.

for loop inside array terminating on second call

i have done coding in C# but not much inside the Console App (teacher is making us do an assignment in it)
I have a problem where my static method works fine the first time it is called (each question is asked), but the second time through the console closes. I need this function to execute 10 times and not sure why it wont. Here is what i have and thanks in advance!:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Lab2
{
class Program
{
//Create the arrays
static string[] questions = new string[5]; //For questions
static int[] tableHeader = new int[10]; //Table Header
static int[,] responses = new int[5, 10]; //For answers
//Int for the number of times the questions have been asked
static int quizCount = 0;
static int answer;
static bool isGoing = true;
static void Main(string[] args)
{
//Set the questions in an array
questions[0] = "On a scale of 1-10, how do you feel about the drinking age in Wisconsin?";
questions[1] = "On a scale of 1-10, how often do you drink a week?";
questions[2] = "On a scale of 1-10, how important is this class?";
questions[3] = "On a scale of 1-10, how would you rate this campus?";
questions[4] = "On a scale of 1-10, how would you rate this command prompt?";
while(isGoing)
Questions();
}
static void Questions()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine(questions[i]);
answer = Convert.ToInt16(Console.ReadLine());
responses[i, quizCount] = answer;
}
if (quizCount < 10)
{
Console.WriteLine("Enter more data? (1=yes, 0=no)");
int again = Console.Read();
if (again != 1)
Environment.Exit(0);
}
else
isGoing = false;
DisplayResults();
}
static void DisplayResults()
{
Console.WriteLine(tableHeader);
for (int i = 0; i < 5; i++)
{
for (int x = 0; x < 10; x++)
{
Console.Write(responses[i, x]);
}
Console.Write("\n");
}
}
}
}
First off Console.Read() returns an int representing the ascii value of what was entered. If the user enters 1, Console.Read() returns 49. (See this ascii table)
You could use Console.ReadKey()
Second, you need some fixes in the way you loop and ask to continue....
int again = Console.Read();
Your problem is here - Console.Read() returns the first character entered (as represented by its ASCII code), not the number you type in. I leave the solution for your homework.

Categories

Resources