Splitting Multiple Numbers - c#

I'm just getting into learning c#, and I'm a little bit over my head. I'm trying to let a user input a list of 5 grades, and then split them to calculate the highest, lowest, and average.
I can't use int and split together, but I'm not sure how to get this to work.
Thanks!
Console.WriteLine("Enter 5 Grades; Whole Integers Only, 0-100; One Space Between Grades");
int allgrades = int.Parse(Console.ReadLine());
string[] splitgrades = allgrades.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
g1.Name = name + "'s GradeBook";
Console.WriteLine(g1.Name);
Console.WriteLine("Press Any Key to Calculate Gradebook Statistics");
Console.ReadKey();
GradeBook book = new GradeBook();
book.AddGrade(splitgrades[0]);
book.AddGrade(splitgrades[1]);
book.AddGrade(splitgrades[2]);
book.AddGrade(splitgrades[3]);
book.AddGrade(splitgrades[4]);
Thank you all for your help; I changed it around to
Console.WriteLine("Enter 5 Grades; Whole Integers Only, 0-100; One Space Between Grades");
string[] splitgrades = Console.ReadLine().Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
int grade = int.Parse(splitgrades[0]);
int grade1 = int.Parse(splitgrades[1]);
int grade2 = int.Parse(splitgrades[2]);
int grade3 = int.Parse(splitgrades[3]);
int grade4 = int.Parse(splitgrades[4]);

In the second line, you're trying to parse the entire input into a single int. You want to first split the string into different ints, then parse each separately.

You're asking the user for a space-delimited list of integers, then trying to parse that string into a single integer. That will cause much sadness during runtime. Instead, you want something like this:
string allGrades = Console.ReadLine();
string[] splitGrades = allGrades.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
This will leave you with an array of (hopefully) 5 integer grades you can add to your GradeBook. When doing so would be the proper time to parse integers from the individual strings in the array.
// Use a foreach instead to allow the user to enter as many grades as they want.
for (int i = 0; i < 5; ++i)
book.AddGrade(int.Parse(splitGrades[i]);

Related

Is there such a thing as an array without size?

I am playing with C#. I try to write program that frames the quote entered by a user in a square of chars. So, the problem is... a user needs to indicate the number of lines before entering a quote. I want to remove this moment, so the user just enters lines of their phrase (each line is a new element in the string array, so I guess a program should kinda declare it by itself?..). I hope I explained clear what I meant x).
I've attached the program code below. I know that it is not perfect (for example, when entering the number of lines, I use the conversion to an integer, and if a user enters a letter, then this may confuse my electronic friend, this is a temporary solution, since I do not want to ask this x) The program itself must count these lines! x)) Though, I don't understand why the symbols on the left side are displayed incorrectly when the program displays output, but I think this also does not matter yet).
//Greet a user, asking for the number of lines.
Console.WriteLine("Greetings! I can put any phrase into beautiful #-square."
+ "\n" + "Wanna try? How many lines in the quote: ");
int numberOfLines = Convert.ToInt32(Console.ReadLine());
//Asking for each line.
string[] lines = new string[numberOfLines];
for (int i = 0; i < numberOfLines; i++)
{
Console.WriteLine("Enter the line: ");
lines[i] = Console.ReadLine();
}
//Looking for the biggest line
int length = 0;
for (int i = 0; i < numberOfLines; i++)
{
if (length < lines[i].Length) length = lines[i].Length;
}
//Starting framing
char doggy = '#';
char space = ' ';
length += 4;
string frame = new String(doggy, length);
Console.WriteLine(frame);
for (int i = 0; i < numberOfLines; i++)
{
string result = new string(space, length - 3 - lines[i].Length);
Console.WriteLine(doggy + space + lines[i] + result + doggy);
}
Console.WriteLine(frame);
Console.ReadLine();
}
}
}
There is performance gap and functionality between "Generic Lists" and arrays, you can read more about cons and pros of this two objects in the internet,
for example you can use list as Dai mentioned in comment like this
List<string> list = new List<string>();
list.Add("one");
list.Add("two");
list.Add("three");
or you can use arraylist
ArrayList arraylist = new ArrayList();
arraylist.Add();
or even you can change the size of array any times but it erase data in it
int[] arr = new int[100];
there is a function called ToArray() you can use it to change generic list to array
Your problem of the left side output is, that you add two values of char. This is not what you expect to be. You must convert the char to a string to append it to other strings:
Console.WriteLine(doggy.ToString() + space.ToString() + lines[i] + result + doggy.ToString());

