Ошибка строка шаблона содержит непарные кавычки

Программирование в 1С для всех

В этой статье изучим один из примитивных типов платформы 1С 8.3 – тип Строка. Научимся выводить строки, соединять, переносить, объединять с другими примитивными типами, а также узнаем, как работают строки в серверном и клиентском контексте, и научимся работать со строками на управляемой форме и в реквизитах объектов.

Строка в 1С

Строка это примитивный тип. Создать переменную типа строка достаточно просто. Нужно переменной присвоить какое-то значение в кавычках.

Метод Сообщить в 1С

Самый простой вариант вывести какую-то строку, это использование процедуры Сообщить. Это процедура глобального контекста, которая выводит сообщение пользователю внизу формы.

В параметре этой процедуры указывается переменная с типом строка (или сама строка), которая будет выведена пользователю на форме.

Если мы код выше применим на какой-нибудь управляемой форме, то получим такое сообщение.

Как объединить строки в 1С

В платформе 1С 8.3 имеется возможность объединять строки. Эта операция называется конкатенация, и выполняется при помощи оператора +.

Можно объединить строки, просто сложив две строки в кавычках. Вот так

Также, можно сложить две переменных с типом строка.

Объединять можно и несколько строк.

Перенос строки в 1С

Все строки, которые мы делали ранее, представляли собой одну длинную строку, что, согласитесь, бывает иногда не совсем удобно. Чтобы не испытывать неудобства, в платформе 1С можно переносить строки, тем самым получая многострочные строки. Для этих целей имеется символ переноса строки – «|» (вертикальная черта).

Наша строка с переносом должна иметь следующий вид.

В случае переноса, после окончания ряда строки не должно быть ни каких символов, а каждая новая строка должна начинаться с символа переноса строки «|».

Если мы выведем эту строку с помощью уже знакомого нам метода Сообщить, то будет такой результат.

Причём, обращу ваше внимание, что не достаточно просто написать символ «|» в строке, нужно этот символ, именно, перенести на новую строку в коде. Поэтому при написании такой строки:

Будет выводиться неверный результат:

Кавычки в строке в 1С

Иногда необходимо внутри строки отобразить кавычку как символ, как это сделать, если у нас кавычка открывает или закрывает строку. Для того, чтобы в строке вывелась кавычка необходимо в строке написать две кавычки подряд.

Будет выдавать следующий результат:

Пустая строка в 1С

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

То есть вот так.

Также, в платформе 1С 8.3. имеется возможность проверить, является строка пустой или нет. Для этого необходимо воспользоваться функцией ПустаяСтрока, где в качестве параметра нужно указать проверяемую строку, а возвращает она Истину, или Ложь, в зависимости от того, пустая строка или нет.

Также, эта функция вернет Истина, если в строке одни пробелы.

В этом примере я воспользовался отладкой в коде.

Перевод примитивных типов в строку

Часто возникает задачи, когда нужно примитивный тип перевести в строку, это можно сделать, используя метод Формат, или просто применить метод глобального контекста Строка, где в качестве параметра указать значение примитивного типа. При помощи этого метода можно перевести число в строку, дату в строку и тип булево в строку.

В коде ниже, преобразуются число, булево значение Истина и дата (текущая дата) в строку, а потом все это выводится в сообщении.

У этого кода будет следующий результат:

Причем, в методе Сообщить мы можем в некоторых случаях указать и переменную не строкового типа.

Также можно операцией конкатенацией соединять переменную типа строка с примитивной переменной не строкового типа.

В обоих случаях код нормально отработается.

Конкатенацией мы можем соединить строку с другим примитивным типом, но не можем, к примеру, соединить дату и булево.

Рекомендую вам не злоупотреблять конкатенацией с другими типами, иногда это может приводить к критическим ошибкам.

Строка 1С в клиентском и серверном контексте

Переменную примитивного типа строка можно создать, как в серверном, так и в клиентском контексте. Такой код будет вполне рабочий.

И также, для строк имеется возможность сериализации: т.е. можно перенести переменную с типом строка с клиента на сервер и наоборот:

Поэтому, и такой код будет вполне рабочим:

И наоборот, код также будет работать:

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

Использование типа Строка в реквизитах объектов

Для того, чтобы реквизит какого-нибудь объекта имел тип Строка, достаточно просто указать этот тип в свойстве Тип нужного реквизита объекта.

У реквизита со свойством строка мы можем указать максимальную длину строки, а также будет длина строки фиксированная или переменная. Максимальная длина – это максимальное количество символов, которое можно вписать в строку.

Если мы укажем, что длина строки фиксированная, то длина строки реквизита объекта всегда будет приводиться к максимальной (заполняться пробелами).

Например, у реквизита ПолноеНаименование справочника Товары, я указал длину строки 10, и также отметил, что это фиксированная длина.

Если я запишу какое-то значение в поле формы, от оно автоматически заполнится пробелами до конца строки, и точно также с пробелами запишется в базу данных.

А если бы мы указали, что допустимая длинна – переменная.

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

Также у строки можно указать, что она имеет неограниченную длину

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

Использование типа строка на управляемой форме

Реквизит управляемой формы 1С также может иметь тип Строка. Достаточно это указать в свойстве Тип реквизита.

Причем нам нужно нажать на кнопку «…» свойства, чтобы получить доступ к дополнительным свойствам строки.

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

Если мы снимем признак неограниченности длинны строки, то сможем указать, какая будет строка – фиксированная или переменна.

Если мы перетащим реквизит в элементы формы, то будет создано поле ввода, в которое пользователь может вводить любую строковую информацию.

У нас имеется возможность сделать многострочный режим ввода, если у элемента поле ввода установим в свойство Многострочный режим значение Да.

Другие статьи о примитивных типах:

Более подробно и основательно начальные вопросы программирования в 1С есть вы можете изучить в
Книга «Программировать в 1С за 11 шагов»

