user input:
"I have 3 apples"
output:
"I"
"have"
"6"
"apples"
My C#:
static void Main(string[] args)
{
Console.WriteLine("Enter a string...");
string delimeter = " ";
string input = Console.ReadLine();
string[] output = input.Split(Convert.ToChar(delimeter));
foreach (var substring in output)
{
Console.WriteLine(substring);
}
Console.Read();
}
I need help getting on the right track. My code only breaks the sentence apart using space as a delimiter.
Give it a try
foreach (var substring in output)
{
int value;
if(int.TryParse(substring, out value)){
value = value * 2;
input = input.Replace(substring, value.ToString());
}
}
Console.WriteLine(input);
You first need to check if your spitted string is a number, if it is then multiple by 2 and replace it in your input variable to get the expected output.
Can you try followoing?
static void Main(string[] args)
{
Console.WriteLine("Enter a string...");
string delimeter = " ";
string input = Console.ReadLine();
var result = System.Text.RegularExpression.Regex.Replace(input,"\d+", match=>(int.Parse(match.Value)*2).ToString(CultureInfo.InvariantCulture));
Console.WriteLine(result);
Console.Read();
}
Here is an algorithm for example.
// an extension method to check if a string is all decimal digits
public static class StringHelper {
public static bool IsNumeric(this string str)
{
if (str.IsNullOrWhiteSpace()) return false;
return str.All(char.IsNumber);
}
}
...
static void Main(string[] args)
{
Console.WriteLine("Enter a string...");
string delimeter = " ";
string input = Console.ReadLine();
string[] output = input.Split(Convert.ToChar(delimeter));
foreach (var substring in output)
{
if (substring.IsNumeric())
{
substring = (int.Parse(substring) * 2).ToString();
}
Console.Write(substring);
}
Console.WriteLine();
Console.Read();
}
Please note that the code is only checking if a substring contains only decimal digits. It's not prepared to handle any number with decimal point for example, and it's also not completely safe. The code is not tested, and is ment only for example purposes.
I intentionally showed a code without using Regular Expressions, but if you're interested, check out the other answers for that alternative.
Related
This question already has answers here:
How do I create a terminable while loop in console application?
(7 answers)
Closed 3 years ago.
I started a C# course now and there is an assignment where I have to create a "palindrome detector" program. Point is that user inputs some word or sentence, then I have to remove chars like ,.;:!? and space from it. I have done that with two different methods, because char method can not remove space so I wrote another method for it.
After "cleaning" operation program reversing input what user gave, and comparing original user input and reversed user input to each other. It they are same it prints "It is palindrome", if they are different it prints "It is not palindrome". That is working fine, BUT THE PROBLEM IS I have to put them in for loop. It have to ask input again and again, until user give empty.
This would be very easy, but somehow I can not do it.
Here is my code:
using System;
namespace Palindromi
{
class Program
{
static void Main()
{
Console.WriteLine("Hei! Tervetuloa palindromin tunnistusohjelmaan. Tämä tunnistaa, onko syöttämäsi sana sama toisinpäin!");
Console.Write("Anna teksti (tyhjä lopettaa): ");
string userinput = Console.ReadLine(); //userinput is user's input, this is what you have to modify. remove some chars and reverse it.
if (userinput == "")
{
Console.ReadLine();//when i have loop this have to be "break". This meant to break for loop when i have it.
}
char[] removechars = { '.', ':', ';', ',', '!', '?' };//this is the list of "have to be removed" chars
string userinput_without_chars = userinput.Trim(removechars); //this method remove chars which are listed
string userinput_without_chars_space = userinput_without_chars.Replace( " ", ""); //replace space with empty
string reverse_string, reversed;
reverse_string = userinput_without_chars_space;
reversed = "";
int len;
len = userinput_without_chars_space.Length - 1;
while (len >= 0)
{
reversed = reversed + reverse_string[len];
len--;
}
Console.WriteLine("Sana käännettynä on {0}", reversed); //tells user input reversed
if (userinput_without_chars_space == reversed)//check is the userinput same than reversed user input
{
Console.Write("On palindromi.");//it is palindrome
}
else
{
Console.Write("Ei ole palindromi.");//it is not palindrome
}
}
}
}
You could potentially do something along these lines:
var running = true;
while(running)
{
var input = Console.ReadLine().ToLower();
var phrase = input.Sanitize(new List<string>() {".", ",", "?", "!", "'", "&", "%", "$", " "});
if(phrase.IsPalindrome())
Console.Writeline("Input was palindrome.");
}
public static string Sanitize(this string input, IList<string> punctuation) =>
String.Join(String.Empty, input.Where(character => punctuation.Contains(character) == false));
public static bool IsPalindrome(this string sentence)
{
for (int l = 0, r = sentence.Length - 1; l < r; l++, r--)
if (sentence[l] != sentence[r])
return false;
return true;
}
public static void Close(string input)
{
// Some logic to see if the application should stop.
}
You could create another method that looks for commands, or keystrokes, then sets the boolean to run as false. Which would break the infinite loop. You could also do an abrupt close with Environment.Exit.
The very simplest approach is replace your Console.ReadLine() where you want to break to return.
Alternatively, you could wrap the logic in another while loop.
while (userinput != "")
{
// Remove chars
// rest of your logic
/* IMPORTANT */
userinput = Console.Readline();
}
To remove the symbols from the input, you can use the Regex.Replace method. In this case, you can be sure, that the specified symbols will be correctly removed from the input string. Note, that you can handle the whitespaces along with other characters you mentioned, like in the code snippet below:
var CharactersToRemove { get; set; } = " ,.;:!?";
var processedInput = Regex.Replace(input.ToLower(), $"[{CharactersToRemove}]", string.Empty);
Note, that here I used input.ToLower() to convert the input to a lowercase string. This will make the palindrome tests case-insensitive. Should you need case-sensitive palindrome tests, just remove the .ToLower() part.
There is no need to reverse the input string to check if it is a palindrome. You can check this within one for loop as follows:
bool CheckForBeingaAPalindrome(string input)
{
var frontIndex = 0;
var tailIndex = input.Length - 1;
for (; frontIndex < tailIndex;)
{
if (input[frontIndex] != input[tailIndex])
return false;
++frontIndex;
--tailIndex;
}
return true;
}
Note, that in this case you only iterate over the elements of the input string once. This approach will give you al least 4 times better performance than the one you used.
Below, you can find a complete minimal working solution to your problem.
using System.Text.RegularExpressions;
using static System.Console;
namespace Assignment
{
public static class PalindromeFinder
{
public static string CharactersToRemove { get; set; } = " ,.;:!?";
public static bool IsPalindrome(string input)
{
var processedInput = RemoveUnnecessaryCharacters(input);
return CheckForBeingAPalindrome(processedInput);
}
private static string RemoveUnnecessaryCharacters(string input)
{
return Regex.Replace(input.ToLower(), $"[{CharactersToRemove}]", string.Empty);
}
private static bool CheckForBeingAPalindrome(string input)
{
var frontIndex = 0;
var tailIndex = input.Length - 1;
for (; frontIndex < tailIndex;)
{
if (input[frontIndex] != input[tailIndex])
return false;
++frontIndex;
--tailIndex;
}
return true;
}
}
public class Program
{
private static void Main(string[] args)
{
ContinuouslyCheckUserInputForBeingAPalindrome();
}
private static void ContinuouslyCheckUserInputForBeingAPalindrome()
{
while (FetchUserInputFromConsole() is string input
&& !string.IsNullOrWhiteSpace(input))
{
var isPalindrome = PalindromeFinder.IsPalindrome(input);
var modifier = isPalindrome ? "a" : "not a";
WriteLine($"It is {modifier} palindrome");
}
}
private static string FetchUserInputFromConsole()
{
Write("Enter a string: ");
return ReadLine();
}
}
}
example = "I-000146.22.43.24"
In the example, I need to validate that the last number after the period isnt over 9. Currently is 24 and thats not valid.
01-08 is valid and anything over that isnt.
How can I add logic to check for this?
One solution would be to use Regex. The regex pattern would be something like this:
^.+\.(0?[0-8])$
Regex demo.
C# example:
string pattern = #"^.+\.(0?[0-8])$";
string[] inputs = new [] { "I-000146.22.43.24", "I-000146.22.43.09",
"I-000146.22.43.08", "xxxxxxx.07" };
foreach (string input in inputs)
{
Match match = Regex.Match(input, pattern);
if (match.Success)
Console.WriteLine($"The input is valid. Last number is '{match.Groups[1].Value}'.");
else
Console.WriteLine("The input is not valid.");
}
Output:
The input is not valid.
The input is not valid.
The input is valid. Last number is '08'.
The input is valid. Last number is '07'.
Try it online.
You could use Linq:
using System;
using System.Linq;
class MainClass {
public static void Main (string[] args) {
String[] tests = new string[3] {"I-000146.22.43.24", "I-000146.22.43.9", "I-000146.22.43.a"};
foreach (string test in tests) {
Console.WriteLine ($"{test} is a valid string: {isValidString (test)}");
}
}
private static bool isValidString (string str) {
var lastNumString = str.Split ('.').Last();
return isSingleDigit (lastNumString);
}
private static bool isSingleDigit (string numString) {
int number;
bool success = Int32.TryParse (numString, out number);
if (success) {
return number >= 0 && number <= 9;
}
return success;
}
}
Output:
I-000146.22.43.24 is a valid string: False
I-000146.22.43.9 is a valid string: True
I-000146.22.43.a is a valid string: False
using System;
class Strng {
// Main Method
public static void Main()
{
// define string
String str = "Some_String";
Console.WriteLine("Given String : " + str);
// delete from index 5 to end of string
Console.WriteLine("New String1 : " + str.Remove(5));
// delete character from index 8 to end of string
Console.WriteLine("New String2 : " + str.Remove(8));
}
}
The above works with the given input but I want to give input dynamically and remove a character from given string dynamically
It looks like you're wanting to read dynamically a string and a character to replace.
You can do this with the use of Console.ReadLine() or Console.ReadKey()
Implementing the following into your main method:
Console.WriteLine("Enter a string:");
string s = Console.ReadLine();
Console.WriteLine("Enter a character to remove:");
string rs = Console.ReadLine().ToString();
//Assuming if they enter 'a' you want to remove both 'a' AND 'A':
string rsUpCase = rs.ToUpper();
string rsLoCase = rs.ToLower();
s = s.Replace(rsUpCase,"");
s = s.Replace(rsLoCase,"");
Console.WriteLine(s);
//Input:
//Aardvarks are boring creatures
//Result:
//rdvrks re boring cretures
Will allow a user to enter a string dynamically (not hard-coded) and remove any character taking advantage of the Replace function - also demonstrated is the use of upper/lower case to determine if you want both variants of a character to be removed.
Hope this helps.
I think the correct question is how to read from console.
You can use Console.Read() and Console.ReadLine().
First ask for the string, and then ask for the index to remove, if this is what you mean with dynamically
This is a MSDN Example about Read
using System;
class Sample
{
public static void Main()
{
string m1 = "\nType a string of text then press Enter. " +
"Type '+' anywhere in the text to quit:\n";
string m2 = "Character '{0}' is hexadecimal 0x{1:x4}.";
string m3 = "Character is hexadecimal 0x{0:x4}.";
char ch;
int x;
//
Console.WriteLine(m1);
do
{
x = Console.Read();
try
{
ch = Convert.ToChar(x);
if (Char.IsWhiteSpace(ch))
{
Console.WriteLine(m3, x);
if (ch == 0x0a)
Console.WriteLine(m1);
}
else
Console.WriteLine(m2, ch, x);
}
catch (OverflowException e)
{
Console.WriteLine("{0} Value read = {1}.", e.Message, x);
ch = Char.MinValue;
Console.WriteLine(m1);
}
} while (ch != '+');
}
}
I have a string which comprise lots of letters. I have used the following code to convert it to numbers, but the new string t still gives me imperfect result.
For example:
tung2003 -> -1-1-1-12003
What I expected: 1161171101032003 (116 is the ASCII code of t, 117 is the ASCII code of u
string t=null;
foreach (char c in Properties.Settings.Default.password)
{
int ascii = (int)Char.GetNumericValue(c);
int counter=0;
counter = ascii;
t = t + Convert.ToString(counter);
}
The problem is the - character. I want my new string only comprises numbers.
It looks like you do not want the ASCII values of the numbers based on your expected output. In that case you can just do something like this:
string input = "tung2003";
string output = string.Empty;
foreach(char c in input)
{
if(char.IsNumber(c))
{
output += c;
}
else
{
output += ((byte)c).ToString();
}
}
//output is now: 1161171101032003
Fiddle here
Also added as a Linq expression for a short hand solution.
// Method 1 Linq
string output = string.Concat(("tung2003".ToCharArray()
.Select(s=> char.IsDigit(s) ? s.ToString() : ((int)s).ToString())));
// Method 2
string input = "tung2003";
string output = string.Empty;
foreach (char c in input)
{
if (Char.IsDigit(c)) output += c.ToString();
else output += ((int)c).ToString();
}
Extrapolating your output it looks like you want two different things. You want to tally each ascii character as long as it is a letter and extract the numeric values to append. The following provides three options, the first is to tally the ascii values from letters and the other two are ways to extract only digits. Because your code example uses a Password I am assuming you are trying to do some sort of custom hashing and if that is the case you should use a Hash implementation from the Cryptography namespace or some other package.
using System;
using System.Linq;
using System.Text.RegularExpressions;
namespace ConsoleApp5
{
class Program
{
static void Main(string[] args)
{
var combined = OnlyLettersToAscii("tung2003") + OnlyNumbers("tung2003");
Console.WriteLine($"Input: tung2003 Output: {OnlyNumbers("tung2003")}");
Console.WriteLine($"Input: tung2003 Output Regex: {OnlyNumbersWithRegex("tung2003")}");
Console.ReadKey();
}
private static string OnlyLettersToAscii(string originalString)
{
if (string.IsNullOrWhiteSpace(originalString)) return originalString;
return string.Join(string.Empty, originalString.ToArray()
.Where(w => char.IsLetter(w))
.Select(s => ((int)s).ToString()));
}
private static string OnlyNumbers(string originalString)
{
if (string.IsNullOrWhiteSpace(originalString)) return originalString;
return new string(originalString.Where(w => char.IsDigit(w)).ToArray());
}
public static string OnlyNumbersWithRegex(string originalString)
{
return Regex.Replace(originalString, #"[^\d]", string.Empty);
}
}
}
string t = "";
foreach (char c in Properties.Settings.Default.password)
{
if (IsNumber(x)) t += System.Convert.ToInt32(c).ToString();
else
{
t += c.ToString();
}
}
Moreover, if you just want to get rid off '-' the use this code: t =String.Replace(t, '-');
Is it possible to have the contain function find if the string contains 2 words or more?
This is what I'm trying to do:
string d = "You hit someone for 50 damage";
string a = "damage";
string b = "someone";
string c = "you";
if(d.Contains(b + a))
{
Console.WriteLine(" " + d);
Console.ReadLine();
}
When I run this, the console window just shuts down really fast without showing anything.
And another question: if I for one want to add how much damage is done, what would be the easiest way to get that number and get it into a TryParse?
You would be better off just calling Contains twice or making your own extension method to handle this.
string d = "You hit someone for 50 damage";
string a = "damage";
string b = "someone";
string c = "you";
if(d.Contains(a) && d.Contains(b))
{
Console.WriteLine(" " + d);
Console.ReadLine();
}
As far as your other question, you could build a regular expression to parse the string to find 50 or if the string is always the same, just split it based on a space and get the 5th part.
public static class StringExtensions
{
public static bool Contains(this string s, params string[] predicates)
{
return predicates.All(s.Contains);
}
}
string d = "You hit someone for 50 damage";
string a = "damage";
string b = "someone";
string c = "you";
if (d.Contains(a, b))
{
Console.WriteLine("d contains a and b");
}
That is because the if statements returns false since d doesn't contain b + a i.e "someonedamage"
Are you looking for the string contains a certain number of words or contains specific words? Your example leads towards the latter.
In that case, you may wish to look into parsing strings or at least use regex.
Learn regex - it will be useful 1000x over in programming. I cannot emphasize this too much. Using contains and if statements will turn into a mess very quickly.
If you are just trying to count words, then :
string d = "You hit someone for 50 damage";
string[] words = d.Split(' '); // Break up the string into words
Console.Write(words.Length);
With the code d.Contains(b + a) you check if "You hit someone for 50 damage" contains "someonedamage". And this (i guess) you don't want.
The + concats the two string of b and a.
You have to check it by
if(d.Contains(b) && d.Contains(a))
This is because d does not contain b + a (i.e. "someonedamage"), and therefore the application just terminates (since your Console.ReadLine(); is within the if block).
Your b + a is equal "someonedamage", since your d doesn't contain that string, your if statement returns false and doesn't run following parts.
Console.WriteLine(" " + d);
Console.ReadLine();
You can control this more efficient as;
bool b = d.Contains(a) && d.Contains(b);
Here is a DEMO.
string d = "You hit someone for 50 damage";
string a = "damage";
string b = "someone";
string c = "you";
if(d.Contains(a) && d.Contains(b))
{
Console.WriteLine(" " + d);
}
Console.ReadLine();
If you have a list of words you can do a method like this:
public bool ContainWords(List<string> wordList, string text)
{
foreach(string currentWord in wordList)
if(!text.Contains(currentWord))
return false;
return true;
}
You could write an extension method with linq.
public static bool MyContains(this string str, params string[] p) {
return !p.Cast<string>().Where(s => !str.Contains(s)).Any();
}
EDIT (thx to sirid):
public static bool MyContains(this string str, params string[] p) {
return !p.Any(s => !str.Contains(s));
}
Because b + a ="someonedamage", try this to achieve :
if (d.Contains(b) && d.Contains(a))
{
Console.WriteLine(" " + d);
Console.ReadLine();
}
So you want to know if one string contains two other strings?
You could use this extension which also allows to specify the comparison:
public static bool ContainsAll(this string text, StringComparison comparison = StringComparison.CurrentCulture, params string[]parts)
{
return parts.All(p => text.IndexOf(p, comparison) > -1);
}
Use it in this way (you can also omit the StringComparison):
bool containsAll = d.ContainsAll(StringComparison.OrdinalIgnoreCase, a, b);
I just checked for a space in contains to check if the string has 2 or more words.
string d = "You hit someone for 50 damage";
string a = "damage";
string b = "someone";
string c = "you";
bool a = ?(d.contains(" ")):true:false;
if(a)
{
Console.WriteLine(" " + d);
}
Console.Read();
So what is that you are really after? If you want to make sure that something has hit for damage (in this case), why are you not using string.Format
string a = string.Format("You hit someone for {d} damage", damage);
In this way, you have the ability to have the damage qualifier that you are looking for, and are able to calculate that for other parts.
string d = "You hit ssomeones for 50 damage";
string a = "damage";
string b = "someone";
if (d.Contains(a) && d.Contains(b))
{
Response.Write(" " + d);
}
else
{
Response.Write("The required string not contain in d");
}
public static bool In(this string str, params string[] p)
{
foreach (var s in p)
{
if (str.Contains(s)) return true;
}
return false;
}
class Program {
static void Main(String[] args) {
// By using extension methods
if ( "Hello world".ContainsAll(StringComparison.CurrentCultureIgnoreCase, "Hello", "world") )
Console.WriteLine("Found everything by using an extension method!");
else
Console.WriteLine("I didn't");
// By using a single method
if ( ContainsAll("Hello world", StringComparison.CurrentCultureIgnoreCase, "Hello", "world") )
Console.WriteLine("Found everything by using an ad hoc procedure!");
else
Console.WriteLine("I didn't");
}
private static Boolean ContainsAll(String str, StringComparison comparisonType, params String[] values) {
return values.All(s => s.Equals(s, comparisonType));
}
}
// Extension method for your convenience
internal static class Extensiones {
public static Boolean ContainsAll(this String str, StringComparison comparisonType, params String[] values) {
return values.All(s => s.Equals(s, comparisonType));
}
}