How to take digits from two different numbers and form a new one

I have the following problem here:My input is several lines of 2 digit numbers and I need to make a new number using the second digit of the first number and the first of the next one.
Example:
int linesOfNumbers = Convert.ToInt32(Console.ReadLine());
for(int i = 0,i<linesOfNumbers,i++)
{
int numbers = Conver.ToInt32(Console.ReadLine());
//that's for reading the input
}
I know how to separate the numbers into digits.My question is how to merge them.
For example if your input is 12 and 21 the output should be 22.
I like oRole's answer, but I think they're missing a couple things with the example input that you provided in your comment. I'll also point out some of the errors in the code that you have.
First off, if you're only given the input 12,23,34,45, then you don't need to call Console.ReadLine within your for loop. You've already gotten the input, you don't need to get any more (from what you've described).
Secondly, unless you're doing mathematical operations, there is no need to store numerical data as ints, keep it as a string, especially in this case. (What I mean is that you don't store Zip Codes in a database as a number, you store it as a string.)
Now, onto the code. You had the right way to get your data:
var listOfNumbers = Console.ReadLine();
At that point, listOfNumbers is equal to "12,23,34,45". If you iterate on that variable as a string, you'll be taking each individual character, including the commas. To get each of the numbers to operate on, you'll need to use string.Split.
var numbers = listOfNumbers.Split(',');
This turns that list into four different two character numbers (in string form). Now, you can iterate over them, but you don't need to worry about converting them to numbers as you're operating on the characters in each string. Also, you'll need a results collection to put everything into.
var results = new List<string>();
// Instead of the regular "i < numbers.Length", we want to skip the last.
for (var i = 0; i < numbers.Length - 1; i++)
{
var first = numbers[i];
var second = numbers[i + 1]; // This is why we skip the last.
results.Add(first[1] + second[0]);
}
Now your results is a collection of the numbers "22", "33", and "44". To get those back into a single string, you can use the helper method string.Join.
Console.WriteLine(string.Join(",", results));
You could use the string-method .Substring(..) to achieve what you want.
If you want to keep int-conversion in combination with user input, you could do:
int numA = 23;
int numB = 34;
int resultAB = Convert.ToInt16(numA.ToString().Substring(1, 1) + numB.ToString().Substring(0, 1));
Another option would be to take the users input as string values and to convert them afterwards like that:
string numC = "12";
string numD = "21";
int resultCD = Convert.ToInt16(numC.Substring(1, 1) + numD.Substring(0, 1));
I hope this code snippet will help you combining your numbers. The modulo operator (%) means: 53 / 10 = 5 Rest 3
This example shows the computation of the numbers 34 and 12
int firstNumber = 34 - (34 % 10) // firstNumber = 30
int secondNumber = 12 % 10; // secondNumber = 2
int combined = firstNumber + secondNumber; // combined = 32
EDIT (added reading and ouput code):
boolean reading = true;
List<int> numbers = new ArrayList();
while(reading)
{
try
{
int number = Convert.ToInt32(Console.ReadLine());
if (number > 9 && number < 100) numbers.Add(number);
else reading = false; // leave reading process if no 2-digit-number
}
catch (Exception ex)
{
// leave reading process by typing a character instead of a number;
reading = false;
}
}
if (numbers.Count() > 1)
{
List<int> combined = new ArrayList();
for (int i = 1; i <= numbers.Count(); i++)
{
combined.Add((numbers[i-1] % 10) + (numbers[i] - (numbers[i] % 10)));
}
//Logging output:
foreach (int combination in combined) Console.WriteLine(combination);
}
As you mention, if you already have both numbers, and they are always valid two digit integers, following code should work for you.
var num1 = 12;
var num2 = 22;
var result = (num2 / 10)*10 + (num1 % 10);
num2/10 returns the first digit of second number, and num1 % 10 returns the second digit of the first number.
The % and / signs are your savior.
If you want the 'ones' digit of a number (lets call it X), simply do X%10 - the remainder will be whatever number is in the 'ones' digit. (23%10=3)
If, instead, the number is two digits and you want the 'tens' digit, divide it by ten. (19/10=1).
To merge them, multiply the number you want to be in the 'tens' digit by ten, and add the other number to it (2*10+2=22)
There are other solutions like substring, etc and many one have already given it above. I am giving the solution VIA LINQ, note that this isn't efficient and it's recommended only for learning purpose here
int numA = 12;
int numB = 21 ;
string secondPartofNumA = numA.ToString().Select(q => new string(q,1)).ToArray()[1]; // first digit
string firstPartofNumB = numB.ToString().Select(q => new string(q,1)).ToArray()[0]; // second digit
string resultAsString = secondPartofNumA + firstPartofNumB;
int resultAsInt = Convert.ToInt32(resultAsString);
Console.WriteLine(resultAsString);
Console.WriteLine(resultAsInt);

