Why does Console.WriteLine() function miss some characters within a string?
Asked Answered
N

7

22

I have a string, declared as:

 string text = "THIS IS LINE ONE "+(Char)(13)+" this is line 2";

And yet, When I write Console.WriteLine(text);,

the output is:

this is line 2E

Why is this behaviour happening? Or is it because I'm being stupid and missing something obvious?

Why does it not print:

THIS IS LINE ONE [CR] //where the CR is a non printed character 
this is line 2

EDIT

Please note: this is NOT a 'how do I add a carriage return' question.

Nikaniki answered 28/11, 2014 at 15:46 Comment(17)
Are you looking for a carriage return? (Char)(10)?Paredes
It seems like the issue is specific just to Console.WriteLine() function. Did you observe such behavior in any other string operations, for example, trying to display the string via TextBox or TextBlock? RegardsCerotype
I'm printing to a dot matrix printerNikaniki
Since we've now established that there is a printer involved. Are you piping the output of your console program to the printer, or are you simply dumping to the console for debugging purposes?Banebrudge
Given that the printer and the console output behave differently for the same output, you need to either change the printer, change the console or send different sequences to the console and the printerSyphon
debugging only (so far), but since i'm still unsuccessful with the printer commands, I can't be certainNikaniki
So... We've established that you have a problem with the output on the standard console with output that has to be like this for the printer to work, except that you have not yet tested how this behaves or works on the printer. Do you know for certain that you actually have a problem?Banebrudge
Again, to iterate this. This is how the standard output behaves. If you don't like the output, change the text you write to it. If you can't because you're only doing this for debugging purposes and the text has to be like this for the printer, stop testing with the standard console, test with the printer.Banebrudge
@LasseV.Karlsen: Yes, I definitely have issues.Nikaniki
How do you know, can you elaborate on the issues you actually have, so far all we know is that the issue you have with standard console is not a real issue that needs to be solved, or at the very least you know the solution to it, change the output. What is the issue with the printer? Does it behave the same way on the printer?Banebrudge
@LasseV.Karlsen: I've already got another question for that it was more "if i can't see the command working on the console, how is it meant to work on the printer"Nikaniki
Ok, let me spell it out then. The printer and the console may behave differently. The only way to know for sure is to test with the actual device, the printer. This is not a problem with Console.WriteLine, and not a problem with the actual characters, it is a "problem" with the standard console behavior. The printer may or may not behave the same way, the behavior of the console has no impact on this.Banebrudge
Your program just gave all those characters to the standard console and asked it to show them, it behaved like that in regards to newline characters. The printer may behave completely different. In fact, old dot matrix printers used one character to just move the head down one line and keep going where it was X-wise, and the other character to move to the start of the line, as such you needed both to get what you want. You will only figure this out if you test with the actual printer.Banebrudge
As per your other question where you mention an OKI Microline 5520.. I just found manuals365.com/swf/oki/552xugb2_tcm3-46086.html?page=74 Which implies that you want Char 10 and not Char 13.Syphon
@PeterM: Thank you for that Link. I believe that could come in quite handy.Nikaniki
What intrigues me is the "E" at the end, coming from nowhere.Returnable
@NicolasBarbulesco It's left over from printing the first line and not covering that entirely with the second. See answers below.Smashup
S
58

(char)13 is a carriage return (To the left margin on the current line)

THIS IS LINE ONE \r this is line 2"

Is interpreted as:

Print THIS IS LINE ONE
then *return* and print this is line 2
The overlap is: E
So you see: this is line 2E

Semipermeable answered 28/11, 2014 at 16:6 Comment(6)
this is correct, there's no issue when strings are of equal length, e.g. string text = "THIS IS LINE ONE " + (Char)(13) + " THIS IS LINE TWO";Delenadeleon
What do you mean no issue? Is the issue that there are leftover characters from the first line, or is it that the cursor doesn't move to the second line (which is what the OP seems to indicate)Banebrudge
@LasseV.Karlsen Alex K. explained this nicely. It returns to the beginning of line 1 and prints line 2 on top of line 1. Because line 1 is longer, there's an overhead, hence the extra 'E' char at the end of the line. For a new line you would do (char)10Delenadeleon
Yes, and the OP asked how to get (char)13 to move to the next line. The issue for the OP was thus never about the leftover characters, it was why it didn't move down to the second line instead of overwriting. So yes, the answer explains nicely why the output looks that way, but for the OP there is still an issue. Though the OP will just have to settle for not getting what he wants I think.Banebrudge
@LasseV.Karlsen I understand what you're saying but (char)13 is not supposed to move to the next line. This is CR, that would be CRLFDelenadeleon
All this hinged on the fact that the OP said his printer behaved like this. As it turns out, it doesn't so I suspect this whole page of text is moot and pretty useless.Banebrudge
B
20

This is how standard output on the console behaves.

  • "\n" ((Char)10) will move the caret to the start of the next line
  • "\r" ((Char)13) will move the caret to the start of the current line

As such, the results are thus the first line overwritten by the second line, leaving only the extra characters that the second line couldn't overwrite.

Since you've clarified that the string/characters have to be like that to get the behavior you want when this text is ultimately sent to the place you actually want to send it to, a dot matrix printer, then you need to test with the printer itself.

