Replacing a char at a given index in string? [duplicate] - c#

This question already has answers here:
how do I set a character at an index in a string in c#?
(7 answers)
Closed 5 years ago.
String does not have ReplaceAt(), and I'm tumbling a bit on how to make a decent function that does what I need. I suppose the CPU cost is high, but the string sizes are small so it's all ok

Use a StringBuilder:
StringBuilder sb = new StringBuilder(theString);
sb[index] = newChar;
theString = sb.ToString();

The simplest approach would be something like:
public static string ReplaceAt(this string input, int index, char newChar)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
char[] chars = input.ToCharArray();
chars[index] = newChar;
return new string(chars);
}
This is now an extension method so you can use:
var foo = "hello".ReplaceAt(2, 'x');
Console.WriteLine(foo); // hexlo
It would be nice to think of some way that only required a single copy of the data to be made rather than the two here, but I'm not sure of any way of doing that. It's possible that this would do it:
public static string ReplaceAt(this string input, int index, char newChar)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
StringBuilder builder = new StringBuilder(input);
builder[index] = newChar;
return builder.ToString();
}
... I suspect it entirely depends on which version of the framework you're using.

string s = "ihj";
char[] array = s.ToCharArray();
array[1] = 'p';
s = new string(array);

Strings are immutable objects, so you can't replace a given character in the string.
What you can do is you can create a new string with the given character replaced.
But if you are to create a new string, why not use a StringBuilder:
string s = "abc";
StringBuilder sb = new StringBuilder(s);
sb[1] = 'x';
string newS = sb.ToString();
//newS = "axc";

I suddenly needed to do this task and found this topic.
So, this is my linq-style variant:
public static class Extensions
{
public static string ReplaceAt(this string value, int index, char newchar)
{
if (value.Length <= index)
return value;
else
return string.Concat(value.Select((c, i) => i == index ? newchar : c));
}
}
and then, for example:
string instr = "Replace$dollar";
string outstr = instr.ReplaceAt(7, ' ');
In the end I needed to utilize .Net Framework 2, so I use a StringBuilder class variant though.

If your project (.csproj) allow unsafe code probably this is the faster solution:
namespace System
{
public static class StringExt
{
public static unsafe void ReplaceAt(this string source, int index, char value)
{
if (source == null)
throw new ArgumentNullException("source");
if (index < 0 || index >= source.Length)
throw new IndexOutOfRangeException("invalid index value");
fixed (char* ptr = source)
{
ptr[index] = value;
}
}
}
}
You may use it as extension method of String objects.

public string ReplaceChar(string sourceString, char newChar, int charIndex)
{
try
{
// if the sourceString exists
if (!String.IsNullOrEmpty(sourceString))
{
// verify the lenght is in range
if (charIndex < sourceString.Length)
{
// Get the oldChar
char oldChar = sourceString[charIndex];
// Replace out the char ***WARNING - THIS CODE IS WRONG - it replaces ALL occurrences of oldChar in string!!!***
sourceString.Replace(oldChar, newChar);
}
}
}
catch (Exception error)
{
// for debugging only
string err = error.ToString();
}
// return value
return sourceString;
}

Related

How to upper case first letter of every word, while not lower casing the rest of the letters? [duplicate]