Изучайте программирование в 1С в месте с моей книгой «Программировать в 1С за 11 шагов»

Книга написана понятным и простым языком — для новичка.

  1. Книга посылается на электронную почту в формате PDF. Можно открыть на любом устройстве!
  2. Научитесь понимать архитектуру 1С;
  3. Станете писать код на языке 1С;
  4. Освоите основные приемы программирования;
  5. Закрепите полученные знания при помощи задачника.

О том как разрабатывать под управляемым приложением 1С, читайте в книге Книга «Основы разработки в 1С: Такси»

Отличное пособие по разработке в управляемом приложении 1С, как для начинающих разработчиков, так и для опытных программистов.

  1. Очень доступный и понятный язык изложения
  2. Книга посылается на электронную почту в формате PDF. Можно открыть на любом устройстве!
  3. Поймете идеологию управляемого приложения 1С
  4. Узнаете, как разрабатывать управляемое приложение;
  5. Научитесь разрабатывать управляемые формы 1С;
  6. Сможете работать с основными и нужными элементами управляемых форм
  7. Программирование под управляемым приложением станет понятным

Промо-код на скидку в 15% — 48PVXHeYu

Эти книги, плюс книга по программированию оперативного учета имеются в едином комплекте: комплект книг по разработке в 1С.
Только для читателей моего блога,
промо-код на скидку в 300 рублей на весь комплект: blog


Если Вам понравился этот урок, был полезен или помог решить какую-нибудь проблему, то Вы можете поддержать мой проект, перечислив любую сумму
.

можно оплатить вручную:

Яндекс.Деньги — 410012882996301
Web Money — R955262494655

Парные и непарные кавычки

Типографика. Оформление текстов

Кавычки — парный знак препинания, который употребляется для выделения прямой речи, цитат, отсылок, названий литературных произведений, газет, журналов, предприятий, а также отдельных слов, если они включаются в текст не в своём обычном значении, используются в ироническом смысле, предлагаются впервые или, наоборот, как устаревшие и т. п.

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

В русском языке традиционно применяются французские «ёлочки», а для кавычек внутри кавычек и при письме от руки — немецкие «лапки». Кроме того, при переводе значения иноязычного слова иногда также употребляют английские одиночные (или так называемые марровские) кавычки (‘ ’).

Поиск ответа

Всего найдено: 23

Здравствуйте! Скажите, пожалуйста, как следует писать название остановки со включённым в него названием объекта, пишущегося в кавычках. В двойных кавычках или без? Например, в объявлениях в транспорте: Следующая остановка — «Метро «Библиотека имени Ленина»?

Ответ справочной службы русского языка

Если есть техническая возможность, следует использовать кавычки разного рисунка: «Метро «Библиотека имени Ленина»». Если такой возможности нет, двойные кав ычки не ставятся: «Метро «Библиотека имени Ленина».

Добрый день! У меня вопрос о кавычках: в сложных предложениях встречается применение двойных кавычек, т.е. первая часть начинается из внешних кавычек, в этой части еще необходимо что-то выделить кавычками, например, наименование, и вся эта сложная конструкция должна закончиться двойным закрытием кавычек. Следует ли применять двойные кав ычки, как в математическом синтаксисе? Спасибо!

Ответ справочной службы русского языка

В таких случаях лучше применять кавычки разного рисунка, например: «»Автоваз» будет развиваться и дальше», – сказал он.

Добрый день! Ставятся ли двойные кав ычки в начале прямой речи, когда первое слово идет в кавычках? Например, «»Автоваз» бцдет развиваться и дальше», — сказал он. Благодарю за ответ. Сергей

Ответ справочной службы русского языка

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

ставятся ли двойные кав ычки после названия компании в конце цитаты, если нет возможности поставить кавычки разного формата?

Ответ справочной службы русского языка

В таком случае используются одинарные кавычки.

С вашего позволения, попробую еще раз задать вопрос, который не дает мне покоя. Нужно ли на обложке книги брать в кавычки название, состоящее лишь из наименования, подлежащего закавычиванию в тексте этой книги? Например, если роман называется «Уют», «Идеал», «Советский» или «Гранд» по названию гостиницы, в котором происходит действие романа, стоит ли так и писать на обложке книги: «Уют», «Идеал» и т. д.?
Кроме того, возможное закавычивание не означает ли, что в условной рецензии на эту книгу следует использовать ужасные двойные кав ычки: «”Уют”», «”Идеал”» и т. п.?
Существуют ли какие-либо указания на этот счет? К сожалению, мне не удалось найти ответов на эти вопросы ни в справочниках, ни в интернете. Но может быть, я что-то и упустил.

Буду рад вашему ответу.

Ответ справочной службы русского языка

Кавычки, указывающие на то, что заголовок является собственным условным наименованием, будут уместны на обложке книги. Двойные кав ычки в рецензии избыточны.

Здравствуйте. Спор вышел с коллегами, я говорю, что в интернет-газете кавычки должны ставиться как в обычном печатном издании: по краям «ёлочки», внутри немецкие «лапки» (пример 1). Мне возражают, что «ведущие» интернет-газеты ставят три «ёлочки» (№ 2) или компьютерные кавычки (№ 3), и это нормально для Интернета. Я отвечаю, что если есть техническая возможность (а она ЕСТЬ), надо ставить двойные кав ычки как положено. Что скажете?
1. ФГУП «Российский научный центр „Прикладная химия“» (классич. двойные кав ычки)
2. ФГУП «Российский научный центр «Прикладная химия»
3. ФГУП «Российский научный центр «Прикладная химия»(«)

Ответ справочной службы русского языка

Совсем плох третий вариант с двумя знаками в конце предложения. В остальном — вопрос не орфографический, не лингвистический. Скорее, вопрос типографской эстетики. Как лучше, Вы знаете: немецкие «лапки», конечно, отличный вариант для верстки, но есть ли «руки», чтобы их последовательно проставлять?

