I am trying to print a string by thermal printer, but the problem is that paper accept only 32 charcters in a line and than break rest text to another line, by this last character always cut into two parts and string is hard to understand.
Example:
string PrintStr = "01-(200),02-(200),03-(200),04-(200),05-(200)";
Current output:
01-(200),02-(200),03-(200),04-(20 # <- 200 is broken into 20 and 0
0),05-(200)
Better output:
01-(200),02-(200),03-(200), # Split on comma, numbers are preserved
04-(200),05-(200)
I also use a Linq mehtod to break line after 32th character but the last character is cutting. I just want after last Comma "," in first 32 characters a new line will be add by that my string will break in readable text. I am sharing my code. Thanks in advance for help..
Input:
var PrintStr = "01-(200),02-(200),03-(200),04-(200),05-(200),06-(200),07-(200),08-(200),09-
(200),10-(200),11-(200),12-(200),13-(200),14-(200),15-
(200),16-(200),17-(200),18-(200),19-(200),20-(200),21-(200),22-(200),23-(200),24-(200),25-(200),26-
(200),27-(200),28-(200),29-(200),30-(200),31-(
200),32-(200),33-(200),34-(200),35-(200),36-(200),37-(200),38-(200),39-(200),40-(200),41-(200),42-
(200),43-(200),44-(200),45-(200),46-(200),47-(200),48-
(200),49-(200),50-(200),51-(200),52-(200),53-(200),54-(200),55-(200),56-(200),57-(200),58-(200),59-
(200),60-(200),61-(200),62-(200),63-(200),64-
(200),65-(200),66-(200),67-(200),A1111-(200)"
Code (my attept):
var AdjustPrintStr = string.Join(Environment.NewLine, PrintStr
.ToLookup(c => k++ / 32)
.Select(e => new String(e.ToArray())));
Output (current, unwanted):
01-(200),02-(200
),03-(200),04-(200),05-(200),06-
(200),07-(200),08-(200),09-(200)
,10-(200),11-(200),12-(200),13-(
200),14-(200),15-(200),16-(200),
17-(200),18-(200),19-(200),20-(2
00),21-(200),22-(200),23-(200),2
4-(200),25-(200),26-(200),27-(20
0),28-(200),29-(200),30-(200),31
-(200),32-(200),33-(200),34-(200
),35-(200),36-(200),37-(200),38-
(200),39-(200),40-(200),41-(200)
,42-(200),43-(200),44-(200),45-(
200),46-(200),47-(200),48-(200),
49-(200),50-(200),51-(200),52-(2
00),53-(200),54-(200),55-(200),5
6-(200),57-(200),58-(200),59-(20
0),60-(200),61-(200),62-(200),63
-(200),64-(200),65-(200),66-(200
Note, that the last "),A1111-(200)" fragment is lost
Well, you have to implement such a routine
(split text at at characters ensuring at most maxWidth characters in each line) manually;
it's not that difficult:
public static IEnumerable<string> MySplit(string text,
int maxWidth, params char[] at) {
if (null == text)
throw new ArgumentNullException(nameof(text));
else if (maxWidth <= 0)
throw new ArgumentOutOfRangeException(nameof(maxWidth));
else if (null == at)
throw new ArgumentNullException(nameof(at));
int startIndex = 0;
int bestIndex = -1;
for (int i = 0; i < text.Length; ++ i) {
if ((i - startIndex) > maxWidth) {
if (bestIndex < 0)
bestIndex = i - 1;
yield return text.Substring(startIndex, bestIndex - startIndex + 1);
startIndex = bestIndex += 1;
bestIndex = -1;
}
if (at.Contains(text[i]))
bestIndex = i;
}
yield return text.Substring(startIndex);
}
Now, let's print out the source string:
string PrintStr = #"01-(200),02-(200),03-(200),04-(200),05-(200),06-(200),07-(200),08-(200),09-
(200),10-(200),11-(200),12-(200),13-(200),14-(200),15-
(200),16-(200),17-(200),18-(200),19-(200),20-(200),21-(200),22-(200),23-(200),24-(200),25-(200),26-
(200),27-(200),28-(200),29-(200),30-(200),31-(
200),32-(200),33-(200),34-(200),35-(200),36-(200),37-(200),38-(200),39-(200),40-(200),41-(200),42-
(200),43-(200),44-(200),45-(200),46-(200),47-(200),48-
(200),49-(200),50-(200),51-(200),52-(200),53-(200),54-(200),55-(200),56-(200),57-(200),58-(200),59-
(200),60-(200),61-(200),62-(200),63-(200),64-
(200),65-(200),66-(200),67-(200),A1111-(200)";
It seems, you should preprocess it in order to remove all new lines, tabulations, spaces etc. and
only then split it:
// Let's remove all white spaces (new lines, tabulations, spaces)
PrintStr = Regex.Replace(PrintStr, #"\s+", "");
// split on comma ',' while ensuring each lines <= 32 characters
var result = string.Join(Environment.NewLine, MySplit(PrintStr, 32, ','));
Console.Write(result);
Outcome:
01-(200),02-(200),03-(200),
04-(200),05-(200),06-(200),
07-(200),08-(200),09-(200),
10-(200),11-(200),12-(200),
13-(200),14-(200),15-(200),
16-(200),17-(200),18-(200),
19-(200),20-(200),21-(200),
22-(200),23-(200),24-(200),
25-(200),26-(200),27-(200),
28-(200),29-(200),30-(200),
31-(200),32-(200),33-(200),
34-(200),35-(200),36-(200),
37-(200),38-(200),39-(200),
40-(200),41-(200),42-(200),
43-(200),44-(200),45-(200),
46-(200),47-(200),48-(200),
49-(200),50-(200),51-(200),
52-(200),53-(200),54-(200),
55-(200),56-(200),57-(200),
58-(200),59-(200),60-(200),
61-(200),62-(200),63-(200),
64-(200),65-(200),66-(200),
67-(200),A1111-(200)
Hope, it's the very picture you want to see after printing
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;
}
I've got a project I'm working on in C#. I've got two char array's. One is a sentence and one is a word. I've got to iterate through the sentence array until I find a word that matches the word that was turned into an word array what I'm wondering is once I find the word how do I iterate backwards through the sentence array at the point I found the word back through the same length as the word array?
Code :
String wordString = "(Four)";
String sentenceString = "Maybe the fowl of Uruguay repeaters (Four) will be found";
char[] wordArray = wordString.ToCharArray();
List<String> words = sentenceString.Split(' ').ToList<string>();
//This would be the part where I iterate through sentence
foreach (string sentence in sentArray)
{
//Here I would need to find where the string of (Four) and trim it and see if it equals the wordString.
if (sentence.Contains(wordString)
{
//At this point I would need to go back the length of wordString which happens to be four places but I'm not sure how to do this. And for each word I go back in the sentence I need to capture that in another string array.
}
I don't know if I'm being clear enough on this but if I'm not please feel free to ask.. Thank you in advanced. Also what this should return is "fowl of Uruguay repeaters". So basically the use case is for the number of letters in the parenthesis the logic should return the same number of words before the word in parenthesis.
our are you. I have few question concerned to this exercise.
If the Word (four) was in beginning it should not return? or return all string?
As the length of four is equal to 4 imagine if that word appear as the second word on sentence what it should return just the first word or return 4 words even including the (four) word.?
My solution is the laziest one I just see your question and decide to help.
My solution assumes it return all the word before the (four) if the length is bigger than the word before the (four) word.
My solution return empty string if the word (four) is in the beginning.
My solution return Length of (four) (4) words before (four) word.
ONCE AGAIN IT IS NOT MY BEST APPROACH.
I see the code bellow:
string wordString = "(Four)";
string sentenceString = "Maybe the fowl of Uruguay repeaters (Four) will be found";
//Additionally you can add splitoption to remove the empty word on split function bellow
//Just in case there are more space in sentence.
string[] splitedword = sentenceString.Split(' ');
int tempBackposition = 0;
int finalposition = 0;
for (int i = 0; i < splitedword.Length; i++)
{
if (splitedword[i].Contains(wordString))
{
finalposition = i;
break;
}
}
tempBackposition = finalposition - wordString.Replace("(","").Replace(")","").Length;
string output = "";
tempBackposition= tempBackposition<0?0:tempBackposition;
for (int i = tempBackposition; i < finalposition; i++)
{
output += splitedword[i] + " ";
}
Console.WriteLine(output);
Console.ReadLine();
If it's not what you want can you answer my questions on top? or help me to understand were it's wrong
int i ;
string outputString = (i=sentenceString.IndexOf(wordString))<0 ?
sentenceString : sentenceString.Substring(0,i) ;
var wordString = "(Four)";
int wordStringInt = 4; // Just do switch case to convert your string to int
var sentenceString = "Maybe the fowl of Uruguay repeaters (Four) will be found";
var sentenceStringArray = sentenceString.Split(' ').ToList();
int wordStringIndexInArray = sentenceStringArray.IndexOf(wordString) - 1;
var stringOutPut = "";
if (wordStringIndexInArray > 0 && wordStringIndexInArray > wordStringInt)
{
stringOutPut = "";
while (wordStringInt > 0)
{
stringOutPut = sentenceStringArray[wordStringInt] + " " + stringOutPut;
wordStringInt--;
}
}
What you are matching is kind of complex, so for a more general solution you could use regular expressions.
First we declare what we are searching for:
string word = "(Four)";
string sentence = "Maybe the fowl of Uruguay repeaters (Four) will be found";
We will then search for the words in this string using regular expressions. Since we don't want to match whitespace, and we need to know where each match actually starts and we need to know the word inside the parenthesis we tell it that we optionally want opening and ending parenthesis, but we also want the contents of those as a match:
var words = Regex.Matches(sentence, #"[\p{Ps}]*(?<Content>[\w]+)[\p{Pe}]*").Cast<Match>().ToList();
[\p{Ps}] means we want opening punctuation ([{ etc. while the * indicates zero or more.
Followed is a sub-capture called Content (specified by ?<Content>) with one or more word characters.
At the end we specify that we want zero or more ending punctuation.
We then need to find the word in the list of matches:
var item = words.Single(x => x.Value == word);
Then we need to find this item's index:
int index = words.IndexOf(item);
At this point we just need to know the length of the contents:
var length = item.Groups["Content"].Length;
This length we use to go back in the string 4 words
var start = words.Skip(index - length).First();
And now we have everything we need:
var result = sentence.Substring(start.Index, item.Index - start.Index);
Result should contain fowl of Uruguay repeaters.
edit: It may be a lot simpler to just figure out the count from the word rather than from the content. In that case the complete code should be the following:
string word = "(Four)";
string sentence = "Maybe the fowl of Uruguay repeaters (Four) will be found";
var wordMatch = Regex.Match(word, #"[\p{Ps}]*(?<Content>[\w]+)[\p{Pe}]*");
var length = wordMatch.Groups["Content"].Length;
var words = Regex.Matches(sentence, #"\S+").Cast<Match>().ToList();
var item = words.Single(x => x.Value == word);
int index = words.IndexOf(item);
var start = words.Skip(index - length).First();
var result = sentence.Substring(start.Index, item.Index - start.Index);
\S+ in this case means "match one or more non-whitespace character".
You should try something like the following, which uses Array.Copy after it finds the number word. You will still have to implement the ConvertToNum function correctly (it is hardcoded in for now), but this should be a quick and easy solution.
string[] GetWords()
{
string sentenceString = "Maybe the fowl of Uruguay repeaters (Four) will be found";
string[] words = sentenceString.Split();
int num = 0;
int i; // scope of i should remain outside the for loop
for (i = 0; i < words.Length; i++)
{
string word = words[i];
if (word.StartsWith("(") && word.EndsWith(")"))
{
num = ConvertToNum(word.Substring(1, word.Length - 1));
// converted the number word we found, so we break
break;
}
}
if (num == 0)
{
// no number word was found in the string - return empty array
return new string[0];
}
// do some extra checking if number word exceeds number of previous words
int startIndex = i - num;
// if it does - just start from index 0
startIndex = startIndex < 0 ? 0 : startIndex;
int length = i - startIndex;
string[] output = new string[length];
Array.Copy(words, startIndex, output, 0, length);
return output;
}
// Convert the number word to an integer
int ConvertToNum(string numberStr)
{
return 4; // you should implement this method correctly
}
See - Convert words (string) to Int, for help implementing the ConvertToNum solution. Obviously it could be simplified depending on the range of numbers you expect to deal with.
Here is my solution, im not using regex at all, for the sake of easy understanding:
static void Main() {
var wordString = "(Four)";
int wordStringLength = wordString.Replace("(","").Replace(")","").Length;
//4, because i'm assuming '(' and ')' doesn't count.
var sentenceString = "Maybe the fowl of Uruguay repeaters (Four) will be found";
//Transform into a list of words, ToList() to future use of IndexOf Method
var sentenceStringWords = sentenceString.Split(' ').ToList();
//Find the index of the word in the list of words
int wordIndex = sentenceStringWords.IndexOf(wordString);
//Get a subrange from the original list of words, going back x Times the legnth of word (in this case 4),
var wordsToConcat = sentenceStringWords.GetRange(wordIndex-wordStringLength, wordStringLength);
//Finally concat the output;
var outPut = string.Join(" ", wordsToConcat);
//Output: fowl of Uruguay repeaters
}
I have a solution for you:
string wordToMatch = "(Four)";
string sentence = "Maybe the fowl of Uruguay repeaters (Four) will be found";
if (sentence.Contains(wordToMatch))
{
int length = wordToMatch.Trim(new[] { '(', ')' }).Length;
int indexOfMatchedWord = sentence.IndexOf(wordToMatch);
string subString1 = sentence.Substring(0, indexOfMatchedWord);
string[] words = subString1.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
var reversed = words.Reverse().Take(length);
string result = string.Join(" ", reversed.Reverse());
Console.WriteLine(result);
Console.ReadLine();
}
Likely this can be improved regardng performance, but I have a feeling you don't care about that. Make sure you are using 'System.Linq'
I assumed empty returns when input is incomplete, feel free to correct me on that. Wasn't 100% clear in your post how this should be handled.
private string getPartialSentence(string sentence, string word)
{
if (string.IsNullOrEmpty(sentence) || string.IsNullOrEmpty(word))
return string.Empty;
int locationInSentence = sentence.IndexOf(word, StringComparison.Ordinal);
if (locationInSentence == -1)
return string.Empty;
string partialSentence = sentence.Substring(0, locationInSentence);
string[] words = partialSentence.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
int nbWordsRequired = word.Replace("(", "").Replace(")", "").Length;
if (words.Count() >= nbWordsRequired)
return String.Join(" ", words.Skip(words.Count() - nbWordsRequired));
return String.Join(" ", words);
}
I went with using an enumeration and associated dictionary to pair the "(Four)" type strings with their integer values. You could just as easily (and maybe easier) go with a switch statement using
case "(Four)": { currentNumber = 4; };
I feel like the enum allows a little more flexibility though.
public enum NumberVerb
{
one = 1,
two = 2,
three = 3,
four = 4,
five = 5,
six = 6,
seven = 7,
eight = 8,
nine = 9,
ten = 10,
};
public static Dictionary<string, NumberVerb> m_Dictionary
{
get
{
Dictionary<string, NumberVerb> temp = new Dictionary<string, NumberVerb>();
temp.Add("(one)", NumberVerb.one);
temp.Add("(two)", NumberVerb.two);
temp.Add("(three)", NumberVerb.three);
temp.Add("(four)", NumberVerb.four);
temp.Add("(five)", NumberVerb.five);
temp.Add("(six)", NumberVerb.six);
temp.Add("(seven)", NumberVerb.seven);
temp.Add("(eight)", NumberVerb.eight);
temp.Add("(nine)", NumberVerb.nine);
temp.Add("(ten)", NumberVerb.ten);
return temp;
}
}
static void Main(string[] args)
{
string resultPhrase = "";
// Get the sentance that will be searched.
Console.WriteLine("Please enter the starting sentance:");
Console.WriteLine("(don't forget your keyword: ie '(Four)')");
string sentance = Console.ReadLine();
// Get the search word.
Console.WriteLine("Please enter the search keyword:");
string keyword = Console.ReadLine();
// Set the associated number of words to backwards-iterate.
int currentNumber = -1;
try
{
currentNumber = (int)m_Dictionary[keyword.ToLower()];
}
catch(KeyNotFoundException ex)
{
Console.WriteLine("The provided keyword was not found in the dictionary.");
}
// Search the sentance string for the keyword, and get the starting index.
Console.WriteLine("Searching for phrase...");
string[] words = sentance.Split(' ');
int searchResultIndex = -1;
for (int i = 0; (searchResultIndex == -1 && i < words.Length); i++)
{
if (words[i].Equals(keyword))
{
searchResultIndex = i;
}
}
// Handle the search results.
if (searchResultIndex == -1)
{
resultPhrase = "The keyword was not found.";
}
else if (searchResultIndex < currentNumber)
{
// Check the array boundaries with the given indexes.
resultPhrase = "Error: Out of bounds!";
}
else
{
// Get the preceding words.
for (int i = 0; i < currentNumber; i++)
{
resultPhrase = string.Format(" {0}{1}", words[searchResultIndex - 1 - i], resultPhrase);
}
}
// Display the preceding words.
Console.WriteLine(resultPhrase.Trim());
// Exit.
Console.ReadLine();
}