I have a DetailsView with a TextBox
and I want the input data be saved always with the first letter in capital.
Example:
"red" --> "Red"
"red house" --> " Red house"
How can I achieve this maximizing performance?
Note:
Based on the answers and the comments under the answers, many people think this is asking about capitalizing all words in the string. E.g. => Red House It isn't, but if that is what you seek, look for one of the answers that uses TextInfo's ToTitleCase method. (Note: Those answers are incorrect for the question actually asked.)
See TextInfo.ToTitleCase documentation for caveats (doesn't touch all-caps words - they are considered acronyms; may lowercase letters in middle of words that "shouldn't" be lowered, e.g., "McDonald" → "Mcdonald"; not guaranteed to handle all culture-specific subtleties re capitalization rules.)
Note:
The question is ambiguous as to whether letters after the first should be forced to lower case. The accepted answer assumes that only the first letter should be altered. If you want to force all letters in the string except the first to be lower case, look for an answer containing ToLower, and not containing ToTitleCase.
Solution in different C# versions
C# 8 with at least .NET Core 3.0 or .NET Standard 2.1
public static class StringExtensions
{
public static string FirstCharToUpper(this string input) =>
input switch
{
null => throw new ArgumentNullException(nameof(input)),
"" => throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input)),
_ => string.Concat(input[0].ToString().ToUpper(), input.AsSpan(1))
};
}
Since .NET Core 3.0 / .NET Standard 2.1 String.Concat() supports ReadonlySpan<char> which saves one allocation if we use .AsSpan(1) instead of .Substring(1).
C# 8
public static class StringExtensions
{
public static string FirstCharToUpper(this string input) =>
input switch
{
null => throw new ArgumentNullException(nameof(input)),
"" => throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input)),
_ => input[0].ToString().ToUpper() + input.Substring(1)
};
}
C# 7
public static class StringExtensions
{
public static string FirstCharToUpper(this string input)
{
switch (input)
{
case null: throw new ArgumentNullException(nameof(input));
case "": throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input));
default: return input[0].ToString().ToUpper() + input.Substring(1);
}
}
}
Really old answers
public static string FirstCharToUpper(string input)
{
if (String.IsNullOrEmpty(input))
throw new ArgumentException("ARGH!");
return input.First().ToString().ToUpper() + String.Join("", input.Skip(1));
}
This version is shorter. For a faster solution, take a look at Diego's answer.
public static string FirstCharToUpper(string input)
{
if (String.IsNullOrEmpty(input))
throw new ArgumentException("ARGH!");
return input.First().ToString().ToUpper() + input.Substring(1);
}
Probably the fastest solution is Darren's (There's even a benchmark) although I would change it's string.IsNullOrEmpty(s) validation to throw an exception since the original requirement expects for a first letter to exist so it can be uppercased. Note that this code works for a generic string and not particularly on valid values from the Textbox.
public string FirstLetterToUpper(string str)
{
if (str == null)
return null;
if (str.Length > 1)
return char.ToUpper(str[0]) + str.Substring(1);
return str.ToUpper();
}
this can also be written as
public string ToTitleCase(string str)
{
var firstword = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str.Split(' ')[0].ToLower());
str = str.Replace(str.Split(' ')[0],firstword);
return str;
}
Where it picks up the first word and converts it to title case then replaces it in the input string.
The right way is to use Culture:
System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(word.ToLower())
Note: This will capitalise each word within a string, e.g. "red house" --> "Red House". The solution will also lower-case capitalisation within words, e.g. "old McDonald" --> "Old Mcdonald".
I took the fastest method from C# Uppercase First Letter - Dot Net Perls and converted to an extension method:
/// <summary>
/// Returns the input string with the first character converted to uppercase, or mutates any nulls passed into string.Empty
/// </summary>
public static string FirstLetterToUpperCaseOrConvertNullToEmptyString(this string s)
{
if (string.IsNullOrEmpty(s))
return string.Empty;
char[] a = s.ToCharArray();
a[0] = char.ToUpper(a[0]);
return new string(a);
}
NOTE: The reason using ToCharArray is faster than the alternative char.ToUpper(s[0]) + s.Substring(1), is that only one string is allocated, whereas the Substring approach allocates a string for the substring, and then a second string to compose the final result.
Here is what this approach looks like, combined with the initial test from CarlosMuñoz's accepted answer:
/// <summary>
/// Returns the input string with the first character converted to uppercase
/// </summary>
public static string FirstLetterToUpperCase(this string s)
{
if (string.IsNullOrEmpty(s))
throw new ArgumentException("There is no first letter");
char[] a = s.ToCharArray();
a[0] = char.ToUpper(a[0]);
return new string(a);
}
You can use the "ToTitleCase method":
string s = new CultureInfo("en-US").TextInfo.ToTitleCase("red house");
//result : Red House
This extension method solves every titlecase problem.
It is easy to use:
string str = "red house";
str.ToTitleCase();
//result : Red house
string str = "red house";
str.ToTitleCase(TitleCase.All);
//result : Red House
The extension method:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
namespace Test
{
public static class StringHelper
{
private static CultureInfo ci = new CultureInfo("en-US");
//Convert all first latter
public static string ToTitleCase(this string str)
{
str = str.ToLower();
var strArray = str.Split(' ');
if (strArray.Length > 1)
{
strArray[0] = ci.TextInfo.ToTitleCase(strArray[0]);
return string.Join(" ", strArray);
}
return ci.TextInfo.ToTitleCase(str);
}
public static string ToTitleCase(this string str, TitleCase tcase)
{
str = str.ToLower();
switch (tcase)
{
case TitleCase.First:
var strArray = str.Split(' ');
if (strArray.Length > 1)
{
strArray[0] = ci.TextInfo.ToTitleCase(strArray[0]);
return string.Join(" ", strArray);
}
break;
case TitleCase.All:
return ci.TextInfo.ToTitleCase(str);
default:
break;
}
return ci.TextInfo.ToTitleCase(str);
}
}
public enum TitleCase
{
First,
All
}
}
For the first letter, with error checking:
public string CapitalizeFirstLetter(string s)
{
if (String.IsNullOrEmpty(s))
return s;
if (s.Length == 1)
return s.ToUpper();
return s.Remove(1).ToUpper() + s.Substring(1);
}
And here's the same as a handy extension
public static string CapitalizeFirstLetter(this string s)
{
if (String.IsNullOrEmpty(s))
return s;
if (s.Length == 1)
return s.ToUpper();
return s.Remove(1).ToUpper() + s.Substring(1);
}
Using string.Create() and avoiding the throw keyword in our method (yes, you read it right), we can take Marcell's answer one step further. Also, my method handles strings of arbitrary length (e.g., several megabytes of text).
public static string L33t(this string s)
{
static void ThrowError() => throw new ArgumentException("There is no first letter");
if (string.IsNullOrEmpty(s))
ThrowError(); // No "throw" keyword to avoid costly IL
return string.Create(s.Length, s, (chars, state) =>
{
state.AsSpan().CopyTo(chars); // No slicing to save some CPU cycles
chars[0] = char.ToUpper(chars[0]);
});
}
Performance
Here are the numbers for benchmarks run on .NET Core 3.1.7, 64 bit. I added a longer string to pinpoint the cost of extra copies.
Method
Data
Mean
Error
StdDev
Median
L33t
red
8.545 ns
0.4612 ns
1.3308 ns
8.075 ns
Marcell
red
9.153 ns
0.3377 ns
0.9471 ns
8.946 ns
L33t
red house
7.715 ns
0.1741 ns
0.4618 ns
7.793 ns
Marcell
red house
10.537 ns
0.5002 ns
1.4351 ns
10.377 ns
L33t
red r(...)house [89]
11.121 ns
0.6774 ns
1.9106 ns
10.612 ns
Marcell
red r(...)house [89]
16.739 ns
0.4468 ns
1.3033 ns
16.853 ns
Full test code
using System;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
namespace CorePerformanceTest
{
class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<StringUpperTest>();
}
}
public class StringUpperTest
{
[Params("red", "red house", "red red red red red red red red red red red red red red red red red red red red red house")]
public string Data;
[Benchmark]
public string Marcell() => Data.Marcell();
[Benchmark]
public string L33t() => Data.L33t();
}
internal static class StringExtensions
{
public static string Marcell(this string s)
{
if (string.IsNullOrEmpty(s))
throw new ArgumentException("There is no first letter");
Span<char> a = stackalloc char[s.Length];
s.AsSpan(1).CopyTo(a.Slice(1));
a[0] = char.ToUpper(s[0]);
return new string(a);
}
public static string L33t(this string s)
{
static void ThrowError() => throw new ArgumentException("There is no first letter");
if (string.IsNullOrEmpty(s))
ThrowError(); // IMPORTANT: Do not "throw" here!
return string.Create(s.Length, s, (chars, state) =>
{
state.AsSpan().CopyTo(chars);
chars[0] = char.ToUpper(chars[0]);
});
}
}
}
Please let me know if you can make it any faster!
public static string ToInvarianTitleCase(this string self)
{
if (string.IsNullOrWhiteSpace(self))
{
return self;
}
return CultureInfo.InvariantCulture.TextInfo.ToTitleCase(self);
}
As this question is about maximizing performance, I adopted Darren's version to use Spans, which reduces garbage and improves speed by about 10%.
/// <summary>
/// Returns the input string with the first character converted to uppercase
/// </summary>
public static string ToUpperFirst(this string s)
{
if (string.IsNullOrEmpty(s))
throw new ArgumentException("There is no first letter");
Span<char> a = stackalloc char[s.Length];
s.AsSpan(1).CopyTo(a.Slice(1));
a[0] = char.ToUpper(s[0]);
return new string(a);
}
Performance
Method
Data
Mean
Error
StdDev
Carlos
red
107.29 ns
2.2401 ns
3.9234 ns
Darren
red
30.93 ns
0.9228 ns
0.8632 ns
Marcell
red
26.99 ns
0.3902 ns
0.3459 ns
Carlos
red house
106.78 ns
1.9713 ns
1.8439 ns
Darren
red house
32.49 ns
0.4253 ns
0.3978 ns
Marcell
red house
27.37 ns
0.3888 ns
0.3637 ns
Full test code
using System;
using System.Linq;
using BenchmarkDotNet.Attributes;
namespace CorePerformanceTest
{
public class StringUpperTest
{
[Params("red", "red house")]
public string Data;
[Benchmark]
public string Carlos() => Data.Carlos();
[Benchmark]
public string Darren() => Data.Darren();
[Benchmark]
public string Marcell() => Data.Marcell();
}
internal static class StringExtensions
{
public static string Carlos(this string input) =>
input switch
{
null => throw new ArgumentNullException(nameof(input)),
"" => throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input)),
_ => input.First().ToString().ToUpper() + input.Substring(1)
};
public static string Darren(this string s)
{
if (string.IsNullOrEmpty(s))
throw new ArgumentException("There is no first letter");
char[] a = s.ToCharArray();
a[0] = char.ToUpper(a[0]);
return new string(a);
}
public static string Marcell(this string s)
{
if (string.IsNullOrEmpty(s))
throw new ArgumentException("There is no first letter");
Span<char> a = stackalloc char[s.Length];
s.AsSpan(1).CopyTo(a.Slice(1));
a[0] = char.ToUpper(s[0]);
return new string(a);
}
}
}
The fastest method:
private string Capitalize(string s){
if (string.IsNullOrEmpty(s))
{
return string.Empty;
}
char[] a = s.ToCharArray();
a[0] = char.ToUpper(a[0]);
return new string(a);
}
Tests show the next results (string with 1,0000,000 symbols as input):
Test results
Try this:
static public string UpperCaseFirstCharacter(this string text) {
return Regex.Replace(text, "^[a-z]", m => m.Value.ToUpper());
}
Check if the string is not null, convert the first character to upper case and the rest of them to lower case:
public static string FirstCharToUpper(string str)
{
return str?.First().ToString().ToUpper() + str?.Substring(1).ToLower();
}
If performance/memory usage is an issue then, this one only creates one (1) StringBuilder and one (1) new String of the same size as the original string.
public static string ToUpperFirst(this string str) {
if(!string.IsNullOrEmpty(str)) {
StringBuilder sb = new StringBuilder(str);
sb[0] = char.ToUpper(sb[0]);
return sb.ToString();
} else return str;
}
Since I happened to be working on this also, and was looking around for any ideas, this is the solution I came to. It uses LINQ, and will be able to capitalize the first letter of a string, even if the first occurrence isn't a letter. Here's the extension method I ended up making.
public static string CaptalizeFirstLetter(this string data)
{
var chars = data.ToCharArray();
// Find the Index of the first letter
var charac = data.First(char.IsLetter);
var i = data.IndexOf(charac);
// capitalize that letter
chars[i] = char.ToUpper(chars[i]);
return new string(chars);
}
I'm sure there's a way to optimize or clean this up a little bit.
If you only care about the first letter being capitalized and it does not matter the rest of the string, you can just select the first character, make it upper case and concatenate it with the rest of the string without the original first character.
String word ="red house";
word = word[0].ToString().ToUpper() + word.Substring(1, word.length -1);
//result: word = "Red house"
We need to convert the first character ToString(), because we are reading it as a Char array, and the Char type does not have a ToUpper() method.
Here's a way to do it as an extension method:
static public string UpperCaseFirstCharacter(this string text)
{
if (!string.IsNullOrEmpty(text))
{
return string.Format(
"{0}{1}",
text.Substring(0, 1).ToUpper(),
text.Substring(1));
}
return text;
}
It can then be called like:
//yields "This is Brian's test.":
"this is Brian's test.".UpperCaseFirstCharacter();
And here are some unit tests for it:
[Test]
public void UpperCaseFirstCharacter_ZeroLength_ReturnsOriginal()
{
string orig = "";
string result = orig.UpperCaseFirstCharacter();
Assert.AreEqual(orig, result);
}
[Test]
public void UpperCaseFirstCharacter_SingleCharacter_ReturnsCapital()
{
string orig = "c";
string result = orig.UpperCaseFirstCharacter();
Assert.AreEqual("C", result);
}
[Test]
public void UpperCaseFirstCharacter_StandardInput_CapitalizeOnlyFirstLetter()
{
string orig = "this is Brian's test.";
string result = orig.UpperCaseFirstCharacter();
Assert.AreEqual("This is Brian's test.", result);
}
I found something in C# Uppercase First Letter - Dot Net Perls:
static string UppercaseFirst(string s)
{
// Check for empty string.
if (string.IsNullOrEmpty(s))
{
return string.Empty;
}
// Return char and concat substring.
return char.ToUpper(s[0]) + s.Substring(1);
}
This will do it although it will also make sure that there are no errant capitals that are not at the beginning of the word.
public string(string s)
{
System.Globalization.CultureInfo c = new System.Globalization.CultureInfo("en-us", false)
System.Globalization.TextInfo t = c.TextInfo;
return t.ToTitleCase(s);
}
We can do this (C# 8.0, .NET 5):
input?.Length > 0 ? char.ToUpperInvariant(input[0]) + input[1..] : input
I believe that is short enough to do inline.
If input is an empty string, we get an empty string. If input is null, we get null.
Otherwise, the code takes the first character input[0] and convert it to uppercase with char.ToUpperInvariant. And concatenate the rest input[1..].
The compiler will convert the range access to a call to Substring, plus it can take advantage of the fact that we already got the length.
Over the accepted answer, this has the advantage of not using LINQ. Some other answers convert the string to array just to take the first character. This code does not do that either.
If you prefer an extension method, you can do this:
public static string FirstCharToUpper(this string input) =>
input?.Length > 0 ? char.ToUpperInvariant(input[0]) + input[1..] : input;
What if you prefer to throw? OK, have it throw:
public static string FirstCharToUpper(this string input) =>
input switch
{
null => throw new ArgumentNullException(nameof(input)),
_ => input.Length > 0 ? char.ToUpperInvariant(input[0]) + input[1..] : input
};
Here roughly equivalent code (since we are making an extension method, we can be a bit more verbose):
public static string FirstCharToUpperEquivalent(this string input)
{
if (input == null)
{
throw new ArgumentNullException(nameof(input));
}
var length = input.Length;
if (length == 0)
{
return input;
}
string firstCharacter = char.ToUpperInvariant(input[0]).ToString();
return string.Concat(firstCharacter, input.Substring(1, length - 1));
}
I did a benchmark with 1000 rounds of 155 words (So they were called 155000 times), and this is the result:
Benchmarking type Tests
TestAccepted 00:00:00.0465979
TestProposalNoThrow 00:00:00.0092839
TestProposalDoThrow 00:00:00.0092938
TestProposalEquival 00:00:00.0091463
I ran it on Windows 10, Intel Core i3, using the code from Simple microbenchmarking in C# by Jon Skeet.
string emp="TENDULKAR";
string output;
output=emp.First().ToString().ToUpper() + String.Join("", emp.Skip(1)).ToLower();
Here's the code that worked for me:
private string StringLetterUppercase(string input)
{
if (input == null)
{
throw new ArgumentNullException(nameof(input));
}
else if (input == "")
{
throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input));
}
else
{
return input.First().ToString().ToUpper() + input.Substring(1);
}
}
There seems to be a lot of complexity here when all you need is:
/// <summary>
/// Returns the input string with the first character converted to uppercase if a letter
/// </summary>
/// <remarks>Null input returns null</remarks>
public static string FirstLetterToUpperCase(this string s)
{
if (string.IsNullOrWhiteSpace(s))
return s;
return char.ToUpper(s[0]) + s.Substring(1);
}
Noteworthy points:
It's an extension method.
If the input is null, empty or white space the input is returned as is.
String.IsNullOrWhiteSpace was introduced with .NET Framework 4. This won't work with older frameworks.
I think the below method is the best solution.
class Program
{
static string UppercaseWords(string value)
{
char[] array = value.ToCharArray();
// Handle the first letter in the string.
if (array.Length >= 1)
{
if (char.IsLower(array[0]))
{
array[0] = char.ToUpper(array[0]);
}
}
// Scan through the letters, checking for spaces.
// ... Uppercase the lowercase letters following spaces.
for (int i = 1; i < array.Length; i++)
{
if (array[i - 1] == ' ')
{
if (char.IsLower(array[i]))
{
array[i] = char.ToUpper(array[i]);
}
}
}
return new string(array);
}
static void Main()
{
// Uppercase words in these strings.
const string value1 = "something in the way";
const string value2 = "dot net PERLS";
const string value3 = "String_two;three";
const string value4 = " sam";
// ... Compute the uppercase strings.
Console.WriteLine(UppercaseWords(value1));
Console.WriteLine(UppercaseWords(value2));
Console.WriteLine(UppercaseWords(value3));
Console.WriteLine(UppercaseWords(value4));
}
}
Output
Something In The Way
Dot Net PERLS
String_two;three
Sam
Reference
Possible solution to resolve your problem:
public static string FirstToUpper(this string lowerWord)
{
if (string.IsNullOrWhiteSpace(lowerWord) || string.IsNullOrEmpty(lowerWord))
return lowerWord;
return new StringBuilder(lowerWord.Substring(0, 1).ToUpper())
.Append(lowerWord.Substring(1))
.ToString();
}
I wanted to provide a "maximum performance" answer. In my mind, a "maximum performance" answer catches all scenarios and provides the answer to the question accounting for those scenarios. So, here is my answer. With these reasons:
IsNullOrWhiteSpace accounts for strings that are just spaces or null/empty.
.Trim() removes white space from the front and back of the string.
.First() takes the first element of an IEnumerable<TSource> (or string).
We should check to see if it is a letter that can/should be uppercase.
We then add the rest of the string, only if the length indicates we should.
By .NET best practice, we should provide a culture under System.Globalization.CultureInfo.
Providing them as optional parameters makes this method totally reusable, without having to type the chosen culture every time.
I also noticed that my and most of these answers did not maintain the whitespace at the beginning of the string. This will also show how to maintain that whitespace.
//Capitalize the first letter disregard all chars using regex.
public static string RegCapString(this string instring, string culture = "en-US", bool useSystem = false)
{
if (string.IsNullOrWhiteSpace(instring))
{
return instring;
}
var m = Regex.Match(instring, "[A-Za-z]").Index;
return instring.Substring(0, m) + instring[m].ToString().ToUpper(new CultureInfo(culture, useSystem)) + instring.Substring(m + 1);
}
//Capitalize first char if it is a letter disregard white space.
public static string CapString(this string instring, string culture = "en-US", bool useSystem = false)
{
if (string.IsNullOrWhiteSpace(instring) ||
!char.IsLetter(instring.Trim().First()))
{
return instring;
}
var whiteSpaces = instring.Length - instring.TrimStart().Length;
return (new string(' ', whiteSpaces)) +
instring.Trim().First().ToString().ToUpper(new CultureInfo(culture, useSystem)) +
((instring.TrimStart().Length > 1) ? instring.Substring(whiteSpaces + 1) : "");
}
Expanding on Carlos' question above, if you want to capitalize multiple sentences you may use this code:
/// <summary>
/// Capitalize first letter of every sentence.
/// </summary>
/// <param name="inputSting"></param>
/// <returns></returns>
public string CapitalizeSentences (string inputSting)
{
string result = string.Empty;
if (!string.IsNullOrEmpty(inputSting))
{
string[] sentences = inputSting.Split('.');
foreach (string sentence in sentences)
{
result += string.Format ("{0}{1}.", sentence.First().ToString().ToUpper(), sentence.Substring(1));
}
}
return result;
}
It seems like none of the solutions given here will deal with a white space before the string.
Just adding this as a thought:
public static string SetFirstCharUpper2(string aValue, bool aIgonreLeadingSpaces = true)
{
if (string.IsNullOrWhiteSpace(aValue))
return aValue;
string trimmed = aIgonreLeadingSpaces
? aValue.TrimStart()
: aValue;
return char.ToUpper(trimmed[0]) + trimmed.Substring(1);
}
It should handle this won't work on other answers (that sentence has a space in the beginning), and if you don't like the space trimming, just pass a false as the second parameter (or change the default to false, and pass true if you want to deal with space)).
FluentSharp has the lowerCaseFirstLetter method which does this.
This is the fastest way:
public static unsafe void ToUpperFirst(this string str)
{
if (str == null)
return;
fixed (char* ptr = str)
*ptr = char.ToUpper(*ptr);
}
Without changing the original string:
public static unsafe string ToUpperFirst(this string str)
{
if (str == null)
return null;
string ret = string.Copy(str);
fixed (char* ptr = ret)
*ptr = char.ToUpper(*ptr);
return ret;
}
The following function is correct for all ways:
static string UppercaseWords(string value)
{
char[] array = value.ToCharArray();
// Handle the first letter in the string.
if (array.Length >= 1)
{
if (char.IsLower(array[0]))
{
array[0] = char.ToUpper(array[0]);
}
}
// Scan through the letters, checking for spaces.
// ... Uppercase the lowercase letters following spaces.
for (int i = 1; i < array.Length; i++)
{
if (array[i - 1] == ' ')
{
if (char.IsLower(array[i]))
{
array[i] = char.ToUpper(array[i]);
}
}
}
return new string(array);
}
I found that here.

