How to capitalize the first character of every sentence - c#

Create an application with a method that accepts a string as an argument and returns a copy of the string with the first character of each sentence capitalized.
This is what I have to far and I can't seem to get it right:
//Create method to process string.
private string Sentences(string input)
{
//Capitalize first letter of input.
char firstLetter = char.ToUpper(input[0]);
//Combine the capitalize letter with the rest of the input.
input = firstLetter.ToString() + input.Substring(1);
//Create a char array to hold all characters in input.
char[] letters = new char[input.Length];
//Read the characters from input into the array.
for (int i = 0; i < input.Length; i++)
{
letters[i] = input[i];
}
//Loop through array to test for punctuation and capitalize a character 2 index away.
for (int index = 0; index < letters.Length; index++)
{
if(char.IsPunctuation(letters[index]))
{
if (!((index + 2) >= letters.Length))
{
char.ToUpper(letters[index+ 2]);
}
}
}
for(int ind = 0; ind < letters.Length; ind++)
{
input += letters[ind].ToString();
}
return input;
}

You could use Linq.Aggregate n - see comments in code and code output for explanation how it work's.
This one will respect "Bla. blubb" as well - you need to check for whitespaces after ".?!"
using System;
using System.Linq;
internal class Program
{
static string Capitalize(string oldSentence )
{
return
// this will look at oldSentence char for char, we start with a
// new string "" (the accumulator, short acc)
// and inspect each char c of oldSentence
// comment all the Console.Writelines in this function, thats
// just so you see whats done by Aggregate, not needed for it to
// work
oldSentence
.Aggregate("", (acc, c) =>
{
System.Console.WriteLine("Accumulated: " + acc);
System.Console.WriteLine("Cecking: " + c);
// if the accumulator is empty or the last character of
// trimmed acc is a ".?!" we append the
// upper case of c to it
if (acc.Length == 0 || ".?!".Any(p => p == acc.Trim().Last())) // (*)
acc += char.ToUpper(c);
else
acc += c; // else we add it unmodified
System.Console.WriteLine($"After: {acc}\n");
return acc; // this returns the acc for the next iteration/next c
});
}
static void Main(string[] args)
{
Console.SetBufferSize(120, 1000);
var oldSentence = "This is a testSentence. some occurences "
+ "need capitalization! for examlpe here. or here? maybe "
+ "yes, maybe not.";
var newSentence = Capitalize(oldSentence);
Console.WriteLine(new string('*', 80));
Console.WriteLine(newSentence);
Console.ReadLine();
}
}
(*)
".?!".Any(p => p == ... )) means does the string ".?!" contain any character that equals ...
acc.Trim().Last() means: remove whitespaces in front/on end of acc and give me the last character
.Last() and .Any() are also Linq. Most of the Linq-esc extension can be found here: https://msdn.microsoft.com/en-us/library/9eekhta0(v=vs.110).aspx
Output (snipped - its rather longish ;o)
Accumulated:
Cecking: T
After: T
Accumulated: T
Cecking: h
After: Th
Accumulated: Th
Cecking: i
After: Thi
Accumulated: Thi
Cecking: s
After: This
Accumulated: This
Cecking:
After: This
Accumulated: This
Cecking: i
After: This i
Accumulated: This i
Cecking: s
After: This is
<snipp - .. you get the idea how Aggregate works ...>
Accumulated: This is a testSentence.
Cecking: s
After: This is a testSentence. S
<snipp>
Accumulated: This is a testSentence. Some occurences need capitalization!
Cecking: f
After: This is a testSentence. Some occurences need capitalization! F
<snipp>
********************************************************************************
This is a testSentence. Some occurences need capitalization! For examlpe here. Or here? Maybe yes, maybe not.

I would suggest to use a regex to identify all the dots in your sentence. Get the match, make it upper case and replace it back in the original sentence, in the match index. I dont actually have any IDE in which try the code on .NET right now but i can write it in pseudocode for better understanding.
String setence = "your.setence.goes.here";
Regex rx = new Regex("/\..*?[A-Z]/");
foreach (Match match in rx.Matches(sentence))
{
setence.remove(match.Index, 2).insert(match.Index, String.ToUpper(match.Value));
}

You have two tasks:
1) Split text into sentences
2) Capitalize the first char in the sentences
Task one can be very complex, e.g. because there a lot of crazy languages out there. Put since this is homework I assume you can go ahead and simply split by well know separators.
Task two is just about basic string operations. You select the first char, make it uppercase and add the missing part of the sentence via a substring operation.
Here is a code example:
char[] separators = new char[] { '!', '.', '?' };
string[] sentencesArray = "First sentence. second sentence!lastone.".Split(separators, StringSplitOptions.RemoveEmptyEntries);
var i = 0;
Array.ForEach(sentencesArray, e =>
{
sentencesArray[i] = e.Trim().First().ToString().ToUpper() +
e.Trim().Substring(1);
i++;
});