Подскажите пожалуста, предусмотрены ли в русском языке двойные кав ычки (т.е. когда название в названии)

Ответ справочной службы русского языка

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

Ответ справочной службы русского языка

Кавычки одного рисунка рядом не повторяют. По возможности используют кавычки разного рисунка: . «».

Подскажите, пожалуйста, если фраза заключена в кавычки, а последнее слово фразы также заключено в кавычки, в конце ставятся двойные кав ычки или одни?
Спасибо.

Ответ справочной службы русского языка

Можно либо использовать кавычки разного начертания, либо закрыть фразу одними закрывающими кавычками.

Здравствуйте, подскажите, пожалуйста, ставятся ли в русском языке двойные кав ычки и, если ставятся, то в каких случаях? В частности, столкнулся с такой ситуацией: в Беларуси существует организация, название которой пишется так: «Движение «За Свободу». Надо ли здесь ставить две закрывающие кавычки в конце или ставится одна? И надо ли ставить две открывающие кавычки, если с названия организации начинается цитата?

Ответ справочной службы русского языка

Следует использовать внутренние кавычки другого рисунка («лапки» вместо >) или избегать скопления кавычек. Если эти приемы невозможны, допускается «непарное» число кавычек.

Спасибо за ответ. Но, вероятно, я не совсем корректно задала вопрос. Нужно ли ставить двойные кав ычки: ООО «Косметическая фирма «Солнышко»». Спасибо

Ответ справочной службы русского языка

В таком случае предпочтительно использовать кавычки разного рисунка: ООО «Косметическая фирма «Солнышко»» . Если по каким-то причинам это невозможно, допустимо писать: ООО «Косметическая фирма «Солнышко». Кавычки одного рисунка рядом не повторяются.

Здраствуйте! Скажите пожалуйста, как правильно ставить двойные кав ычки в названиях. Ставятся ли закрывающие ковычки 2 раза или один?. Спасибо

Ответ справочной службы русского языка

Если в предложении необходимо использовать двойные кав ычки, можно ли использовать одни и те же, например:

Задача «Работа по программе «Восстановление работы ног»»

или следует использовать разные, например:

Задача «Работа по программе «Восстановление работы ног»»

Ответ справочной службы русского языка

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

Здравствуйте! Вам пишут из редакции электронной газеты. У нас принят один вид кавычек — » «. И постоянно возникает вопрос, как оформлять в таком случае преложения типа: «Сегодня мы познакомимся с историей написания романа «Война и мир»», — сказал учитель. Нужны ли двойные кав ычки в конце или достаточно одних? Спасибо.

Ответ справочной службы русского языка

Вторые кавычки не нужны: _»Сегодня мы познакомимся с историей написания романа «Война и мир», — сказал учитель._

Подскажите, пожалуйста, ставятся ли в предложении двойные кав ычки (по типу двойных скобок)?

Ответ справочной службы русского языка

источники:

http://orfogrammka.ru/%D1%82%D0%B8%D0%BF%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D0%BA%D0%B0/%D0%BF%D0%B0%D1%80%D0%BD%D1%8B%D0%B5_%D0%B8_%D0%BD%D0%B5%D0%BF%D0%B0%D1%80%D0%BD%D1%8B%D0%B5_%D0%BA%D0%B0%D0%B2%D1%8B%D1%87%D0%BA%D0%B8/

http://new.gramota.ru/spravka/buro/search-answer?s=%D0%B4%D0%B2%D0%BE%D0%B9%D0%BD%D1%8B%D0%B5%20%D0%BA%D0%B0%D0%B2

Совмещение

Зарплата и кадры государственного учреждения, редакция 3.1 (3.1.13.219)
Здравствуйте ! Создаю сотруднику документ «Совмещение профессий» — Совмещение должностей — выбираю должность .Выходит ошибка»выходит ошибка — «словосочетание содержит непарные скобки или кавычки». При выборе этой же должности н-р в кадровом перемещение ничего подобного не происходит

Эти
действия осуществляются в среде
программирования QBASIC.
Для входа в главное меню необходимо
нажать клавишу ALT.
Затем нажать подсвеченную букву пункта
меню и выбрать нужный пункт под меню.
Если пункт подменю оканчивается
троеточием «…», что при выборе
этого пункта возникнет диалоговое окно.

Главное
меню включает пункты «ФАЙЛ, РЕДАКТИРОВАНИЕ,
ПРОСМОТР, ПОИСК, ЗАПУСК, ОТЛАДКА,
ПАРАМЕТРЫ, СПРАВКА». Рассмотрим содержание
пунктов меню:

Среда
программирования QBASIC
представляет собой интеллектуальный
редактор, осуществляющий синтаксический
контроль вводимого текста. Если
строка программы, набранная строчными
буквами, написана правильно, то после
перевода курсора на следующую строку
все ключевые слова
QBASIC
будут написаны заглавными буквами,
операторы отделены друг от друга
.
Это позволяет сразу понять, есть ли в
строке ошибки.

При
редактировании удаление текста слева
от курсора производится клавишей
Backspace
(),
а справа — клавишей Del.
Чтобы копировать, вырезать, удалить
текст, его предварительно необходимо
выделить. Выделяется текст с помощью
комбинации клавиши Shift
+ клавиши со стрелками или с нажатой
левой клавишей мыши. Приемы ввода текста
мало отличаются от работы в других
редакторах. Наиболее применяемые команды
меню дублируются комбинациями клавиш
(см. таблицу 0.0.5).

Среда
программирования QBASIC
позволяет запустить программу на
выполнение. Если появилось сообщение
об ошибке, и она понятна, следует щелкнуть
по кнопке OK,
при необходимости уточнений выбрать
Справку
или обратиться к таблице 0.0.6.