c#- How can I format an output so that a string always takes up 7 digits?

string name1 = "John";
string name2 = "Alexander";
Console.WriteLine(??);
//desired output:
John Alexand
How can I format the strings so that they will always take up 7 spaces? I'm familiar with how to do this in C, but I cannot find a way to do it for C#.
Use PadRight and SubString
var a = "James";
Console.WriteLine(a.PadRight(7, ' ').Substring(0, 7));
Formatting like $"{name, 7}" ensures that the result will have length at least 7; however, longer inputs will not be trimmed (i.e. "Alexander" will not be trimmed to "Alexand").
We have to impement the logic manually and I suggest hiding it in an extension method:
public static class StringExtensions {
public static string ToLength(this string source, int length) {
if (length < 0)
throw new ArgumentOutOfRangeException("length");
else if (length == 0)
return "";
else if (string.IsNullOrEmpty(source))
return new string(' ', length);
else if (source.Length < length)
return source.PadRight(length);
else
return source.Substring(0, length);
}
}
usage:
Console.WriteLine($"{name1.ToLength(7)} {name2.ToLength(7)}");
I would use an extension method coupled with PadRight()
public void Main() {
string name1 = "John";
string name2 = "Alexander";
string FullName = name1.FixLeft(7) + name2.FixLeft(7);
Console.WriteLine(FullName);
}
private static string FixLeft(this string TextInput, int DesiredLength) {
if (TextInput.Length < DesiredLength) { return TextInput.PadRight(DesiredLength); }
else { return TextInput.Substring(0,DesiredLength); }
}