I Have created a method in Groovy for the same
String capitalizeFirstCharInSentence(String str) {
String result = ''
str = str.toLowerCase()
List<String> strings = str.tokenize('.')
strings.each { line ->
StringBuilder builder = new StringBuilder(line)
int i = 0
while (i < builder.size() - 1 && !Character.isLowerCase(builder.charAt(i))) {
i++
}
if (Character.isLowerCase(builder.charAt(i))) {
builder.setCharAt(i, builder.charAt(i).toUpperCase())
result += builder.toString() + '.'
}
}
return result
}

I liked the way you formatted your method because it made it easy for newer coders to read so I decided to try to make the code work while maintaining the structure. The main problem I saw was that you were not replacing the arrays after formatting them.
//Create method to process string.
private string Sentences(string input)
{
//Create a char array to hold all characters in input.
char[] letters = new char[input.Length];
//Read the characters from input into the array.
for (int i = 0; i < input.Length; i++)
{
letters[i] = input[i];
}
//Capitalize first letter of input.
letters[0] = char.ToUpper(letters[0]);
//Loop through array to test for punctuation and capitalize a character 2 index away.
for (int index = 0; index < letters.Length; index++)
{
if(char.IsPunctuation(letters[index]))
{
if (index + 2 <= letters.Length)
{
letters[index + 2] = char.ToUpper(letters[index+ 2]);
}
}
}
// convert array back to string
string results = new string(letters)
return results;
}

Related

How to return the char, of a loops next position, in a char array?

I want to replace a string (that the user inputs) with the next character in the alphabet. I'm having trouble returning the next value from my loop.
Error message: Index was outside the bounds of the array.
I understand that the array ends, and that might be a problem from the +1 I entered. How would I go about solving this?
string inputString = "abcdefghijklmnopqqrstuvxyz";
char[] inputCharArray = inputString.ToCharArray();
char[] alphabetArray = "abcdefghijklmnopqrstuvxyz".ToArray();
var resultStr = "";
for (int i = 0; i < inputCharArray.Length; i++)
{
if(alphabetArray.Contains(inputCharArray[i]))
resultStr += inputCharArray[i+1];
else
resultStr += inputCharArray[i];
}
System.Console.WriteLine(resultStr);
You're getting an Out Of Range exception because i will eventually equal the last index of your input array, and adding 1 to that number is beyond what the array has.
First, make it easier on yourself by making a function to convert a single char into the next letter.
Note, this answer assumes that you want to "wrap around" - the next letter after "z" goes back to "a".
char NextLetter(char input)
{
if (input < 'a' || input > 'z') // simple validation
throw new ArgumentException();
input += (char)1; // go to the next char value
if (input > 'z') // did you go past z?
input = 'a'; // go back to a
return input;
}
Yes, you can also do modulo, this method is the simple version.
Now you can loop through all the letters in your input to construct the output string. In addition, you don't need to .ToCharArray() a string - a string already implements IEnumerable<char>.
var input = "abcxyz";
var outputBuilder = new StringBuilder();
foreach (char letter in input)
{
outputBuilder.Append(NextLetter(letter));
}
Console.WriteLine(outputBuilder.ToString());
// prints "bcdyza"
You can use Array.IndexOf to find the index of the current character in the alphabet, then you can use the modulo operator (%) to get the index of the next character in the alphabet (assuming the alphabet wraps from z to a in your desired solution):
string inputString = "abcdefghijklmnopqqrstuvxyz";
char[] inputCharArray = inputString.ToCharArray();
char[] alphabetArray = "abcdefghijklmnopqrstuvxyz".ToArray();
var resultStr = "";
for (var i = 0; i < inputCharArray.Length; i++)
{
var indexInAlphabet = Array.IndexOf(alphabetArray, inputCharArray[i]);
var indexOfNextLetter = (indexInAlphabet + 1) % alphabetArray.Length;
resultStr += alphabetArray[indexOfNextLetter];
}
Console.WriteLine(resultStr);

Remove all but specified substring from string

