Почему функция Console.WriteLine() пропускает некоторые символы в строке?

У меня есть строка, объявленная как:

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

И все же, когда я пишу Console.WriteLine(text);,

вывод:

this is line 2E

Почему такое поведение происходит? Или это потому, что я тупой и упускаю что-то очевидное?

Почему не печатает:

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

ИЗМЕНИТЬ

Обратите внимание: это НЕ вопрос о том, как добавить возврат каретки.


person jbutler483    schedule 28.11.2014    source источник
comment
Вы ищете возврат каретки? (символ)(10)?   -  person Drew Kennedy    schedule 28.11.2014
comment
Похоже, проблема связана только с функцией Console.WriteLine(). Наблюдали ли вы такое поведение при каких-либо других строковых операциях, например, при попытке отобразить строку через TextBox или TextBlock? С Уважением   -  person Alexander Bell    schedule 28.11.2014
comment
Я печатаю на матричном принтере   -  person jbutler483    schedule 28.11.2014
comment
Так как мы установили, что здесь задействован принтер. Вы передаете вывод своей консольной программы на принтер или просто выгружаете на консоль для целей отладки?   -  person Lasse V. Karlsen    schedule 28.11.2014
comment
Учитывая, что принтер и консольный вывод ведут себя по-разному для одного и того же вывода, нужно либо сменить принтер, сменить консоль, либо отправить разные последовательности на консоль и на принтер   -  person Peter M    schedule 28.11.2014
comment
только отладка (пока), но так как я все еще не могу работать с командами принтера, я не могу быть уверен   -  person jbutler483    schedule 28.11.2014
comment
Итак... Мы установили, что у вас есть проблема с выводом на стандартную консоль с выводом, который должен быть таким, чтобы принтер работал, за исключением того, что вы еще не проверяли, как это ведет себя или работает на принтере. Знаете ли вы наверняка, что у вас действительно есть проблема?   -  person Lasse V. Karlsen    schedule 28.11.2014
comment
Опять же, чтобы повторить это. Так ведет себя стандартный вывод. Если вам не нравится вывод, измените текст, который вы записываете в него. Если вы не можете, потому что вы делаете это только в целях отладки, а текст должен быть таким для принтера, прекратите тестирование со стандартной консолью, протестируйте на принтере.   -  person Lasse V. Karlsen    schedule 28.11.2014
comment
@LasseV.Karlsen: Да, у меня определенно есть проблемы.   -  person jbutler483    schedule 28.11.2014
comment
Откуда вы знаете, можете ли вы уточнить проблемы, которые у вас есть на самом деле, пока все, что мы знаем, это то, что проблема, которая у вас есть со стандартной консолью, не является реальной проблемой, которую нужно решить, или, по крайней мере, вы знаете решение для это, измените вывод. В чем есть проблема с принтером? На принтере так же себя ведет?   -  person Lasse V. Karlsen    schedule 28.11.2014
comment
@LasseV.Karlsen: у меня уже есть еще один вопрос по этому поводу это было более если я не вижу команду, работающую на консоли, как она должна работать на принтере   -  person jbutler483    schedule 28.11.2014
comment
Хорошо, тогда позвольте мне объяснить это. Принтер и консоль могут работать по-разному. Единственный способ узнать наверняка — протестировать реальное устройство, принтер. Это не проблема Console.WriteLine и не проблема с реальными персонажами, это проблема стандартного поведения консоли. Принтер может вести себя так же, а может и не так, поведение консоли на это не влияет.   -  person Lasse V. Karlsen    schedule 28.11.2014
comment
Ваша программа просто передала все эти символы стандартной консоли и попросила ее показать их, она вела себя так в отношении символов новой строки. Принтер может вести себя совершенно иначе. Фактически, старые матричные принтеры использовали один символ, чтобы просто переместить головку вниз на одну строку и продолжить движение по оси X, а другой символ — для перемещения в начало строки, поэтому вам нужны были оба, чтобы получить то, что вы хотели. хочу. Вы поймете это, только если проверите на реальном принтере.   -  person Lasse V. Karlsen    schedule 28.11.2014
comment
Что касается вашего другого вопроса, где вы упоминаете OKI Microline 5520. Я только что нашел manuals365.com/swf/oki/552xugb2_tcm3-46086.html?page=74 Это означает, что вам нужен Char 10, а не Char 13.   -  person Peter M    schedule 28.11.2014
comment
@PeterM: Спасибо за эту ссылку. Я считаю, что это могло бы пригодиться.   -  person jbutler483    schedule 28.11.2014
comment
Что меня заинтриговало, так это буква Е в конце, возникшая из ниоткуда.   -  person Nicolas Barbulesco    schedule 29.11.2014
comment
@NicolasBarbulesco Осталось напечатать первую строку и не покрыть ее полностью второй. См. ответы ниже.   -  person Daniel Fischer    schedule 29.11.2014