How to find how many string in other string

I randomly trying to make this code works. The problem that I have is I can't find the string in some string, because char only takes one character.
Is there another way to do it?
e.g. I can find how many char "e" in "excellent", But I can't find "ll". It'll give me error.
The code which I use:
try
{
int count = label1.Text.Split(Convert.ToChar(textBox1.Text)).Length - 1;
MessageBox.Show(count.ToString());
}
catch
{
messagebox.show("error");
}
Thats why I am using try to catch the error.
This is because you use Convert.ToChar(...) which is supposed to take only convertible string to char (that is, consists of a single character, but "ll" consists of two characters).
You could create an extension for string to do what you want:
public static class StringExtensions {
public static List<int> AllIndexesOf(this string str, string value) {
if (String.IsNullOrEmpty(value))
throw new ArgumentException("the string to find may not be empty", "value");
List<int> indexes = new List<int>();
for (int index = 0; ; index += value.Length) {
index = str.IndexOf(value, index);
if (index == -1)
return indexes;
indexes.Add(index);
}
}
}
And then just use it like:
int count = label1.Text.AllIndexesOf(textBox1.Text).Count;

Split the string after a word

I want to split a string after a word, not after the character.
Example string:
A-quick-brown-fox-jumps-over-the-lazy-dog
I want to split the string after "jumps-"
can I use the stringname.Split("jumps-") function?
I want the following output:
over-the-lazy-dog.
I suggest using IndexOf and Substring since you actually want a suffix ("String after word"), not a split:
string source = "A-quick-brown-fox-jumps-over-the-lazy-dog";
string split = "jumps-";
// over-the-lazy-dog
string result = source.Substring(source.IndexOf(split) + split.Length);
var theString = "A-quick-brown-fox-jumps-over-the-lazy-dog.";
var afterJumps = theString.Split(new[] { "jumps-" }, StringSplitOptions.None)[1]; //Index 0 would be what is before 'jumps-', index 1 is after.
I usually use extension methods:
public static string join(this string[] strings, string delimiter) { return string.Join(delimiter, strings); }
public static string[] splitR(this string str, params string[] delimiters) { return str.Split(delimiters, StringSplitOptions.RemoveEmptyEntries); }
//public static string[] splitL(this string str, string delimiter = " ", int limit = -1) { return vb.Strings.Split(str, delimiter, limit); }
public static string before(this string str, string delimiter) { int i = (str ?? ""). IndexOf(delimiter ?? ""); return i < 0 ? str : str.Remove (i ); } // or return str.splitR(delimiter).First();
public static string after (this string str, string delimiter) { int i = (str ?? "").LastIndexOf(delimiter ?? ""); return i < 0 ? str : str.Substring(i + delimiter.Length); } // or return str.splitR(delimiter).Last();
sample use:
stringname.after("jumps-").splitR("-"); // splitR removes empty entries
You could extend the Split() method. In fact, I did this a few months ago. Probably not the prettiest code but it gets the job done. This method splits at every jumps-, not just at the first one.
public static class StringExtensions
{
public static string[] Split(this String Source, string Separator)
{
if (String.IsNullOrEmpty(Source))
throw new Exception("Source string is null or empty!");
if (String.IsNullOrEmpty(Separator))
throw new Exception("Separator string is null or empty!");
char[] _separator = Separator.ToArray();
int LastMatch = 0;
List<string> Result = new List<string>();
Func<char[], char[], bool> Matches = (source1, source2) =>
{
for (int i = 0; i < source1.Length; i++)
{
if (source1[i] != source2[i])
return false;
}
return true;
};
for (int i = 0; _separator.Length + i < Source.Length; i++)
{
if (Matches(_separator.ToArray(), Source.Substring(i, _separator.Length).ToArray()))
{
Result.Add(Source.Substring(LastMatch, i - LastMatch));
LastMatch = i + _separator.Length;
}
}
Result.Add(Source.Substring(LastMatch, Source.Length - LastMatch));
return Result.ToArray();
}
}