The above behavior is localized to the standard console. If you output the same characters to "standard output" but have redirected this to a printer, it is the printer's definition on how to deal with these characters that is important, and this may be different from the standard console.

As such, the behavior you see on the standard console is just that, the behavior of the standard console. You need to actually test with the printer to see how this behaves.

Banebrudge answered 28/11, 2014 at 16:5 Comment(0)
C
5

If you want this behavior:

THIS IS LINE ONE [CR] //where the CR is a non printed character 
this is line 2

You need this code:

        char a = (char)10;
        string text = "THIS IS LINE ONE" + a + "this is line 2"

        Console.WriteLine(text);

A carriage return((Char) 13) is a control character or mechanism used to reset a device's position to the beginning of a line of text, because of that you experience this behavior. Like I said you need (char)13 for your case.

Chequer answered 28/11, 2014 at 16:3 Comment(2)
this is in fact correct, but I need it to be a char(13) for the printer (since that's what it's expecting to see).Nikaniki
@Nikaniki Then create your own WriteLine method that replaces 13 by 10...?Nineteen
A
4

"A carriage return, sometimes known as a cartridge return and often shortened to CR, or return, is a control character or mechanism used to reset a device's position to the beginning of a line of text." (source)

CR never changes a line, in fact it returns all the way to the beginning of "THIS IS LINE ONE " and prints " this is line 2" on top of it, hence why you see the additional E at the end of the sentence, as line one is one character longer. This is made clearer if you remove the two spaces from the two strings (last character of first string and first character of second string) where the output then becomes "this is line 2NE".

From the same source:

"It commands a printer, or other output system such as a display, to move the position of the cursor to the first position on the same line."

What you're looking for is not CR, but a combination of CR and LF (line feed): CRLF

Amberjack answered 28/11, 2014 at 16:35 Comment(0)
M
2

(Char)13 is a carriage return, while (Char)10 is a line feed. As others have said, this means that (Char)13 will return to the beginning of the line you are on, so that by the time you have written the (shorter) line 2, it will be written over the first section of the string - thus the remaining "E".

If you try it with a shorter second string, you can see this happening:

string text = "THIS IS LINE ONE " + (Char)13 +"test";
Console.WriteLine(text);

gives output:

"test IS LINE ONE"

Therefore, to solve your problem, the correct code will be:

string text = "THIS IS LINE ONE " + (Char)10 +"test";
Console.WriteLine(text);

which outputs:

THIS IS LINE ONE
this is line 2

Edit:

Originally, since you said your printer requires it to be a (Char)13, I suggested trying both (Char)10 + (Char)13 (or vice versa) to achieve a similar effect. However, thanks to Peter M's exceedingly helpful comments, it appears the brand of printer you are using does in fact require just a (Char)10 - according to the manual, (Char)10 will produce a line feed and a carriage return, which is what you require.

Marni answered 28/11, 2014 at 16:10 Comment(5)
Dot matrix printer commands can be a black art and can be very very manufacturer specific, so I wouldn't proclaim any solution for a printer until you knew the exact make and model - and had one on your desk that you had tested the code with - and only if you were going to deploy that exact printer. :-)Syphon
That's a fair point - I've edited my answer to suggest it as something that could be tried rather than as a complete solution. If this makes it an irrelevant answer in the OP's case, although it does solve the issue on my computer, I can delete it. :-)Marni
The OP revealed that he another question which mentions the printer involved. I googled the commands and found manuals365.com/swf/oki/552xugb2_tcm3-46086.html?page=74 Feel free to incorporate that in you answer!Syphon
And from my reading of that reference he wants Char 10 anyway!Syphon
@PeterM: While dot-matrix commands vary between manufacturers, at least historically I've found them relatively straightforward. I would expect that printers which are capable of overprinting would generally regard "CR" as a command to overprint what follows starting at the beginning of the same line; only devices which use the same motor to drive the carriage and paper feed would be unable to manage that.Exserviceman
S
2

The output isn't what it seems. Your terminal program is hiding you some characters of the bytes written in stdout because he interprets the carriage return presence as a text layout command (which is, go back to left). A hexdump can confirm that the output is correct by showing the very bytes of output.

using System;
public class Hello1 {
  public static void Main()  {
     string text = "THIS IS LINE ONE "+(Char)(13)+" this is line 2";
     System.Console.WriteLine(text);
   }   
}

Compile and run :

$ gmcs a.cs
$ ./a.exe
 this is line 2E
$ ./a.exe | hexdump -C
00000000  54 48 49 53 20 49 53 20  4c 49 4e 45 20 4f 4e 45  |THIS IS LINE ONE|
00000010  20 0d 20 74 68 69 73 20  69 73 20 6c 69 6e 65 20  | . this is line |
00000020  32 0a                                             |2.|
00000022
Stovall answered 28/11, 2014 at 21:5 Comment(0)
S
-2

Use string.Concat() to concatenate

string text = String.Concat(...)

and try to print this

Stenopetalous answered 28/11, 2014 at 15:56 Comment(2)
This doesn't change the fact that the printed output is incorrect.Rident
The + symbol in C# results in a call to String.Concat (except in cases such as this, where concatenation can be performed at compile time)Hath

© 2022 - 2024 — McMap. All rights reserved.