Вот
некоторые приемы, применяемые при
отладке программ. Например, если программа
по 2-й лабораторной работе дает неправильные
значения, то это может быть по двум
причинам: либо неправильно реализованы
формулы, либо не реализовано ветвление
и программа считает не по той формуле.
Чтобы проверить второй вариант, нужно
воспользоваться клавишей F8,
высвечивающей траекторию движения по
программе. При этом строки с оператором
IF…THEN
следует сделать многооператорными,
поставив в конце пустой PRINT.
Если какой-либо оператор мешает
разобраться в причинах появления ошибки,
то его можно вывести из рассмотрения,
не стирая, поставив перед ним оператор
REM.
А чтобы вывести из рассмотрения большой
фрагмент программы, следует использовать
GOTO
с указанием номера строки, куда следует
перепрыгнуть. Чтобы разобраться с
циклом, например, выяснить, правильно
ли считается сумма, можно в него вставить
оператор PRINT,
поставив за ним SLEEP,
организующий паузу до нажатия любой
клавиши. Впрочем, с целью создания паузы
можно применять и просто SLEEP.
Проверить, работает ли цикл или иной
фрагмент программы, можно, использовав
PRINT
«Я здесь».

Таблица 0.0.5.

Назначение
функциональных клавиш в среде
QBASIC

Клавиши

Назначение

F1

Справка
по ключевому слову, функции или
оператору, отмеченному курсором

Shift+F1

Вывод
на дисплей оглавления справочной
информации

F2

Вывод
на экран списка имен всех задействованных
в программе процедур и функций, а также
самой программы

Sfift+F2

Вывод
на экран следующей процедуры или
функции

Ctrl+F2

Вывод
на экран предыдущей процедуры или
функции

F3

Повтор
поиска по ключевому слову

F4

Переход
к экрану вывода и обратно

F5

Продолжение
работы по программе

Shift+F5

Запуск
программы

F6

Переброс
курсора из окна ввода программы в окно
непосредственного счета и обратно

Shift+F6

Переброс
курсора из одной створки окна
редактирования в другую и обратно

F7

Выполнение
программы до курсора

F8

Пошаговое
выполнение программы с заходом в
процедуры и функции

F9

Установка
или снятие контрольной точки в программе

F10

Пошаговое
выполнение программы без захода в
процедуры и функции

Shift+
+клавиши
со
стрелками

Выделение
фрагмента программы

Shift
+Del

Вырезание
фрагмента программы

Ctrl
+Y

Вырезание
строки программы

Shift
+Ins

Вставка
в программу ранее вырезанного фрагмента

Ctrl
+Ins

Копирование
выделенного фрагмента программы

Ctrl
+ Shift

Русский
шрифт (правые), английский (левые)

Ctrl +Break

Приостановка
выполнения программы

Примечание:

Комбинация
клавиш, например, сначала нажать Ctrl,

затем, не отпуская Ctrl,
нажать Shift

Таблица 0.0.6.

Код

Сообщение об
ошибке и возможная причина

1

NEXT
без
FOR
(NEXT
without FOR)

Для
окончания цикла NEXT
нет соответствующего заголовка FOR.
Количество FOR
и NEXT
должны совпадать

2

Синтаксическая
ошибка
(Syntax error)

Оператор
содержит грамматическую ошибку в
написании ключевого слова или ошибку
в пунктуации, либо есть непарные скобки
или другие нарушения правил синтаксиса
языка Бейсик

3

RETURN
без
GOSUB
(RETURN
without GOSUB)

Для
оператора возврата из подпрограммы
RETURN
нет соответствующего обращения к
подпрограмме GOSUB

4

Нет
данных
(Out of DATA)

В
операторе DATA
нет данных. Посчитайте количество
данных в операторе DATA
и количество считываний из него
оператором READ.
Посмотрите внимательно, не поставили
ли вы при перечислении данных в
каком-нибудь месте точку вместо запятой

5

Неверный
вызов
функции
(Illegal function call)

Возникает
чаще всего при попытке извлечения
квадратного корня из отрицательного
числа или появления отрицательного
числа или 0 под знаком логарифма, а
также применения графических операторов
без включения графического режим
SCREEN.
Вообще же подобное сообщение возникает
при попытке вызова функции с недопустимым
параметром

6

Переполнение
(Overflow)

Числовая
переменная или строковая константа
выходят за пределы допустимого
диапазона (например, в знаменателе
получается очень малая величина или
при работе с возведением в степень).
Проверьте и измените значение при
необходимости

7

Не
хватает
памяти
(Out of memory)

8

Метка
не определена
(Label not defined)

Для
операторов GOTO
или GOSUB
задается переход на несуществующую
метку

9

Индекс
вне
диапазона
(Subscript out of range)

Сообщение
возникает при работе с массивами,
когда индекс какого- либо элемента
массива превышает его объявленный в
операторе DIM
размер, а также в том случае, когда
массив занимает в памяти объем более
64 Кбайт. Появляется также, если в
формуле, оперирующей с элементами
массива, они заменены другими переменными
(x(i)
заменен на просто x).

10

Повторяющееся
определение
(Duplicate definition)

Может
возникнуть, если элемент массива,
объявленного в операторе DIM,
фигурирует далее (в формуле или
выражении) в несвязанном или неправильно
связанном виде

Продолжение таблицы
0.0.6.

11

Деление
на ноль
(Division of zero)

Выражение
в знаменателе после подстановки
значений переменных и вычислений,
видимо, обращается в ноль

12

Ошибка в режиме
управления

13

Ошибка ввода

14

В
строке нет места
(Out
of
string
space)

16

Слишком
сложная строковая формула

(String
formula too complex)

17

Невозможно
продолжить

18

Функция
не определена
(Function not defined)

Возможно,
используемая функция не определена
опера-тором DEF
FN,
или допущена ошибка при определении
или вызове функции

19

Нет
RESUME
(No
RESUME)

20

RESUME
без
ошибки
(RESUME
without error)

24

Устройство
в тайм-ауте
(Device timeout)

25

Ошибка
устройства
(Device fault)