Determine if string has all unique characters

I'm working through an algorithm problem set which poses the following question:
"Determine if a string has all unique characters. Assume you can only use arrays".
I have a working solution, but I would like to see if there is anything better optimized in terms of time complexity. I do not want to use LINQ. Appreciate any help you can provide!
static void Main(string[] args)
{
FindDupes("crocodile");
}
static string FindDupes(string text)
{
if (text.Length == 0 || text.Length > 256)
{
Console.WriteLine("String is either empty or too long");
}
char[] str = new char[text.Length];
char[] output = new char[text.Length];
int strLength = 0;
int outputLength = 0;
foreach (char value in text)
{
bool dupe = false;
for (int i = 0; i < strLength; i++)
{
if (value == str[i])
{
dupe = true;
break;
}
}
if (!dupe)
{
str[strLength] = value;
strLength++;
output[outputLength] = value;
outputLength++;
}
}
return new string(output, 0, outputLength);
}
If time complexity is all you care about you could map the characters to int values, then have an array of bool values which remember if you've seen a particular character value previously.
Something like ... [not tested]
bool[] array = new bool[256]; // or larger for Unicode
foreach (char value in text)
if (array[(int)value])
return false;
else
array[(int)value] = true;
return true;
try this,
string RemoveDuplicateChars(string key)
{
string table = string.Empty;
string result = string.Empty;
foreach (char value in key)
{
if (table.IndexOf(value) == -1)
{
table += value;
result += value;
}
}
return result;
}
usage
Console.WriteLine(RemoveDuplicateChars("hello"));
Console.WriteLine(RemoveDuplicateChars("helo"));
Console.WriteLine(RemoveDuplicateChars("Crocodile"));
output
helo
helo
Crocdile
public boolean ifUnique(String toCheck){
String str="";
for(int i=0;i<toCheck.length();i++)
{
if(str.contains(""+toCheck.charAt(i)))
return false;
str+=toCheck.charAt(i);
}
return true;
}
EDIT:
You may also consider to omit the boundary case where toCheck is an empty string.
The following code works:
static void Main(string[] args)
{
isUniqueChart("text");
Console.ReadKey();
}
static Boolean isUniqueChart(string text)
{
if (text.Length == 0 || text.Length > 256)
{
Console.WriteLine(" The text is empty or too larg");
return false;
}
Boolean[] char_set = new Boolean[256];
for (int i = 0; i < text.Length; i++)
{
int val = text[i];//already found this char in the string
if (char_set[val])
{
Console.WriteLine(" The text is not unique");
return false;
}
char_set[val] = true;
}
Console.WriteLine(" The text is unique");
return true;
}
If the string has only lower case letters (a-z) or only upper case letters (A-Z) you can use a very optimized O(1) solution.Also O(1) space.
c++ code :
bool checkUnique(string s){
if(s.size() >26)
return false;
int unique=0;
for (int i = 0; i < s.size(); ++i) {
int j= s[i]-'a';
if(unique & (1<<j)>0)
return false;
unique=unique|(1<<j);
}
return true;
}
Remove Duplicates in entire Unicode Range
Not all characters can be represented by a single C# char. If you need to take into account combining characters and extended unicode characters, you need to:
parse the characters using StringInfo
normalize the characters
find duplicates amongst the normalized strings
Code to remove duplicate characters:
We keep track of the entropy, storing the normalized characters (each character is a string, because many characters require more than 1 C# char). In case a character (normalized) is not yet stored in the entropy, we append the character (in specified form) to the output.
public static class StringExtension
{
public static string RemoveDuplicateChars(this string text)
{
var output = new StringBuilder();
var entropy = new HashSet<string>();
var iterator = StringInfo.GetTextElementEnumerator(text);
while (iterator.MoveNext())
{
var character = iterator.GetTextElement();
if (entropy.Add(character.Normalize()))
{
output.Append(character);
}
}
return output.ToString();
}
}
Unit Test:
Let's test a string that contains variations on the letter A, including the Angstrom sign Å. The Angstrom sign has unicode codepoint u212B, but can also be constructed as the letter A with the diacritic u030A. Both represent the same character.
// ÅÅAaA
var input = "\u212BA\u030AAaA";
// ÅAa
var output = input.RemoveDuplicateChars();
Further extensions could allow for a selector function that determines how to normalize characters. For instance the selector (x) => x.ToUpperInvariant().Normalize() would allow for case-insensitive duplicate removal.
public static bool CheckUnique(string str)
{
int accumulator = 0;
foreach (int asciiCode in str)
{
int shiftedBit = 1 << (asciiCode - ' ');
if ((accumulator & shiftedBit) > 0)
return false;
accumulator |= shiftedBit;
}
return true;
}

Categories

Resources