C#: String divided into substrings, excluding tabs

I have a file that looks something like this:
0 4 5
6 9 9
etc, with three numbers in each row, separated by tabs. I have an array of the lines from the file:
string[] lines = File.ReadAllLines(theFile);
For each line, I am calling a function whose intended result is to return an array of integers. Here's what my code looks like as of now:
public int[] getPoint(string line)
{
int xlength= line.IndexOf(" "); //find location of first white space
int x= Int32.Parse(line.Substring(0, xlength)); //find x-coordinate and turn it from a string to an int
int ylength = line.IndexOf(" ", xlength); //find next white space
int y = Int32.Parse(line.Substring(xlength + 1, ylength)); //y-coordinate starts after first white space and ends before next
int z = Int32.Parse(line.Substring(ylength + 1, line.Length)); //z starts after 2nd white space and goes through end of line
return new int[] { x, y, z }; //return a new point!
}
My problem is with the IndexOf(string) function. It does not recognize tabs. How could I write this so that each my getPoint function achieves its purpose? Thank you.
Try to use IndexOf() with tabs, not with spaces:
int xlength= line.IndexOf("\t"); //"\t" - to find tabs
Also, use "\t" in every IndexOf() call.
How about this using Split and Linq and LinqPad
void Main()
{
var lines = new List<string> { "0\t4 5", "6\t9\t9" };
lines.Select(l => GetPoint(l)).Dump();
}
static int[] GetPoint(string s)
{
var values = s.Split(new[] {' ', '\t'}, StringSplitOptions.RemoveEmptyEntries);
return values.Select(v => int.Parse(v)).ToArray();
}
Of course you would use
File.ReadLines("path").Select(l => GetPoint(l)).Dump();
Try using the ReadLines method instead. RealLines will read the file line by line into memory as requested. Also, try using the Split method. I would also add error handling in case the found string is not parseable to an int. Here is some code to guide you but you may need to adjust it to fit your needs:
foreach (var thisLine in File.ReadLines(theFile))
{
int[] point = getPoint(thisLine);
}
public int[] getPoint(string line)
{
// Split by tab or space
string[] portions = line.Split(new char[] { ' ', '\t' });
int x = Int32.Parse(portions[0]); //find x-coordinate and turn it from a string to an int
int y = Int32.Parse(portions[1]); //y-coordinate starts after first white space and ends before next
int z = Int32.Parse(portions[2]); //z starts after 2nd white space and goes through end of line
return new int[] { x, y, z }; //return a new point!
}
To add a bit of additional capacity to the suggestions above, you could use Regex.Matches() as follows:
string line = "1\t-25\t5";
var numbers = Regex.Matches(line, #"-?\d+");
foreach (var number in numbers)
Console.WriteLine(number);
And then parse those numbers as integers.
This has two benefits.
It can handle negative numbers, and
It will pull out the numbers successfully, even if tabs weren't used or are not reliable.

Rearranging a string of numbers from highest to lowest C#

What I'm trying to do is to create a function that will rearrange a string of numbers like "1234" to "4321". I'm certain that there are many much more efficient ways to do this than my method but I just want to see what went wrong with what I did because I'm a beginner at programming and can use the knowledge to get better.
My thought process for the code was to:
find the largest number in the inputted string
add the largest number into a list
remove the largest number from the inputted string
find the largest number again from the (now shorter) string
So I made a function that found the largest number in a string and it worked fine:
static int LargestNumber(string num)
{
int largestnumber = 0;
char[] numbers = num.ToCharArray();
foreach (var number in numbers)
{
int prevNumber = (int) char.GetNumericValue(number);
if (prevNumber >= largestnumber)
{
largestnumber = prevNumber;
}
}
return largestnumber;
}
Now the rearranging function is what I am having problems with:
static List<int> Rearrange(string num)
{
List<int> rearranged = new List<int>(); // to store rearranged numbers
foreach (var number in num) //for every number in the number string
{
string prevnumber = number.ToString(); // the previous number in the loop
if (prevnumber == LargestNumber(num).ToString()) // if the previous number is the larges number in the inputted string (num)
{
rearranged.Add(Convert.ToInt32(prevnumber)); // put the previous number into the list
// removing the previous number (largest) from the inputted string and update the inputted string (which should be now smaller)
StringBuilder sb = new StringBuilder(num);
sb.Remove(num.IndexOf(number), 1);
num = sb.ToString();
}
}
return rearranged; // return the final rearranged list of numbers
}
When I run this code (fixed for concatenation):
var rearranged = Rearrange("3250");
string concat = String.Join(" ", rearranged.ToArray());
Console.WriteLine(concat);
All I get is:
5
I'm not sure what I'm missing or what I'm doing wrong - the code doesn't seem to be going back after removing '5' which i s the highest number then removing the next highest number/
Your issue is your if statement within your loop.
if (prevnumber == LargestNumber(num).ToString()
{
rearranged.Add(Convert.ToInt32(prevnumber));
//...
}
You only ever add to your List rearranged if the value of prevnumber is the largest value, which is false for every number but 5, so the only value that ever gets added to the list is 5.
That's the answer to why it's only returning 5, but I don't think that will make your method work properly necessarily. You're doing a very dangerous thing by changing the value of the collection you are iterating over (the characters in num) from within the loop itself. Other answers have been written for you containing a method that rearranges the numbers as you've described.
Your Rearrange method is returning List<int> when you try to write that to the console, the best it can do is write System.Collections.Generic.List1[System.Int32] (its type)
Instead of trying to write the list, convert it first into a data type that can be written (string for example)
eg:
var myList = Rearrange("3250");
string concat = String.Join(" ", myList.ToArray());
Console.WriteLine(concat);
Building on pats comment you could iterate through your list and write them to the console.
e.g.
foreach(var i in Rearrange(3250))
{
console.writeline(i.ToString());
}
or if you want to see the linq example.
using system.linq;
Rearrange(3250).foreach(i => console.writeline(i.ToString()));
--edit after seeing you're only getting '5' output
This is because your function only adds number to the list if they are the largest number in your list, which is why 5 is only being added and returned.
Your Rearrange method can be written easily using Array.Sort (or similar with (List<T>) :
int[] Rearrange(int num)
{
var arr = num.ToString ().ToCharArray ();
Array.Sort (arr, (d1, d2) => d2 - d1);
return Array.ConvertAll (arr, ch => ch - '0');
}
Just reading your first sentence
Does not test for integers
static int ReversedNumber(string num)
{
char[] numbers = num.ToCharArray();
Array.Sort(numbers);
Array.Reverse(numbers);
Debug.WriteLine(String.Concat(numbers));
return (int.Parse(String.Concat(numbers)));
}
Because your foreach loop within Rearrange method only loop through the original num. The algorithm doesn't continue to go through the new num string after you have removed the largest number.
You can find the problem by debugging, this foreach loop in Rearrange goes only 4 times if your input string is "3250".

How to Display the Largest and Smallest Values of an Array

To start this is a homework assignment and I'm having a bit of trouble and would like some suggestions. So far I've created this application to take 10 inputted values from a user and store them into an array. I pass the array to the SmallAndLarge method where it displays derermines the smallest and largest of the 10 values using Sort() but now i have to display the smallest and largest of the 10 values the user entered and am having a trouble. Any help at all would be great!!
Also one other problem ive noticed that if the values 1 through 10 are entered 10 will be before 2 and after one when the array is sorted and displayed. Why is this?
namespace SmallAndLarge
{
class Program
{
static void Main()
{
int found = 0;
string[] numbers = new string[10];
for (int i = 0; i < numbers.Length; i++)
{
Console.Write("Enter ten numbers --> ");
numbers[i] = Console.ReadLine();
}
SmallestAndLargest(numbers);
}
public static int SmallestAndLargest(string[] numbers1)
{
int x;
Array.Sort(numbers1);
for (x = 0; x < numbers1.Length; ++x)
Console.Write("{0} ", numbers1[x]);
return x;
}
}
}
You can use Linq to cast and return the Largest/Smallest using Min/Max
string[] numbers = new string[] {"1","2","3","15","30","7" };
var converted = numbers.Select(int.Parse);
int largest = converted.Max();
int smallest = converted.Min();
You have the numbers as strings. That explains why "10" comes before "2", it's for the same reason that "am" comes before "i" in an alphabetic sort. The first character of "10" is '1' which comes before '2'.
So before you sort the array, or search for the max og min value, you need to convert the strings into some numeric type. It could be the int type, for example. You would hold them in an array of type int[], not string[].
To convert from the string given by Console.ReadLine into int, use an overload of int.Parse or int.TryParse methods, for example.
If the user should be allowed to type non-integral numbers like 3.14, you could use decimal instead of int.
It looks like you are iterating over the array. I would do the following:
Create two int variables (small and large, respectively)
Set them both equal to the first element of the array
Loop through the elements;
For each element[i], (convert the element to int using int.Parse() or equivalent).
if element[i] > large, large = element[i]; if element[i] < small, small = element[i]
There is no need for sort if you only need min and max. And I would store the ints into and int array rather than string array, make the conversion when the user inputs the value. That way, when an invalid value is input, your program fails right then.
Here's a very simple, though long winded answer. Add the values to a List and use Min/Max returns. Your already using a for loop to iterate through the list, no reason to do it twice.
static void Main(string[] args)
{
string[] StringValues = new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10","Not Number" };
List<int> ConvertedStrings = new List<int>();
foreach (string S in StringValues)
{
ConvertedStrings = ParseStringToInt(S, ConvertedStrings);
}
Console.WriteLine();
Console.WriteLine("Max Value: " + ConvertedStrings.Max().ToString());
Console.WriteLine("Min Value: " + ConvertedStrings.Min().ToString());
Console.ReadLine();
}
static private List<int> ParseStringToInt(string Input, List<int> ConvertedStrings)
{
int ConvertedValue = 0;
if (int.TryParse(Input, out ConvertedValue))
{
Console.WriteLine(Input + " sucessfully parsed and added...");
ConvertedStrings.Add(ConvertedValue);
return ConvertedStrings;
}
else
{
Console.WriteLine(Input + " failed to parse...");
}
return ConvertedStrings;
}
sa_ddam213 has got the killer answer though :P

Categories