i'm quite a beginner in C# , i tried to write a program that extract words from an entered string, the user has to enter a minimum length for the word to filter the words output ... my code doesn't look good or intuitive, i used two arrays countStr to store words , countArr to store word length corresponding to each word .. but the problem is i need to use hashtables instead of those two arrays , because both of their sizes are depending on the string length that the user enter , i think that's not too safe for the memory or something ?
here's my humble code , again i'm trying to replace those two arrays with one hashtable , how can this be done ?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
int i = 0 ;
int j = 0;
string myString = "";
int counter = 0;
int detCounter = 0;
myString = Console.ReadLine();
string[] countStr = new string[myString.Length];
int[] countArr = new int[myString.Length];
Console.Write("Enter minimum word length:");
detCounter = int.Parse(Console.ReadLine());
for (i = 0; i < myString.Length; i++)
{
if (myString[i] != ' ')
{
counter++;
countStr[j] += myString[i];
}
else
{
countArr[j] = counter;
counter = 0;
j++;
}
}
if (i == myString.Length)
{
countArr[j] = counter;
}
for (i = 0; i < myString.Length ; i++)
{
if (detCounter <= countArr[i])
{
Console.WriteLine(countStr[i]);
}
}
Console.ReadLine();
}
}
}
You're not doing too badly for a first attempt but this could be a lot better.
First thing: use TryParse rather than Parse when parsing an integer input by a human. If the human types in "HELLO" instead of an integer, your program will crash if you use Parse; only use Parse when you know that it is an integer.
Next thing: consider using String.Split to split the string into an array of words, and then process the array of words.
Next thing: code like yours that has a whole lot of array mutations is hard to read and understand. Consider characterizing your problem as a query. What are you trying to ask? I'm not sure I completely understand your code but it sounds to me like you are trying to say "take this string of words separated by spaces. Take a minimum length. Give me all the words in that string which are more than the minimum length." Yes?
In that case, write the code that looks like that:
string sentence = whatever;
int minimum = whatever;
var words = sentence.Split(' ');
var longWords = from word in words
where word.Length >= minimum
select word;
foreach(var longWord in longWords)
Console.WriteLine(longWord);
And there you go. Notice how the code reads like what it is doing. Try to write code so that the code conveys the meaning of the code, not the mechanism of the code.
One word. Dictioary (or HashTable). Both are standard datatypes you can use
Use a Dictionary for this (in your case, you are looking for a Dictionary).
Your extracted string will be the key, the length of it the Value.
Dictionary<string, int> words = new Dictionary<string,int>();
//algorithm
words.Add(word, length);
Related
I'm using c#, I have a string of cash entries I need to add together and get the total
arrTotalSplitCosts.Text = "24.90,10.60,1.90,20";
While the below works, as soon as I add a decimal point or a string value to replace the numbers in the array with my generated numbers, the below crashes
int[] arr = new int[] { 1, 2, 3 };
int sum = 0;
for (int i = 0; i < arr.Length; i++)
{
sum += arr[i];
}
I want to take these values from a form post:
arrTotalSplitCosts.Text = "24.90,10.60,1.90,20";
And total them e.g. Total = 57.40
Anyone got any ideas, I'm struggling, thanks in advance.
The input is a string (not an array of string, but a single string).
You then have to take that string and split it into a list or array.
The values have decimals, so they cannot be dealt with as int. int is an integer; a whole number. You should deal with your data as a list of doubles.
When you convert from string to double, you should use tryparse, as you can more stringently enforce the conversion and check for exceptions as you go.
I've put a sample below, but note that I made it much more verbose than I normally would, just to (hopefully) more clearly show each of the steps.
If I was going to actually do this, I would use Linq more and combine multiple steps into single lines.
So something like this:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
Console.WriteLine("Hello World");
var inString = "24.90,10.60,1.90,20";
var stringValues = inString.Split(',');
List<double> doubleValues = new List<double>();
foreach(string v in stringValues){
double outNum;
double num = double.TryParse(v, out outNum)? outNum : 0;
doubleValues.Add(num);
}
Console.WriteLine(doubleValues.Sum(i => i)); // output = 57.4
}
}
Don't use , as a seperator. You can prefer ;.
For 10.000,00 formatting style
var sum = arrTotalSplitCosts.Text.Split(';').Select(decimal.Parse).Sum()
For 10,000.00 formatting style
var sum = arrTotalSplitCosts.Split(';').Select(a => decimal.Parse(a, CultureInfo.InvariantCulture)).Sum()
using System;
namespace reverse
{
class Program
{
static void Main(string[] args)
{
int[] a = new int [10];
for (int i= 0; i<a.Length; i++)
{
a[i] = int.Parse(Console.ReadLine());
}
}
}
}
here I can get values from a user by pressing enter key after each time i give the value but I want to give value as a whole with comma. Thanks!
I would suggest to gradually step towards functional programming.
Why?
Weel, with words from Eric Lippert from "Functional programming for beginners"
I will talk about the “why” a little bit, but basically it boils down to
a great many bugs are caused by bad mutations.
By taking a page
from functional style and designing programs so that variables and
data structures change as little as possible, we can eliminate a
large source of bugs.
Structuring programs into small functions
whose outputs each depend solely on inputs
makes for programs that
are easy to unit test.
the ability to pass functions as data
allows us to create new and interesting control flows and patterns,
like LINQ.
Rewriting your code
Use Linq in a single and simple line:
int [] res =
Console.ReadLine () // read the input
.Split (',') // transform it into an array
.Take (10) // consider only the first 10 strings
.Select (int.Parse) // transform them into int
.ToArray (); // and finally get an array
You can add a check after the Split and before Take:
.Where (d => {int t; return int.TryParse (d, out t);}).Take
Try this one and read comments to get more info :
static void Main()
{
string input = Console.ReadLine(); // grab user input in one whole line
string[] splitted = input.Split(','); // split user input by comma sign ( , )
int[] a = new int[splitted.Length]; // create a new array that matches user input values length
for(int i = 0; i < splitted.Length; i++) // iterate through all user input values
{
int temp = -1; // create temporary field to hold result
int.TryParse(splitted[i], out temp); // check if user inpu value can be parsed into int
a[i] = temp; // assign parsed int value
}
}
This method will ensure that program will execute even if user wont input numerics. For example if user input will be :
1 , 2,3,45,8,9898
The output will be :
{ 1, 2, 3, 45, 8, 9898 }
But if the input will be :
1,adsadsa,13,4,6,dsd
The output will be :
{ 1, 0, 13, 4, 6, 0 }
While working on a basic coding challenge I have come across a confusing situation that i am unable to fathom the cause of (I am new to programming)
whilst attempting to split a number into its individual digits, my int array contains the value 13 but returns the value 49??
there is probably an obvious reason for this and if so i apologize.
I have found an alternate way to split my numerical string into individual digits but would still like to know what i was doing wrong
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AddTheDigits
{
class Program
{
static void Main(string[] args)
{
using (StreamReader reader = new StreamReader("TextFile1.txt"))
{
//int total = 0;
string line = reader.ReadLine();
//Console.WriteLine(line); //testing
char[] charArray = line.ToCharArray(0,1);
int[] intArray = new int[charArray.Length];
for (int i = 0; i < intArray.Length; i++)
{
intArray[i] = Convert.ToInt32(charArray[i]);
Console.Write(intArray[i]);
}
}
Console.ReadLine();
}
}
}
You are probably mixing up the ASCII code for the digits with the digits themselves. Try replacing
intArray[i] = Convert.ToInt32(charArray[i]);
with
intArray[i] = charArray[i] - '0';
and see if that helps.
you're taking you line (Which probably contains '13'), and grabbing the first char in it (line.ToCharArray(0,1);). You then convert this char (which has the numerical value 49, equal to '1' in UTF-16) to an int (still equals 49) and you print it. That's it. the '3' is left out due to the ToCharArray only grabbing the first character.
What you are doing is essentially:
"13".ToCharArray(0,1);
which will give you the same value as :
char c = '1';
which is 49, the ASCII code for '1'
49 is ASCII code for 1.
Instead of using Int32.Convert, you should use Int32.Parse.
So this time, I've got numbers entered in as a list, with a space delimiting each number. The code I've written now places the number in a row as it should, but fails out when I try and convert the string to Int32, killing the program and not giving me the sum. I don't understand errors well enough yet to be able to decipher exactly what the error is. How does a guy convert split string arrays into numbers to produce a sum?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Dynamic_Entry
{
class Program
{
static void Main()
{
Console.Write("Please provide a list of numbers, separated by spaces: ");
string list = Console.ReadLine();
string[] parts = list.Split(' ');
int sum = 0;
for (int i = 0; i < parts.Length ; i++)
{
Console.WriteLine("{0, 5}", parts[i]);
}
sum = Convert.ToInt32(list);
Console.WriteLine("-----");
Console.Write("{0, 5}", sum);
Console.ReadLine();
}
}
}
for (int i = 0; i < parts.Length; i++)
{
Console.WriteLine("{0, 5}", parts[i]);
sum += Convert.ToInt32(parts[i]);
}
Fixed.
You were trying to convert "1 2 3 4 5 55" to an int. You must convert "1", "2, "3"... to an int and add them to sum.
I'll add that if you want to Split the string, it would be better to do something like
string[] parts = list.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
In this way multiple spaces between numbers are removed (1 2 3 for example)
Andrei had posted a very simple example of use of LINQ...
int sum = parts.Sum(p => Convert.ToInt32(p));
This you would put OUTSIDE the for cycle. It converts to int and adds all the "parts". It means "for each part convert it to int and add it. Return the sum".
You can convert each string to an int and add them in a loop as #xanatos proposes, or you can use LINQ and Enumerable.Sum(), eg:
var sum=parts.Sum(part=>Convert.ToInt32(part));
or
var sum=parts.Select(part=>Convert.ToInt32(part))
.Sum();
The real benefit comes when you have more complex expressions, eg. when you need to filter values, extract properties etc.
For example, you could filter values greater than 3 like this:
var sum=parts.Select(part=>Convert.ToInt32(part))
.Where(num=>num>3)
.Sum();
I am looking for a c# function or routine that will center justify text.
For example, if I have a sentence, I have noticed that when the sentence is justified to the edges of the screen, that spaces are placed in the line. The inserted spaces start in the center and move out from there on both sides as needed as needed.
Is there a C# function that I can pass my string, say 50 chars, and get back a pretty 56 char string?
Thanks in advance,
Rob
Nice task. Here's a solution based on Linq extension methods. If you do not wish to use them, see history for previous version of code. In this example spaces on the left and right sides from center are 'equal' with respect to order of inserting.
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
public static String Justify(String s, Int32 count)
{
if (count <= 0)
return s;
Int32 middle = s.Length / 2;
IDictionary<Int32, Int32> spaceOffsetsToParts = new Dictionary<Int32, Int32>();
String[] parts = s.Split(' ');
for (Int32 partIndex = 0, offset = 0; partIndex < parts.Length; partIndex++)
{
spaceOffsetsToParts.Add(offset, partIndex);
offset += parts[partIndex].Length + 1; // +1 to count space that was removed by Split
}
foreach (var pair in spaceOffsetsToParts.OrderBy(entry => Math.Abs(middle - entry.Key)))
{
count--;
if (count < 0)
break;
parts[pair.Value] += ' ';
}
return String.Join(" ", parts);
}
static void Main(String[] args) {
String s = "skvb sdkvkd s kc wdkck sdkd sdkje sksdjs skd";
String j = Justify(s, 5);
Console.WriteLine("Initial: " + s);
Console.WriteLine("Result: " + j);
Console.ReadKey();
}
}
As far as I know, there is no "built-in" C# or .net library function for this, so you'd have to implement something on your own (or find some code online whose license suits your needs).
A simple greedy algorithm shouldn't be too difficult to implement, however:
Until the required number of characters is reached:
Extend the shortest sequence of spaces by one
(choose one randomly if there is more than one such sequence).
I'd distribute the spaces randomly rather than starting at the center, to make sure the spaces are evenly distributed among your text (rather than concentrated at one position). Oh, and keep in mind that some people consider fully-justified fixed-font text harder to read than left-justified fixed-font text.