26

FOR
без
NEXT (FOR
without NEXT)

Для
заголовка цикла FOR
нет соответствующего окончания цикла
NEXT.
Количество FOR
и NEXT
должны совпадать

27

Нет
бумаги
(Out of paper)

29

WHILE
без
WEND
(WHILE without WHILE)

Для
ключевого слова WHILE
нет соответствующего слова WEND

30

WEND
без
WHILE
(WEND without WHILE)

Для
ключевого слова WEND
нет соответствующего слова WHILE

33

Повторяющаяся
метка
(Duplicate label)

При
расстановке меток допущен повтор
одной и той же метки в разных местах
программы. Обычно возникает при
редактировании текста программы
копированием

35

Подпрограмма не
определена

Сообщение
возникает при попытке обращения к
несуществующей подпрограмме

37

Ошибка счетчика
аргументов

38

Массив не определен

Попытка
работать с элементами массива, который
не был объявлен оператором DIM

39

Требуется
CASE ELSE
(CASE ELSE expected)

40

Необходима
переменная
(Variable required)

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

Продолжение таблицы
0.0.6.

50

Переполнение
FIELD
(FIELD overflow)

51

Внутренняя
ошибка
(Internal
error)

Чаще
всего неверная работа компьютера,
реже – смысловые ошибки программы,
не сразу различимые на первый взгляд.
Часто требуется ручная прокрутка
программы

52

Плохое
имя файла / плохой номер

(Bad
file name or number)

Имя
файла не соответствует требованиям
DOS
(например, не указан путь для файла не
из текущего каталога)

53

Файл
не
найден
(File not found)

При
попытке обращения к файлу неправильно
указано его имя или путь к нему

54

Плохой
режим файла
(Bad file mod)

Возникает,
если файл создан в редакторе не
совместном с редактором, используемым
в настоящем случае

55

Файл
уже
открыт
(File already open)

Попытка
повторного открытия файла или удаления
открытого файла

56

Оператор
FIELD активен
(FIELD statement activ)

57

Ошибка
в/вв устройства
(Device I/O error)

Ошибка
устройства ввода/вывода, с которой не
справляется DOS.
Попробуйте посмотреть, все ли в порядке
с аппаратной частью, т.е. внешними
устройства компьютера

58

Файл
уже существует
(File already exists)

Попытка
сохранить файл под именем уже
существующего на диске файла

59

Неверная
длина записи
(Bad record length)

61

Диск
заполнен
(Disk full)

Диск,
на который производится запись файла,
не имеет достаточно места для этого.
Надо освободить дисковое пространство,
удалив что-нибудь менее важное

62

Ошибка:
введен конец файла
(Input
past end of file)

Возникает,
когда для чтения из файла организуется
цикл, число шагов которого больше
числа содержащихся в файле записей.
Чтобы избежать появление ошибки,
используйте функцию EOF
для досрочного выхода из цикла.

63

Неверный
номер
записи
(Bad record number)

64

Плохое
имя
файла
(Bad file name)

Имя
файла не соответствует требованиям
DOS

67

Слишком
много файлов

(Too
many
files)

68

Устройство
недоступно

(Device
unavailable)

В
дисководе нет диска или он испорчен

Окончание таблицы
0.0.6.

69

Переполнение
буфера коммуникации

(Communication-buffer
overflow)

Попытка
копирования в буфер слишком большого
объема информации

70

Нет
разрешения

(Permission
denied)

71

Ошибка
формата диска

(Disk
not
ready)

Открыта
защелка дисковода, в дисководе нет
диска или он испорчен.

72

Ошибка
диска
(Disk-media error)

В
дисководе нет диска или он испорчен

73

Недоступная
возможность
(Advanced
feature unavailable)

74

Переименование
через диски
(Rename
across
disks)

75

Ошибка
доступа к пути / файлу
(Path
/ File
access
error)

76

Путь
не найден
(Path
not
found)

При
попытке обращения к файлу неправильно
указано его имя или путь к нему

Пишем простой транслятор на Лиспе — I +17

Lisp


Рекомендация: подборка платных и бесплатных курсов создания сайтов — https://katalog-kursov.ru/

Давайте попробуем написать на Лиспе… транслятор простого императивного языка. Нет-нет, я не ошибся – именно транслятор. Транслировать он будет в Лисп-код. А дальше этот код может быть выполнен Лисп-системой.

Здесь бесценную услугу нам окажет то обстоятельство, что в Лиспе нет барьера между кодом и данными (это редкое свойство некоторых языков программирования называется “гомоиконность”). Но и изобразительные возможности Лиспа тоже сыграют не последнюю роль.

В качестве реализации я буду использовать HomeLisp. Желающие смогут адаптировать этот проект под Common Lisp. Скажу сразу – применительно к рассматриваемой задаче существенная разница между Common Lisp и HomeLisp состоит только в обработке строк и файлов.

Скачать портабельную версию HomeLisp можно по ссылке. На этом же сайте расположена и документация. Желающие могут копировать код из статьи и сразу проверять работоспособность.

Предлагаемая вашему вниманию тема послужила основой для моей мастерской на знаменитой Новосибирской ЛШЮП-2018. С результатами мастерской можно ознакомиться здесь. А далее я излагаю свой подход. Предполагаю, что читатель знаком с языком Лисп.

Приступаем

Начнем с “простого императивного языка”, который мы будем транслировать в Лисп.
Язык будет обрабатывать только числовые данные. Код на этом языке состоит из функций (процедур, возвращающих значения). Среди этих функций одна должна называться main. Именно с этой функции начинается выполнение кода. Хотя зачем так себя связывать? Пишем функции на императивном языке, они транслируются в Лисп и могут использоваться вместе с лисповскими функциями. Но не будем забегать вперед…