Ответы (7)


(char)13 – это возврат каретки (к левому краю текущей строки)

THIS IS LINE ONE \r this is line 2"

Интерпретируется как:

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

person Alex K.    schedule 28.11.2014
comment
Действительно хорошее объяснение! - person mybirthname; 28.11.2014
comment
это правильно, нет проблем, когда строки имеют одинаковую длину, например. string text = "THIS IS LINE ONE " + (Char)(13) + " THIS IS LINE TWO"; - person globetrotter; 28.11.2014
comment
Что значит без проблем? Является ли проблема в том, что в первой строке остались символы, или в том, что курсор не перемещается во вторую строку (что, по-видимому, указывает OP) - person Lasse V. Karlsen; 28.11.2014
comment
@LasseV.Karlsen Алекс К. хорошо объяснил это. Он возвращается к началу строки 1 и печатает строку 2 поверх строки 1. Поскольку строка 1 длиннее, возникают накладные расходы, поэтому в конце строки появляется дополнительный символ «E». Для новой строки вы должны сделать (char)10 - person globetrotter; 28.11.2014
comment
Да, и ОП спросил, как заставить (char)13 перейти на следующую строку. Таким образом, проблема OP никогда не заключалась в оставшихся символах, а в том, почему он не перешел на вторую строку вместо перезаписи. Так что да, ответ хорошо объясняет, почему вывод выглядит именно так, но для OP все еще есть проблема. Хотя я думаю, что ОП просто придется смириться с тем, что он не получит то, что хочет. - person Lasse V. Karlsen; 28.11.2014
comment
@ LasseV.Karlsen Я понимаю, о чем вы говорите, но (char)13 не должен переходить на следующую строку. Это CR, это будет CRLF - person globetrotter; 28.11.2014
comment
Все это зависело от того факта, что ОП сказал, что его принтер вел себя так. Как оказалось, это не так, поэтому я подозреваю, что вся эта страница текста спорна и довольно бесполезна. - person Lasse V. Karlsen; 28.11.2014

Вот как ведет себя стандартный вывод на консоли.

  • "\n" ((Char)10) переместит курсор в начало следующей строки
  • "\r" ((Char)13) переместит курсор в начало текущей строки

Таким образом, в результате первая строка перезаписывается второй строкой, оставляя только дополнительные символы, которые вторая строка не может перезаписать.

Поскольку вы пояснили, что строка/символы должны быть такими, чтобы получить желаемое поведение, когда этот текст в конечном итоге отправляется туда, куда вы на самом деле хотите его отправить, то есть на матричный принтер, тогда вам нужно проверить с самим принтером.

Описанное выше поведение локализовано для стандартной консоли. Если вы выводите те же символы на «стандартный вывод», но перенаправляете их на принтер, важным является определение принтером того, как обращаться с этими символами, и это может отличаться от стандартного приставка.

Таким образом, поведение, которое вы видите на стандартной консоли, — это просто поведение стандартной консоли. Вам нужно на самом деле протестировать принтер, чтобы увидеть, как он себя ведет.

person Lasse V. Karlsen    schedule 28.11.2014

Если вы хотите такое поведение:

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

Вам нужен этот код:

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

        Console.WriteLine(text);

Возврат каретки ((Char) 13) — это управляющий символ или механизм, используемый для сброса положения устройства в начало строки текста, из-за которого вы испытываете такое поведение. Как я уже сказал, вам нужно (char) 13 для вашего случая.

person mybirthname    schedule 28.11.2014
comment
это на самом деле правильно, но мне нужно, чтобы это был char(13) для принтера (поскольку это то, что он ожидает увидеть). - person jbutler483; 28.11.2014
comment
@ jbutler483 Тогда создайте свой собственный метод WriteLine, который заменяет 13 на 10...? - person Sebastian Negraszus; 28.11.2014

