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.
Related
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/
I am having an issue with picking randomly from a list. When I run the program, it keeps writing the same string over and over again when I want it to come up with a different random string each time. Here is an example:
using System;
using System.Collections.Generic;
namespace List
{
class Program
{
static void Main(string[] args)
{
var letterList = new List<string>
{
"A","B","C","D"
};
Random r = new Random();
int letterListIndex = r.Next(letterList.Count);
for (int i = 0; i < 10; i++) {
Console.WriteLine(letterList[letterListIndex]);
}
}
}
}
For Example: When I run this code it would write "B" 10 times. I want it to come up with 10 different letters every time. I know that you could just write:
int letterListIndex1 = r.Next(letterList.Count);
int letterListIndex2 = r.Next(letterList.Count);
int letterListIndex3 = r.Next(letterList.Count);
Console.WriteLine(letterList[letterListIndex1]);
Console.WriteLine(letterList[letterListIndex2]);
Console.WriteLine(letterList[letterListIndex3]);
But I wanted to know if there was an easier way to do so.
Thanks.
You should put your letterListIndex variable inside for loop
for (int i = 0; i < 10; i++) {
int letterListIndex = r.Next(letterList.Count);
Console.WriteLine(letterList[letterListIndex]);
}
Otherwise you get the same index every time.
You need to put
int letterListIndex = r.Next(letterList.Count);
inside the for loop.
you can use below code
for (int i = 0; i < 10; i++) {
Console.WriteLine(letterList[r.Next(letterList.Count)]);
}
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;
}
I'm new to c# so be ready for some dumb questions.
My current task is to find a score from an array where the highest/lowest scores have been taken away, and if the highest/lowest occur more than once (ONLY if they occur more than once), one of them can be added:
eg. int[] scores = [4, 8, 6, 4, 8, 5] therefore the final addition will be 4+8+6+5 = 23.
Another condition of the task is that LINQ cannot be used, as well as any of the System.Array methods. (you can see by my previously ask questions that has been a bit of a pain for me, since I solved this with LINQ in less than 5 minutes).
So here is the problem: I have working code the solves the problem but the task requires multiple methods/functions, so I cannot receive full marks if I have only 3 methods (including main). I have been trying to restructure the program but with all sorts of issues. Here is my code (just so I can explain it better):
using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Scoring {
class Program {
static int highOccurrence = 0;
static int lowOccurrence = 0;
//static int high; <------
//static int low; <------
static void Main(string[] args) {
int[] scores = { 4, 8, 6, 4, 8, 5 };
findScore(scores);
ExitProgram();
}
static int findOccurrence(int[] scores, int low, int high) { //find the number of times a high/low occurs
for (int i = 0; i < scores.Length; i++) {
if (low == scores[i]) {
lowOccurrence++;
//record number of time slow occurs
}
if (high == scores[i]) {
highOccurrence++;
//record number of times high occurs }
}
return highOccurrence;
}
static int findScore(int[] scores) { //calculates score, needs to be restructured
int[] arrofNormal = new int[scores.Length];
//int low = scores[0]; <----This is where the issue is
//int high = scores[0]; <----- ^^^^^
int total = 0;
for (int i = 0; i < scores.Length; i++) {
if (low > scores[i]) {
low = scores[i];
} //record lowest value
if (high < scores[i]) {
high = scores[i];
//record highest value
}
}
for (int x = 0; x < scores.Length; x++) {
if (scores[x] != low && scores[x] != high) {
arrofNormal[x] = scores[x];
//provides the total of the scores (not including the high and the low)
}
total += arrofNormal[x];
}
findOccurrence(scores, low, high);
if (highOccurrence > 1) { //if there is more than 1 high (or 1 low) it is added once into the total
total += high;
if (lowOccurrence > 1) {
total += low;
}
}
Console.WriteLine("Sum = " + total);
return total; //remove not all code paths return.. error
}
static void ExitProgram() {
Console.Write("\n\nPress any key to exit program: ");
Console.ReadKey();
}//end ExitProgram
}
}
I have placed arrows in the code above to show where my issue is. If I try to declare "high" and "low" as global variables, my final answer is always a few numbers off, buy if I leave the variables declared as "high = scores[0]" etc, I will get the right answer.
What I want ideally is to have separate methods for each step of the calculation, so right now I have method for finding the number of times a specific value shows up in the array. The next I would like to do is finding the highest/lowest value in the array, one method would do the final calculation, and the final one would write the results into the console window. The last two parts (finding the high/low and final calculation) are currently in the find score method.
Any help would be greatly appreciated. Thanks.
How can I implement this so it is always ten numbers in length and how would I store n and r, loop 10 times, and store each loop aswell?
loop the random generator 10x to create 2x10 multiple 10 digit numbers.
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
F();
F();
}
static Random _r = new Random();
static void F()
{
int n = _r.Next();
int r = _r.Next();
Console.WriteLine(n);
Console.WriteLine(r);
Console.ReadLine();
}
}
Something like this may be what you're looking for?
Though I'm not keen on the naming conventions, I'm not sure what these apply to, so can't exactly name them relevantly myself...
static int[] randomNumberArray0 = new int[10];
static int[] randomNumberArray1 = new int[10];
static Random random = new Random();
static void PopulateRandomNumberArrays()
{
for (int i = 0; i < 10; i++)
{
randomNumberArray0[i] = random.Next();
randomNumberArray1[i] = random.Next();
}
}
Update:
To execute this method then further output the values at a later time, try this:
static void PrintRandomNumberArrayValues(int[] array)
{
for (int i = 0; i < array.Length; i++)
{
Console.WriteLine("{0}", array[i]);
}
Console.WriteLine();
}
static void Main()
{
PopulateRandomNumberArrays();
PrintRandomNumberArrayValues(randomNumberArray0);
PrintRandomNumberArrayValues(randomNumberArray1);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
Output would look something like this:
2044334973
153458690
1271210885
734397658
746062572
162210281
1091625245
123317926
410432738
989880682
866647035
481104609
834599031
1153970253
94252627
1041485031
1934449666
414036889
1886559958
2083967380
Further update:
For the generated values to be constrained to 10 digits in length, it means the minimum generated value must be larger than 999999999 and, since an int has a max value of 2,147,483,647, smaller or equal to that, so:
for (int i = 0; i < 10; i++)
{
randomNumberArray0[i] = random.Next(1000000000, int.MaxValue);
randomNumberArray1[i] = random.Next(1000000000, int.MaxValue);
}
I have a feeling this still may not satisfy your needs though, as what I see coming next is that the numbers should be able to be represented as 0000000001, for instance - let's see.
Yet another update:
As I thought, the value of numbers should not be constrained to our specified range, but rather only the output formatted appropriately; thus generation reverts to my original suggestion and printing is altered as so:
Console.WriteLine("{0:D10}", array[i]);
I guess you could use a list of tuples to store and return your results:
static List<Tuple<int,int>> F()
{
var results = new List<Tuple<int,int>> ();
for (int i = 0; i < 10; i++)
{
results.Add(new Tuple<int, int>(_r.Next(), _r.Next()));
}
return results;
}