Набор операторов языка обычен: присвоение, ветвление, арифметический цикл, досрочный выход из цикла, ввод, вывод и вызов функции. Впрочем, синтаксически вызов функции оформляется как присвоение (результата вызова). Комментарии пусть содержат звездочку в первой позиции строки. Язык, разумеется, должен обеспечивать возможность создания рекурсивных функций. Чтобы стало понятнее, приведу примеры кода – печать последовательных нечетных чисел и вычисление их суммы:

proc main()
  local s,n,k
  input n
  for i=1 to n
      k=2*i-1
      print k
      s=s+k
  end_for
  print s  
end_proc

По своему духу – это бэйсик-подобный язык. Я буду называть его “мини-бэйсик”. Наш транслятор должен преобразовать приведенный код в следующую Лисп-функцию:

(defun main nil
   (let ((s 0) (n 0) (k 0))
     (setq n (read))
     (iter (for i from 1 to n)
       (setq k (- (* 2 i) 1))
       (printline k)
       (setq s (+ s k)))
   (printline s)))

Мне очень нравится пакет iterate, который в профессиональных пакетах Common Lisp реализован в виде макро. В HomeLisp функция iter (реализующая значительную часть возможностей макро iterate) включена в ядро языка. Мое пристрастие к iter и послужило причиной того, что циклы нашего “мини-бэйсика” будут транслироваться в вызовы iter.

С чего начать реализацию? Давайте начнем ее с выбора файла, подлежащего трансляции и с построчного чтения и печати этого файла. Запускать транслятор нам придется множество раз, так пусть этот запуск с самого начала будет удобным. Вот как может выглядеть эта функция:

(defun start (&optional (fname nil))
   (setq *numline* 0)
   (setq *flagerr* nil)
   (when (null fname)
         (setq fname (sysGetOpenName (sysHome) "Мини-бэйсик|*.mbs")))
   (let ((fi (gensym 'fi)))
        (when fname          
          (filOpen fi fname _INPUT)
          (loop
              (getLine fi) 
              (when (or *flagerr* (filEOF fi)) (return t)))
          (filClose fi)
          (when *flagerr* (printsline "**** Были найдены ошибки"))))
   (unset '*numline*)
   (unset '*flagerr*))

Функция имеет необязательный параметр fname – имя файла, содержимое которого будет транслироваться. При входе в функцию создаются две глобальные переменные numLine номер строки исходного файла и flagerr — флаг состояния ошибки. Перед завершением функции эти переменные уничтожаются (функция HomeLisp-а unset уничтожает глобальные переменные).

Если имя входного файла опущено – то вызывается стандартный windows-диалог выбора файла (sysGetOpenName). В качестве стартовой директории используется текущая директория (sysHome). Далее создается уникальный символ для файлового манипулятора и файл открывается для текстового чтения. Затем в бесконечном цикле производится чтение файла строка за строкой (функция getLine). После каждой операции проверятся, не возникла ли ошибка, и не достигнут ли конец файла. Если возникла ошибка или зафиксирован конец файла – цикл разрывается, файл закрывается, и, если были ошибки – выводится итоговое сообщение.
Собственно чтение из файла выполняет функция getLine:

(defun getLine (fil)
  (let ((stri ""))
    (loop
      (when (filEof fil) (return ""))
      (setq *numline* (add1 *numline*)) 
      (setq stri (filGetline fil))
      (printsline (strCat (format *numline* "0000") " " 
                  (strRTrim stri)))
      (setq stri (strATrim stri)) 
      (unless (or (eq "" stri) (eq "*" (strLeft stri 1))) 
      (return stri)))))

Эта функция принимает идентификатор открытого файла и в бесконечном цикле выполняет следующие действия:

  • проверяет состояние “конец файла”. В этом случае цикл разрывается и функция возвращает пустую строку;
  • увеличивается на единицу счетчик прочитанных строк;
  • читается очередная строка файла;
  • прочитанная строка печатается с удалением возможных пробелов справа;
  • если прочитанная строка непуста и не содержит звездочку в первой позиции, то она
    возвращается из функции;

Таким образом, в выходной листинг попадают все строки файла в их исходном виде.

Разбиваем на процедуры

А теперь давайте научим наш код разбивать входной поток на отдельные процедуры. Сначала введенную строку потребуется разбить на лексемы (неделимые входные лексические единицы). Этот процесс называется парсингом; нам предстоит создать парсер. Написание парсеров — классическая тема, существуют библиотеки готовых парсеров и специальные средства, позволяющие сгенерировать нужный парсер… Мы пойдем своим путем.

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

  • Обычные символы;
  • Символы-разделители.

Так, в операторе присвоения “x = 15 + y^2” символы x,1,5,y и 2 – есть обычные символы, а символы “пробел”, +,^ — разделители. Чем обычный символ отличается от разделителя? Разделитель – всегда отделяет одну лексему от другой. Наш оператор присвоения, будучи разбит на лексемы, выглядит так: “x”, “=”, ”15”, “y”, “^”, “2”.

Как можно заметить, не все разделители попадают в результат парсинга (пробелы, в частности, не попадают). Будем называть разделители, которые не попадают в результат, разделителями первого типа. Остальные разделители будут называться разделителями второго типа.

Входом парсера будет строка, выходом – список строковых лексем. В качестве накопителя будет использоваться локальная переменная – аккумулятор. Первоначально аккумулятор содержит пустую строку.

Алгоритм парсинга может быть таким: читаем символ за символом входную строку. Если встретился обычный символ, конкатенируем его с аккумулятором. Если встречается разделитель, то:

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

Вот код парсера:

(defun parser (txt &optional (d1 " ,") (d2 "()+-*/^=<>%"))
  (let ((res nil)
        (lex "") )
   (iter (for s in-string (strCat txt (strLeft d1 1)))
     (cond ((plusp (strInd d1 s))
            (when (> (strLen lex) 0) (collecting lex into res))
                  (setq lex ""))
           ((plusp (strInd d2 s)) 
            (when (> (strLen lex) 0) (collecting lex into res))
                  (collecting s into res)  
                  (setq lex ""))
           (t (setq lex (strCat lex s))))) res))

У функции кроме обязательного параметра имеется два необязательных: d1 содержит строку, каждый символ которой есть разделитель первого типа, а строка d2 содержит разделители второго типа.

Программная логика функции parser описана выше. Следует только отметить, что перед началом работы к концу входной строки присоединяется разделитель. Это сделано для того, чтобы последняя обработанная лексема на “зависла” в аккумуляторе (роль аккумулятора играет локальная переменная lex).

Проверим наш парсер “в деле”:

(parser "x = 15 + y^2")
==> ("x" "=" "15" "+" "y" "^" "2")

Все верно, не так ли? Но работать со списками строк – это не вполне по-лисповски. Давайте от списков строк перейдем к списку атомов. Для этого нам понадобится функция, которая… склеит все лексемы опять в длинную строку (но между лексемами вставит по пробелу), потом к началу этой строки приклеит открывающую скобку, к концу – закрывающую… а затем заставит Лисп прочитать полученный список:

(defun mk-intf (txt)
  (let ((lex (parser txt " ," "()+-*/^=<>%"))
        (intf ""))
   (iter (for a in lex) (setq intf (strCat intf a " ")))
   (input (strCat "(" intf ")"))))

Теперь, если подать на вход функции mk-intf наш оператор присвоения, то получим:

(mk-intf "x = 15 + y^2")
==> (X = 15 + Y ^ 2)

Что, согласитесь, гораздо приятнее.

Теперь немного изменим функцию start: эта функция должна будет читать и обрабатывать целые процедуры:

(defun start (&optional (fname nil))
   (setq *numline* 0)
   (setq *flagerr* nil)
   (when (null fname)
         (setq fname (sysGetOpenName (sysHome) "Мини-бэйсик|*.mbs")))
   (when fname      
      (let ((fi (gensym 'fi)))
           (filOpen fi fname _INPUT)
           (loop
               (let ((curr-proc (action-proc fi)))
                    (when (or *flagerr* (filEOF fi)) (return t))
                    (eval curr-proc)))
           (filClose fi))
           (when *flagerr* (printsline "**** Были найдены ошибки")))
   (unset '*numline*)
   (unset '*flagerr*))

В теле цикла вызывается функция action-proc (обработать процедуру), которая будет формировать тело принятой процедуры уже на Лиспе. Тело процедуры, сохраненное как S-выражение в переменной curr-proc, передается затем на вход eval. И принятая функция “реинкарнируется” в среде Лисп!

Что должна делать action-proc? Эта функция получает в качестве параметра идентификатор открытого файла. Функция читает из файла строку за строкой, пропускает пустые строки и комментарии, остальные строки парсит, переводит в форму списка, и генерирует тело процедуры.

Мы будем постепенно “учить” action-proc генерации. И начнем с того, что научим нашу функцию распознавать начало и конец процедуры. В мини-бэйсике начало процедуры имеет вид:

proc name(p1,p2,p3)

попробуем распарсить такую строку:

(mk-intf "proc name(p1,p2,p3)")
==> (PROC NAME (P1 P2 P3))

Как же должна реагировать на этот ввод функция action-proc? Вполне естественно: убедившись, что голова списка есть атом PROC, нужно взять второй элемент списка как имя функции, а третий элемент – как список параметров. Имя и список параметров следует сохранить в локальных переменных. Когда же прочитывается оператор end_proc, то нужно из имени функции и списка параметров сформировать форму defun с пустым (пока) телом, и вернуть эту форму как результат. Вот как это выглядит:

(defun action-proc (fi)
   (let ((stmt nil)
         (proc-name nil)
         (proc-parm nil))
    (loop
         (setq stmt (mk-intf (getLine fi))) 
         (when (null stmt) (return t))
         (cond ((eq (car stmt) 'proc) 
                    (setq proc-name (nth 1 stmt))
                    (setq proc-parm (nth 2 stmt)))                    
               ((eq (car stmt) 'end_proc) (return t))
               (t (printsline (strCat "**** Оператор " 
                              (output stmt) 
                              " не распознан")) 
                  (setq *flagerr* t))))
    `(defun ,proc-name ,proc-parm (quote OK))))

Для окончательного формирования предложения defun используется обратная блокировка. Обратите внимание на то, что в качестве результата сгенерированная процедура будет выдавать атом OK.

Теперь мы можем проверить наш код в действии. Занесем в файл 0000.mbs следующий код:

proc f1(x,y)
end_proc 
proc f2(x)
end_proc

Запустим процедуру start, выберем 0000.mbs и увидим на консоли:

0001 proc f1(x,y)
0002 end_proc
0003 proc f2(x)
0004 end_proc

При желании можно убедиться, что Лисп-машине теперь доступны две (пока бесполезные) функции f1 и f2:

(getd 'f1)
==> (EXPR (X Y) (QUOTE OK))
(getd 'f2)
==> (EXPR (X) (QUOTE OK))

Более того! Их уже можно и запустить:

(f1 1 2)
==> OK
(f2 2)
==> OK

Наш транслятор сделал первый вдох…

Ввод, вывод и локальные переменные

А сейчас самое время научить наш новорожденный транслятор обрабатывать операторы input, print и local.

Проще всего обработаем ввод и печать. Оба оператора имеют одинаковую синтаксическую структуру: ключевое слово и переменная. Оператор input x должен превратиться в такую Лисп-форму (setq x (read)). Соответственно, оператор print x превращается в форму (printline x). Для хранения этих форм необходимо в функции action-proc предусмотреть локальную переменную body. В этой переменной будут накапливаться формы, осуществляющие вычисления будущей функции. Дальше все довольно просто:

(defun action-proc (fi)
   (let ((stmt nil)
         (proc-name nil)
         (proc-parm nil)
         (loc-var nil)
         (body nil))
    (loop
         (setq stmt (mk-intf (getLine fi))) 
         (when (null stmt) (return t))
         (cond ((eq (car stmt) 'proc) 
                    (setq proc-name (nth 1 stmt))
                    (setq proc-parm (nth 2 stmt)))                    
               ((eq (car stmt) 'end_proc) (return t))
               ((eq (car stmt) 'print) 
                    (setq body (append body 
                               (list (cons 'printline (cdr stmt))))))
               ((eq (car stmt) 'input) 
                    (setq body (append body 
                      (list (list 'setq (cadr stmt) (list 'read) )))))
               (t (printsline (strCat "**** Оператор " 
                              (output stmt) 
                              " не распознан"))
                              (setq *flagerr* t))))
    `(defun ,proc-name ,proc-parm ,@body)))

Давайте теперь подготовим вот такой исходник на мини-бэйсике:

proc f1(x,y)
 print x
 print y
end_proc 
proc f2(x)
 input x
 print x
end_proc

и попробуем его протранслировать… У нас появятся две лисповские функции f1 и f2. Посмотрим на их определяющие выражения и убедимся, что они сгенерированы верно:

(getd 'f1)
==> (EXPR (X Y) (PRINTLINE X) (PRINTLINE Y))
(getd 'f2)
==> (EXPR (X) (SETQ X (READ)) (PRINTLINE X))

Можно и вызвать эти функции, и убедиться, что они работают именно так, как и предполагалось. Пусть вас не смущает, что мы вводим значение в переменную-параметр – просто у нас нет пока локальных переменных… Давайте их добавим.

Оператор local может находиться в любом месте процедуры и встречаться более одного раза. Если в процессе обработки процедуры встретился оператор local, то необходимо взять список переменных и сохранить его в локальной переменной. После встречи оператора end_proc необходимо сгенерировать форму let и “заключить в нее” все выполняемые операторы (пока – только input и print). Вот как теперь будет выглядеть action-proc:

(defun action-proc (fi)
   (let ((stmt nil)
         (proc-name nil)
         (proc-parm nil)
         (loc-var   nil)
         (lv        nil)
         (body      nil))
    (loop
         (setq stmt (mk-intf (getLine fi))) 
         (when (null stmt) (return t))
         (cond ((eq (car stmt) 'proc) 
                    (setq proc-name (nth 1 stmt))
                    (setq proc-parm (nth 2 stmt)))                    
               ((eq (car stmt) 'end_proc) (return t))
               ((eq (car stmt) 'print) 
                    (setq body (append body 
                               (list (cons 'printline (cdr stmt))))))
               ((eq (car stmt) 'input) 
                    (setq body (append body 
                               (list (list 'setq (cadr stmt) 
                                     (list 'read) )))))
               ((eq (car stmt) 'local) 
                    (setq loc-var (append loc-var (cdr stmt))))
               (t (printsline (strCat "**** Оператор " 
                              (output stmt) " не распознан")) 
                              (setq *flagerr* t))))
    (iter (for a in (setof loc-var)) (collecting (list a 0) into lv))           
    `(defun ,proc-name ,proc-parm (let ,lv ,@body))))

Список локальных переменных накапливается в переменной loc-var. После завершения обработки процедуры из этого списка строится список пар вида (имя 0). При этом нежелательно повторение одинаковых имен… Как его предотвратить? Конечно, можно на каждой обработке оператора local проверять, нет ли повторения имен (если есть – выдавать сообщение об ошибке). Но, мне кажется, лучше просто устранить повторения, что и делает вызов setof. Теперь давайте протранслируем и запустим вот эту программу:

proc f1(x,y)
 local a,b,c
 print x
 print y
 input a
 print a
end_proc

Убеждаемся, что она работает именно так, как и предполагает алгоритм. Но все самое интересное впереди!

Отсюда можно скачать окончательный вариант того, что мы с вами нашкодили…

Продолжение следует!

 

Партнёрская программа 1С и Бланка

 

Зависает на функции «ПолучитьСклоненияСтроки»

Я
   Случайный прохожий

12.10.20 — 10:54

Добрый день!

Есть у клиентов виртуалка с сервером 1С + SQL. У пользователей периодически зависает 1с (может раз в неделю, а может раз в месяц).

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

Платформа раньше стояла 8.3.15.1830 (х32), недавно перевел на 8.3.17.1549 (х64) — не помогло. Кэши, соответственно, почистил, базу обновил до последней (Бухгалтерия Предприятия 3.0.83.33) и перерегистрировал в консоли.

   SleepyHead

1 — 12.10.20 — 11:28

Посмотри, что склоняет. Если в этой строке есть кавычки, непарные скобки и еще что-то, может попытаться вывести сообщение и на этом зависнуть (но это не точно).

Вообще, офигеваю я с этой функции, почему бы не убрать все «неправильные» символы перед анализом, а потом склонять, так и не понял. Пришлось даже вкорячить клиентам расширение, которое это делает, проблемы исчезли.

  

Случайный прохожий

2 — 12.10.20 — 11:36

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

Рекомендовать в новости

0

01.01.2020 — 18:00


С:Предприятие 8.3 (8.3.15.1830)
Бухгалтерия предприятия, редакция 3.0 (3.0.75.37) проф
при загрузке из банка в бухгалтерию 8.3 выходит ошибка — словосочетание содержит непарные скобки или кавычки, не удается провести выгруженную платежку на выплату зарплаты по зарплатному реестр. Помогите, кто может

1

08.11.2021 — 15:59

В личку пришлите мне контакты ваши (можно на почту) и файл, который неверно грузиться/негрузиться. А также по-возможности текст ошибки, исправлю

Понравилась статья? Поделить с друзьями:
  • Ошибка стиральной машины samsung черный
  • Ошибка строка 0 синтаксическая ошибка xml
  • Ошибка строительства квартиры симс 2
  • Ошибка стратега сканворд
  • Ошибка страницы стим