I have a string that contains several instances of a substring, as well as other text. The substring is specified by beginning with a given sequence of letters (e.g. CNTY) and ending with a double slash (//). How could I efficiently remove all text that does not fall inside the specified substring? Thanks for the help. I found that this Regex will return the result needed:
string result = Regex.Matches(text, "CNTY(.*)//").Cast<Match>().Aggregate("", (s, t) => s + t.Value, s => s);
But, I have another more complicated substring, which begins with WEATHLOC, then contains wildcard text across several lines, and ends with a line beginning RMKS, more wildcard text, and then //. Here is an example:
WEATHLOC/ICAO:KCOS//
OBSTIME/052005Z//
WIND/360/10//
VSBY/10/SM//
CLDLYR/-/LYR:BKN//
TEMP/MAXTEMP:15/MINTEMP:18//
ALTSTG/HG:29.92//
RMKS/SAMPLE//
Everything from WEATHLOC to the final // needs to be captured, and I can only rely on its beginning with WEATHLOC and ending with RMKS*//. Is there a way to express that in a Regex match?
This should work:
string text = "hiCNTYhello//content What /-CNTYworld//12texCNTY!//That's it";
string search = "CNTY(.*?)//";
MatchCollection matches = Regex.Matches(text, search);
Will match "hello", "world" and "!"
This little code segment works. The RegEx method was too difficult for me, but this does work. We are trying to check if we are in bounds of CNTY // and to output that text to the StringBuilder.
static void Main(string[] args)
{
var input = #"CNTYTestingTesting//This is some more test CNTY1234//And some moreCNTYWhat is this?//";
var sb = new StringBuilder();
int inCnty = -1;
for (int i = 0; i < input.Length; i ++)
{
// Test for start
if (i < input.Length - 4)
{
if (input.Substring(i, 4) == "CNTY")
{
inCnty = i + 4; // Index of first CNTY
}
}
// Test for end
if (i < input.Length - 1)
{
if (input.Substring(i, 2) == #"//")
{
inCnty = -1; // Reset
}
}
// Test if we are in the segment
if (i >= inCnty && inCnty > 0)
{
// Outside string
sb.Append(input[i]);
}
}
var output = sb.ToString();
Console.WriteLine(output);
Console.Read();
}

Reverse Words at odd position only C#

This is my code. How can I edit it to show every word which is at the odd position ONLY to be reversed?
for (int i = input.Length - 1; i >= 0; i--)
{
if (input[i] == ' ')
{
result = tmp + " " + result;
tmp = "";
}
else
tmp += input[i];
}
result = tmp + " " + result;
Console.WriteLine(result);
Example input:
"How are you today"
to output:
"How era you yadot"
Based on the position of a word ['How' -> 0] do not reverse; [are -> 1 odd index] Reverse
You can achieve it with the help of LINQ:
var input = "hello this is a test message";
var inputWords = input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
var result = string.Join(" ",
inputWords.Select((w, i) =>
i % 2 == 0
? w
: new string(w.Reverse().ToArray())
));
Where w in the select is the word, and i is the index, starting at 0 for the first word. % is the modulus operator and gets the remainder. If i % 2 == 0 (i.e. i can be divided by 2 with no remainder), then the original is returned. If there is a remainder (odd) then the reversed word is returned. Finally, it's all wrapped up in a string.Join(" ", items); which turns it back into a normal string rather than an array of items.
Try it online
So far you have a string, like this:
string input = "I want to reverse all odd words (odd words only!).";
And you, naturally, want to perform the task. Now it's the main question what's an odd word?
If you mean word's position (I at position 0, want at 1 - should be reversed etc.)
then you can use regular expressions to match words and Linq to process them:
using System.Linq; // To reverse single word
using System.Text.RegularExpressions; // To match the words within the text
...
// Let's elaborate the test example: add
// 1. some punctuation - ()!. - to preserve it
// 2. different white spaces (spaces and tabulation - \t)
// to add difficulties for naive algorithms
// 3. double spaces (after "to") to mislead split based algorithms
string input = "I want to reverse all\todd words (odd words only!).";
int index = 0; // words' indexes start from zero
string result = Regex.Replace(
input,
"[A-Za-z']+", // word is letters and apostrophes
match => index++ % 2 == 0
? match.Value // Even words intact
: string.Concat(match.Value.Reverse())); // Odd words reversed
Console.WriteLine(result);
If you want to reverse the words with odd Length, i.e. I, all, odd then all you have to do is to change the condition to
match => match.Value % 2 == 0
Outcome:
I tnaw to esrever all ddo words (ddo words ylno!).
Please, notice, that the punctuation has been preserved (only words are reversed).
OP: Based on the position of a word ['How' -> 0] do not reverse; [are -> 1 odd index] Reverse
public static void Main()
{
string input = "How are you today Laken-C";
//As pointed out by #Dmitry Bychenko string input = "How are you today";
//(double space after How) leads to How are uoy today outcome
input = Regex.Replace(input, #"\s+", " ");
var inp = input.Split(' ').ToList();
for (int j = 0; j < inp.Count(); j++)
{
if(j % 2 == 1)
{
Console.Write(inp[j].Reverse().ToArray());
Console.Write(" ");
}
else
Console.Write(inp[j] + " ");
}
}
OUTPUT:
DEMO:
dotNetFiddle
try this is perfect working code..
static void Main(string[] args)
{
string orgstr = "my name is sagar";
string revstr = "";
foreach (var word in orgstr.Split(' '))
{
string temp = "";
foreach (var ch in word.ToCharArray())
{
temp = ch + temp;
}
revstr = revstr + temp + " ";
}
Console.Write(revstr);
Console.ReadKey();
}
Output: ym eman si ragas

How do I alternate the case in a string?

I need to alternate the case in a sentence and I don't know how to.
For example:
thequickbrownfoxjumpsoverthelazydog
to
GoDyZaLeHtReVoSpMuJxOfNwOrBkCiUqEhT
this is my code so far
Console.WriteLine("Please enter a sentence:");
string text = Console.ReadLine();
text = text.Replace(" ", "");
char[] reversed = text.ToCharArray();//String to char
Array.Reverse(reversed);//Reverses char
new string(reversed);//Char to string
Console.WriteLine(reversed);
Console.ReadLine();
Please note that there are no spaces for a reason as that's also part of the homework task.
A string is immutable, so, you need to convert it to a char[].
char[] characters = text.ToCharArray();
for (int i = 0; i < characters.Length; i+=2) {
characters[i] = char.ToUpper(characters[i]);
}
text = new string(characters);
There is no point to reverse your string. Just upper case your even number indexed characters in your string.
Remember, my culture is tr-TR and this String.ToUpper method works depends on your current thread culture. In this example, your output can be different than mine.
Here an example in LINQPad;
string s = "thequickbrownfoxjumpsoverthelazydog";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.Length; i++)
{
if (i % 2 == 0)
{
sb.Append(s[i].ToString().ToUpper());
}
else
{
sb.Append(s[i].ToString());
}
}
sb.ToString().Dump();
Output will be;
ThEqUiCkBrOwNfOxJuMpSoVeRtHeLaZyDoG
Another possible solution with LINQ can be done in one line like this:
string s = "thequickbrownfoxjumpsoverthelazydog";
string result = new String(s
// take each character
.ToCharArray()
// convert every character at even index to upper
.Select ((character, index) => (index % 2) == 0 ? Char.ToUpper(character) : character)
// back to array in order to create a string
.ToArray());
Console.WriteLine(result);
The output is:
ThEqUiCkBrOwNfOxJuMpSoVeRtHeLaZyDoG
This solution uses the indexed LINQ Select clause in order to access the current index and the value that is currently projected.
A one liner:
new string(myString.Select((c, i) => i % 2 == 0 ? char.ToUpper(c) : c).ToArray())
An extension method:
public static string AltCase(this string s)
{
return new string(s.Select((c, i) => i % 2 == 0 ? char.ToUpper(c) : c).ToArray());
}

Replace consecutive characters with same single character

I was just wondering if there is a simple way of doing this. i.e. Replacing the occurrence of consecutive characters with the same character.
For eg: - if my string is "something likeeeee tttthhiiissss" then my final output should be "something like this".
The string can contain special characters too including space.
Can you guys suggest some simple way for doing this.
This should do it:
var regex = new Regex("(.)\\1+");
var str = "something likeeeee!! tttthhiiissss";
Console.WriteLine(regex.Replace(str, "$1")); // something like! this
The regex will match any character (.) and \\1+ will match whatever was captured in the first group.
string myString = "something likeeeee tttthhiiissss";
char prevChar = '';
StringBuilder sb = new StringBuilder();
foreach (char chr in myString)
{
if (chr != prevChar) {
sb.Append(chr);
prevChar = chr;
}
}
How about:
s = new string(s
.Select((x, i) => new { x, i })
.Where(x => x.i == s.Length - 1 || s[x.i + 1] != x.x)
.Select(x => x.x)
.ToArray());
In english, we are creating a new string based on a char[] array. We construct that char[] array by applying a few LINQ operators:
Select: Capture the index i along with the current character x.
Filter out charaters that are not the same as the subsequent character
Select the character x.x back out of the anonymous type x.
Convert back to a char[] array so we can pass to constructor of string.
Console.WriteLine("Enter any string");
string str1, result="", str = Console.ReadLine();
char [] array= str.ToCharArray();
int i=0;
for (i = 0; i < str.Length;i++ )
{
if ((i != (str.Length - 1)))
{ if (array[i] == array[i + 1])
{
str1 = str.Trim(array[i]);
}
else
{
result += array[i];
}
}
else
{
result += array[i];
}
}
Console.WriteLine(result);
In this code the program ;
will read the string as entered from user
2.Convert the string in char Array using string.ToChar()
The loop will run for each character in string
each character stored in that particular position in array will be compared to the character stored in position one greater than that . And if the characters are found same the character stored in that particular array would be trimmed using .ToTrim()
For last character the loop will show error of index out of bound as it would be the last position value of the array. That's why I used * if ((i != (str.Length - 1)))*
6.The characters left after trimming are stored in result in concatenated form .
word = "something likeeeee tttthhiiissss"
re.sub(r"(.)\1+", r"\1",word)

Categories