«Возврат каретки, иногда называемый возвратом картриджа и часто сокращаемый до CR или возврата, представляет собой управляющий символ или механизм, используемый для сброса положения устройства на начало строки текста». (источник)

CR никогда не изменяет строку, на самом деле он возвращается к началу "THIS IS LINE ONE " и печатает " this is line 2" поверх него, поэтому вы видите дополнительное E в конце предложения, поскольку первая строка длиннее на один символ. Это становится яснее, если вы удалите два пробела из двух строк (последний символ первой строки и первый символ второй строки), где вывод становится "this is line 2NE".

Из того же источника:

«Он дает команду принтеру или другой системе вывода, такой как дисплей, переместить позицию курсора в первую позицию в той же строке».

Вам нужно найти не CR, а комбинацию CR и LF (перевод строки): CRLF

person trashr0x    schedule 28.11.2014

(Char)13 – это возврат каретки, а (Char)10 – перевод строки. Как уже говорили другие, это означает, что (Char)13 вернется к началу строки, на которой вы находитесь, так что к тому времени, когда вы напишете (более короткую) строку 2, она будет записана поверх первого раздела строки - таким образом оставшаяся "Е".

Если вы попробуете сделать это с более короткой второй строкой, вы увидите, как это происходит:

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

дает вывод:

"test IS LINE ONE"

Следовательно, для решения вашей проблемы правильным кодом будет:

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

который выводит:

THIS IS LINE ONE
this is line 2

Редактировать:

Первоначально, поскольку вы сказали, что ваш принтер требует, чтобы он был (Char) 13, я предложил попробовать оба (Char)10 + (Char)13 (или наоборот) для достижения аналогичного эффекта. Тем не менее, благодаря чрезвычайно полезным комментариям Питера М., похоже, что марка принтера, который вы используете, на самом деле требует только (Char)10 - согласно руководстве, (Char)10 произведет перевод строки и возврат каретки, что вам и нужно.

person Luna    schedule 28.11.2014
comment
Команды матричного принтера могут быть black art и могут быть очень специфичными для производителя, поэтому я бы не стал объявлять какое-либо решение для принтера, пока вы не узнаете точную марку и модель - и не имеете на своем столе такой, с которым вы протестировали код - и только если вы собираетесь развернуть именно этот принтер. :-) - person Peter M; 28.11.2014
comment
Это справедливое замечание - я отредактировал свой ответ, чтобы предложить его как нечто, что можно было бы попробовать, а не как полное решение. Если это делает его неуместным ответом в случае с ОП, хотя он решает проблему на моем компьютере, я могу удалить его. :-) - person Luna; 28.11.2014
comment
ОП показал, что у него есть еще один вопрос, в котором упоминается задействованный принтер. Я погуглил команды и нашел manuals365.com/swf/oki/ 552xugb2_tcm3-46086.html?page=74 Не стесняйтесь включать это в свой ответ! - person Peter M; 28.11.2014
comment
И, судя по тому, что я прочитал в этой ссылке, он все равно хочет Char 10! - person Peter M; 28.11.2014
comment
@PeterM: Хотя команды точечной матрицы различаются у разных производителей, по крайней мере, исторически я находил их относительно простыми. Я ожидаю, что принтеры, способные накладывать поверх, обычно будут рассматривать CR как команду для наложения того, что следует, начиная с начала той же строки; только устройства, которые используют один и тот же двигатель для привода каретки и подачи бумаги, не смогут справиться с этим. - person supercat; 29.11.2014

Вывод не такой, каким кажется. Ваша терминальная программа скрывает от вас некоторые символы байтов, записанных в стандартный вывод, потому что он интерпретирует наличие возврата каретки как команду текстового макета (то есть вернуться налево). Шестнадцатеричный дамп может подтвердить правильность выходных данных, показывая сами байты выходных данных.

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);
   }   
}

Скомпилируйте и запустите:

$ 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
person Nope    schedule 28.11.2014

Используйте string.Concat() для объединения

string text = String.Concat(...)

и попробуй напечатать это

person Anton Kozlovsky    schedule 28.11.2014
comment
Это не меняет того факта, что напечатанный вывод неверен. - person Arturo Torres Sánchez; 29.11.2014
comment
Символ + в C# приводит к вызову String.Concat (за исключением таких случаев, как этот, когда конкатенация может выполняться во время компиляции) - person Ben Voigt; 04.12.2014