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
This is my code:
string textToEncode = File.ReadAllText(#"C:\Users\ASUS\Desktop\szyfrowanie2\TextSample.txt");
textToEncode = textToEncode.ToLower();
char[] distinctLetters = textToEncode.Distinct().ToArray();
var count = textToEncode.Distinct().Count();
Console.WriteLine("Letters used in text: \n\n");
for (int i = 0; i < count; i++)
{
if (Equals(distinctLetters[i]," "))
{
Console.Write("<space>");
}
else
{
Console.Write(" " + distinctLetters[i] + " ");
}
}
I want to read the .txt file, turn it all to lowercases by ToLower(); method, but then when I want to read all the distinct characters from .txt file and then write them on screen, they don't show up. Yet later when I use
for (int i = 0; i < distinctLetters.Length; i++)
{
Console.Write("Swap " + distinctLetters[i] + " with ");
it shows the letter that indeed was changed into a lowercase, but wasn't visible on screen by first for loop. First word in my TextSample.txt file is "With". The first loop only shows
i t h
But as the second loop starts, it asks
Swap w with
and I have no idea why.
Also the if statement in first loop doesn't work, it doesn't detect the space.
I modified your code a bit and apart from "fixing" if statement (as it was never true because of the fact your array contains chars, but was compared to a string (" " is a string, ' ' is a char)) included a new loop which highlights and fixes what turned out to be the main problem (carriage return and new line symbols, which was kindly pointed out by Wim ten Brink in the comments). The string value I used is there only to demonstrate the issue.
string textToEncode = "abc\rdefabdg";
textToEncode = textToEncode.ToLower();
char[] distinctLetters = textToEncode.Distinct().ToArray();
var count = distinctLetters.Length;
Console.WriteLine("Letters used in text (old):");
for (int i = 0; i < count; i++)
{
var letter = distinctLetters[i];
if (Equals(letter, " "))
{
Console.Write("<space>");
}
else
{
Console.Write(distinctLetters[i]);
}
}
Console.WriteLine();
Console.WriteLine("Letters used in text (new):");
for (int i = 0; i < count; i++)
{
var letter = distinctLetters[i];
if (!char.IsLetter(letter))
continue;
Console.Write(distinctLetters[i]);
}
And the output is:
Letters used in text (old):
defg
Letters used in text (new):
abcdefg
I've also modified your code a bit:
string textToEncode = File.ReadAllText(#"C:\Users\ASUS\Desktop\szyfrowanie2\TextSample.txt").ToLower();
char[] distinctLetters = textToEncode.Distinct().ToArray();
var count = distinctLetters.Count();
Console.WriteLine("Letters used in text: \n\n");
for (int i = 0; i < count; i++)
{
if (Equals(distinctLetters[i], ' ')) { Console.Write("<space>"); }
else if (Equals(distinctLetters[i], '\r')) { Console.Write("<cr>"); }
else if (Equals(distinctLetters[i], '\n')) { Console.Write("<lf>"); }
else { Console.Write(" " + distinctLetters[i] + " "); }
}
Just a few minor things. I merged the two first lines, changed " " into ' ' so it now compares characters, changed the counting of characters to use distinctLetters instead of executing the same Distinct() command again and I added two conditions to handle the carriage return and line feed. (I always mix them up, btw.)
This now shows the right result but should also explain why characters went missing! A simple reason, actually. Your text file has a carriage return character, which will send the cursor back to the left. This will cause the first character to be overwritten by a space...
So your code actually prints " w i ..." but then gets the '\r'. It will then print a space, go back to the beginning of the line and writes another space over the ' '! Then the newline will come next, which prints a second space over the 'w', moves to the next line and prints a space again. Then the rest gets printed...
Simple, isn't it? But by capturing these two special characters with the two extra if statements, it is fixed... :-) The '\r' and '\n' characters are often overlooked in console applications, giving unexpected results when they get printed.
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
I need to indent multiple lines of text (in contrast to this question for a single line of text).
Let's say this is my input text:
First line
Second line
Last line
What I need is this result:
First line
Second line
Last line
Notice the indentation in each line.
This is what I have so far:
var textToIndent = #"First line
Second line
Last line.";
var splittedText = textToIndent.Split(new string[] {Environment.NewLine}, StringSplitOptions.None);
var indentAmount = 4;
var indent = new string(' ', indentAmount);
var sb = new StringBuilder();
foreach (var line in splittedText) {
sb.Append(indent);
sb.AppendLine(line);
}
var result = sb.ToString();
Is there a safer/simpler way to do it?
My concern is in the split method, which might be tricky if text from Linux, Mac or Windows is transfered, and new lines might not get splitted correctly in the target machine.
Since you are indenting all the lines, how about doing something like:
var result = indent + textToIndent.Replace("\n", "\n" + indent);
Which should cover both Windows \r\n and Unix \n end of lines.
Just replace your newline with newline + indent:
var indentAmount = 4;
var indent = new string(' ', indentAmount);
textToIndent = indent + textToIndent.Replace(Environment.NewLine, Environment.NewLine + indent);
The following solution may seem long-winded compared to other solutions posted here; but it has a few distinct advantages:
It will preserve line separators / terminators exactly as they are in the input string.
It will not append superfluous indentation characters at the end of the string.
It might run faster, as it uses only very primitive operations (character comparisons and copying; no substring searches, nor regular expressions). (But that's just my expectation; I haven't actually measured.)
static string Indent(this string str, int count = 1, char indentChar = ' ')
{
var indented = new StringBuilder();
var i = 0;
while (i < str.Length)
{
indented.Append(indentChar, count);
var j = str.IndexOf('\n', i + 1);
if (j > i)
{
indented.Append(str, i, j - i + 1);
i = j + 1;
}
else
{
break;
}
}
indented.Append(str, i, str.Length - i);
return indented.ToString();
}
Stakx's answer got me thinking about not appending superfluous indentation characters. And I think is best to avoid those characters not only at the end, but also in the middle and beginning of the string (when that's all that line has).
I used a Regex to replace new lines only if they are not followed by another new line, and another Regex to avoid adding the first indent in case the string begins with a new line:
Regex regexForReplace = new Regex(#"(\n)(?![\r\n])");
Regex regexForFirst = new Regex(#"^([\r\n]|$)");
string Indent(string textToIndent, int indentAmount = 1, char indentChar = ' ')
{
var indent = new string(indentChar, indentAmount);
string firstIndent = regexForFirst.Match(textToIndent).Success ? "" : indent;
return firstIndent + regexForReplace.Replace(textToIndent, #"$1" + indent);
}
I create the Regexs outside the method in order to speed up multiple replacements.
This solution can be tested at: https://ideone.com/9yu5Ih
If you need a string extension that adds a generic indent to a multi line string you can use:
public static string Indent(this string input, string indent)
{
return string.Join(Environment.NewLine, input.Split(Environment.NewLine).Select(item => string.IsNullOrEmpty(item.Trim()) ? item : indent + item));
}
This extension skips empty lines.
This solution is really simple to understand if you know linq and it's more simple to debug and change if you need to adapt it to different scopes.
I have a code in C# and have to print a label with the name of the seller, but i have a problem.
Every line in the label comport 20 letters and i have 2 lines to put this name.
I need to arrange the name of the seller in the 2 lines, without cut words.
For example - Name: JOSE MAURICIO BERTOLOTO MENDES
Line1: JOSE MAURICIO
Line2: BERTOLOTO MENDES
someone know how i do this?
Thanks
EDIT: Based in the answers, i implemente this code:
string[] SellerPrint = Seller.Split(' ');
Line1 = "";
Line2 = "";
foreach (string name in SellerPrint )
{
if (Line1.Length <= 20)
{
if ((Line1 + name).Length <= 20)
Line1 += (Line1.Length == 0) ? name : " " + name;
else
break;
}
}
Line2 = (Seller.Replace(Line1, "").Length <= 20) ? Seller.Replace(Line1+ " ", "") : Seller.Replace(Line1+ " ", "").Remove(20);
Thanks for the help!
You could simply split the string into words using string.Split() and then add to each as long it small enough to add to the line.
I also wouldn't use the character count but use Graphics.MeasureString() instead.
You can split the full name in to it's individual parts.
var names = fullname.Split(' ');
Which will give you a string[]. From there you can do the math by looking at length of each string.
The idea is that you want to append all parts of the name until you will reach or exceed your 20 character limit on the next token. When that happens, append a new line with that token and continue appending until you hit the character limit once again.
Here is a quick example:
public static string FormatName(string name)
{
const int MaxLength = 20;
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
if (name.Length <= MaxLength)
return name;
string[] tokens = name.Split(' ');
if (tokens.Length == 0)
return name; //hyphen the name?
StringBuilder sb = new StringBuilder(name.Length);
int len = 0;
foreach (string token in tokens)
{
if (token.Length + len < MaxLength)
{
sb.Append(token + " ");
len += token.Length;
}
else
{
sb.Append(Environment.NewLine + token + " ");
len = 0;
}
}
return sb.ToString();
}
Note: I left the case open for when a section of the name, without spaces, is longer than 20 characters. Also, this example will continue on to the Nth line, if the name won't fit onto two lines.
Here is the logic.
Use String.split to split the name into an array. Iterate over the strings in the array, concat them into a line, while the line is less than 20 characters. A recursive function would be a good idea! When you are greater than two lines, drop the rest of the names that put it over.
I'm not sure but I think you can use a special character: '\n' (without the quotes)
Its basiclly stands for new line. So for example : JOSE MAURICIO BERTOLOTO MENDES will become JOSE MAURICIO \n BERTOLOTO MENDES.