On-line: гостей 2. Всего: 2 [подробнее..]
АвторСообщение





Пост N: 14
Зарегистрирован: 27.08.23
ссылка на сообщение  Отправлено: 18.04.24 21:55. Заголовок: Как смоделировать команду GOTO в Clipper/Harbour


В Интернете я случайно наткнулся на несколько старых компьютерных журналов 1986 года, из которых когда-то учился программированию . Там я нашел листинги понравившихся мне, на языке BASIC (численные методы решения систем уравнений). Я легко портировал несколько программ с Basic на Harbour и они работают хорошо и корректно, но с одной я столкнулся с трудностями. Это листинг программы для решения нелинейных уравнений, и проблема в том, что команда перехода GOTO используется во многих местах этой программы. В некоторых местах GOTO используется безоговорочно, а где-то внутри оператора IF...THEN. Поскольку в Clipper/Harbour нет команды GOTO, есть ли возможность смоделировать ее (команду GOTO)?
Я пытался что-то сделать, изменить программу, но не смог...

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 20 [только новые]







Пост N: 338
Зарегистрирован: 05.10.06
ссылка на сообщение  Отправлено: 19.04.24 09:22. Заголовок: Оператор goto имеетс..


Оператор goto имеется в C++, вероятно с какими то ограничениями можно вставить в код программы:
#pragma BEGINDUMP
код на С++
...
#pragma ENDDUMP

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник


Пост N: 1726
Зарегистрирован: 27.01.07
ссылка на сообщение  Отправлено: 19.04.24 10:37. Заголовок: А можете листинг выл..


А можете листинг выложить? Аж интересно стало)

Спасибо: 0 
ПрофильЦитата Ответить
moderator


Пост N: 1601
Зарегистрирован: 06.07.06
ссылка на сообщение  Отправлено: 19.04.24 11:05. Заголовок: Тут надо программу с..


Тут надо программу смотреть, ее логику - решения возможны разные.
Например, оформить кусак кода, куда ведет goto, как фунцию/процедуру и вызывать ее всюду, где надо.

Спасибо: 0 
ПрофильЦитата Ответить





Пост N: 15
Зарегистрирован: 27.08.23
ссылка на сообщение  Отправлено: 19.04.24 12:46. Заголовок: Как смоделировать команду GOTO в Clipper/Harbour


Я отправляю два файла. Один файл представляет собой отсканированную страницу компьютерного журнала который содержит листинг программы. Сканирование довольно плохое (видимо сканеры 1986 года были не такими уж хорошими). Второй файл — это листинг, который я преобразовал в Harbour. Итак, вы видите, что с этим можно сделать. Если вам удастся решить этот «узел Горди» операторов GOTO, это будет супер!

Скан объявления из журнала:
https://i.postimg.cc/Qd718D1N/Nelinearne-jedna-ine-3.png

Мой перевод с Basic на Harbour:
----------------------------------------------------------------------------------------------------------------------
#include "Hwgui.ch"
#include "guilib.ch"
#include "hbclass.ch"

#include "Common.CH"
#include "Fileio.CH"
#include "Directry.CH"

/*
Эта часть программы решает нелинейные уравнения вида:
(a+bi)X^n + (a+bi)X^n-1 + ... + (a+bi)X^0 = 0, где
а – действительная часть коэффициента,
b – мнимая часть и
n – степень многочлена.

FUNC ResavanjePol( aMt, nn ):
aMt — матрица размером 2 x n, содержащая действительную и мнимую части коэффициентов
nn - степень многочлена

Например:
2X^3 -3X^2 + 4X - 1 = 0
nn := 3
aMt:={ ;
{ 2, -3, 4, -1 }, ;
{ 0, 0, 0, 0 } ;
}
*/

STATIC a:={}, b:={}, p:={}, q:={}, re:={}, im:={}
STATIC i, j, k, e, k1, ii, pp, qq, p1, q1, aa, a1, bb, b1, w, s, z, u, v, n, f, m, l

//------------------------------------------------------------------------------------------
FUNC ResavanjePol( aMt, nn ) // Вычисляет все корни многочлена
LOCAL aResenje:={}, nZbirImg:=0

// Inicijalizacija() -->Точность расчета взята из файла конфигурации - nTacnost:=0.0000001, поэтому функция Inicijalizacija() не нужна

i:=0
j:=0
k:=0
e:=0
k1:=0
ii:=1
pp:=0 // p --> pp В исходной программе переменная "p", я поменял ее на "pp", потому что там тоже есть матрица с таким именем
qq:=0 // q --> qq -II- -II- -II-
p1:=0
q1:=0
a1:=0
aa:=0 // a --> aa -II- -II- -II-
b1:=0
bb:=0 // b --> bb -II- -II- -II-
w:=0
s:=0
z:=0
u:=0
v:=0
f:=0
m:=0
l:=0

n:=nn // Степень многочлена
e:=nTacnost // Точность расчета

a:=ARRAY( n +1 )
b:=ARRAY( n +1 )
p:=ARRAY( n +1 )
q:=ARRAY( n +1 )
re:=ARRAY( n +1 )
im:=ARRAY( n +1 )

FOR i:=1 TO n+1
a:=aMt[1, i] // Действительная (реальная) часть коэффициента
p:=a
b:=aMt[2, i] // Мнимая (имагинарная) часть коэффициента
q:=b
nZbirImg += ABS( b ) // Если сумма мнимых (имагинарных) частей коэффициента равна нулю, решения являются действительными числами
NEXT

IF nZbirImg==0
aResenje:=ARRAY( n ) // Решения — действительные (реальные) числа
ELSE
aResenje:=ARRAY( 2, n ) // Решения представляют собой комплексные числа
END IF

// Вычисление корней многочленов модифицированным методом Ньютона:
k:=n
k1:=k + 1
ii:=1 // GoTo 200
pp:=0
qq:=0

// значение многочлена
a1:=p[1] // GoTo 220
b1:=q[1]
++s

IF s==100
s:=0
e:=e*10
END IF
IF e >= 0.01
RETURN aResenje // Сходимость (конвергенция) не достигнута, конец расчета! Пустая матрица возвращается в основную программу.
END IF

FOR i:=2 TO k1
w:=pp*a1 - qq*b1 + p // Ряд 260
b1:=pp*b1 + qq*a1 + q
a1:=w
NEXT
w:=a1*a1 + b1*b1
IF ii != 1
GoTo_340() // Переход/прыжок
END IF
aa:=a1
bb:=b1
j:=1
ii:=2
GoSub850()
GoTo_220() // Ряд 330 - Переход - Безусловный прыжок

IF ii != 3 // GoTo 340
GoTo_400() // Переход/прыжок
END IF
IF w < aa*aa + bb*bb
GoTo_380() // Переход/прыжок
END IF

z:=z/2
pp:=p1 + z*u
qq:=q1 + z*v // Ряд 360
GoTo_220() // Ряд 370 - Переход/прыжок - Безусловный прыжок

aa:=a1 // GoTo 380
bb:=b1
j:=1
ii:=2

GoSub850() // Ряд 390
GoTo_220() // Ряд 390 - Переход/прыжок
IF w^j > e*e // GoTo 400
GoTo_430 // Переход/прыжок
END IF
j:=j + 1
GoSub850() // Ряд 420
GoTo_220() // Ряд 420 - Переход/прыжок

IF aa + bb < e*e // GoTo 430
GoTo_610() // Переход/прыжок
END IF
u:=-(aa*a1 + bb*b1)/w
v:=(aa*b1 - bb*a1)/w
w:=SQRT(u*u + v*v)
f:=v/w
f:=ATAN(f)/j
IF u < 0
f:=PI()/j - f // Ряд 480
END IF
w:=w^(1/j)
u:=w*COS(f)
v:=w*SIN(f)
k1:=k + 1

FOR i:=1 TO k1
p:=a
q:=b
NEXT
ii:=3
z:=1
p1:=pp
q1:=qq
pp:=p1 + z*u
qq:=q1 + z*v
GoTo_220() // Ряд 590 - Переход/прыжок

// Схема Горнера
FOR l:=1 TO j // GoTo 610

++m
re[m]:=p
IF ABS(pp) < e
re[m]:=0
END IF
im[m]:=qq
IF ABS(qq) < e
im[m]:=0
END IF
k1:=k - l + 1
p[1]:=a[1]
q[1]:=b[1]

FOR i:=2 TO k1 // Ряд 670
p:=a + pp*p[i - 1] - qq*q[i - 1]
q:=b + qq*p[i - 1] + pp*q[i - 1]
a:=p
b:=q
NEXT

NEXT

// Проверка конца // Ряд 730
IF k > j
k:=k - j
GoTo_200() // Переход/прыжок
END IF

// Печать результатов:
/*
Действительные корни находятся в re[], а мнимые корни находятся в im[].
Точность в f.
*/

RETURN aResenje
//-------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------
FUNC GoSub850() // Коэффициенты деривации

k1:=k - j + 1
FOR i:= 1 TO k1
w:=k1 - i + 1
p:=w*p
q:=w*q
NEXT

RETURN NIL
//-------------------------------------------------------------------------------------------

Спасибо: 0 
ПрофильЦитата Ответить





Пост N: 16
Зарегистрирован: 27.08.23
ссылка на сообщение  Отправлено: 19.04.24 12:52. Заголовок: Как смоделировать команду GOTO в Clipper/Harbour


Я тоже пробовал, как вы сказали, но это слишком сложно. Например, оператор GOTO ведет к месту в программе, где есть несколько других операторов GOTO, поэтому программа имеет множественное ветвление. Я пытался, но у меня ничего не получилось, потому что я заблудился, как говорят в Сербии, «как гусь в тумане»...

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник


Пост N: 1727
Зарегистрирован: 27.01.07
ссылка на сообщение  Отправлено: 19.04.24 12:58. Заголовок: Нарисуйте блок-схему..


Нарисуйте блок-схему. Визуально всё увидите.

Спасибо: 1 
ПрофильЦитата Ответить
Администратор




Пост N: 4158
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 19.04.24 13:07. Заголовок: Вспоминаю 40 лет наз..


Вспоминаю 40 лет назад, фортран. Там был goto
В общем случае вопрос решения не имеет. Нет в клиппере-харборе такого оператора. Ну нет и все
А в частном случае надо разбирать логику программы, как сказал Александр. Выделить управляющие операторы, их совсем немного.
Это if-elesif-endif, for-next, case если есть. В тексте вроде бы только видно goto 220. Добавить существующий оператор языка, который бы эмулировал этот goto

Спасибо: 1 
ПрофильЦитата Ответить
постоянный участник




Пост N: 4552
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 19.04.24 13:11. Заголовок: Мирослав Можете исп..


Мирослав
Можете использовать Hash, т.е. ваш код - это наборы блоков кода, goto переход на стоку-позицию в hash, можно добавить в таком случае вариант меток, типа ":met1" и делать переход еще и по меткам (типа Eval или AEval по метке). Что то похожее (типа свой язык со своим препроцессором) делал на clipper, потом перенес в VO на VOScript но оч. давно, в основе был массив
PS
Нашел, что переносил в hb 2.0 из VO, может пригодится (развить команды, препоцессор можно) Скрытый текст

PS2
Можно делать не препроцессор, а интепретатор команд

Спасибо: 1 
ПрофильЦитата Ответить





Пост N: 17
Зарегистрирован: 27.08.23
ссылка на сообщение  Отправлено: 19.04.24 16:49. Заголовок: Как смоделировать команду GOTO в Clipper/Harbour


Когда я задавал этот вопрос на форуме, я надеялся, что в Clipper/Harbor может быть какая-то функция/команда, которая делает то же самое или похожее на GOTO, о которой я не знал.
Поскольку я вижу, что такого не существует, мне придется потрудиться и изменить программу. Скорее всего, я последую совету PSP и нарисую блок-схему (алгоритм).
Потом попробую поменять программу, о чем сообщу на форуме.

Спасибо: 0 
ПрофильЦитата Ответить





Пост N: 18
Зарегистрирован: 27.08.23
ссылка на сообщение  Отправлено: 22.04.24 12:29. Заголовок: Как смоделировать команду GOTO в Clipper/Harbour


После долгих раздумий я решил последовать совету, данному мне MIKHAIL-ом, а именно написать эту часть программы на C:

#pragma BEGINDUMP
код в С (gcc.exe)
...
#pragma ENDDUMP

В самом начале я столкнулся с проблемой, поэтому хотел бы попросить кого-нибудь, кто в этом разбирается, помочь мне. Вот проблема:
Мне нужно вызвать функцию, которая написана в C, из основной программы, которая написана в Harbour, и передать ей три параметра, а именно: 1-двумерная матрица/area (разм. m x n), 2-параметр n и 3-параметр nTacnost. Далее, мне нужно, чтобы эта функция в C возвращала двумерную матрицу решений. Вот пример:

FUNC MyProg()
LOCAL aResenja:={}...
...
...( Код у Harbour)...
...
aResenja:= ResavanjePol( aMatr, n, nTacnost)
...
RETURN NIL
...
...
#pragma BEGINDUMP
...
(код у С - gcc.exe):
HB_FUNC( RESAVANJEPOL )
{
int n; // Степень полинома, целое число
float e; // Точность, 0.0000001 (на пример)
float **aMt; // Area dim m x n
float **aResenja; // Area dim m x n

n=hb_parni(2);
e=hb_parnd(3);

aMt = hb_par??? ; // Я не знаю как правильно написать эту часть кода

aResenja = (???)hb_xgrab( ??? ); // Я не знаю как правильно написать эту часть кода
...
...
...

??? hb_ret???( aResenja ); // Я не знаю как правильно написать эту часть кода
}
#pragma ENDDUMP

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

Спасибо: 0 
ПрофильЦитата Ответить





Пост N: 339
Зарегистрирован: 05.10.06
ссылка на сообщение  Отправлено: 22.04.24 16:49. Заголовок: давненько не писал, ..


давненько не писал, могу ошибиться, надеюсь коллеги поправят меня:

aMt = hb_param( 1, HB_IT_ARRAY );

hb_itemRelease( hb_itemReturn( aResenja ) );

Спасибо: 1 
ПрофильЦитата Ответить





Пост N: 19
Зарегистрирован: 27.08.23
ссылка на сообщение  Отправлено: 23.04.24 00:12. Заголовок: Как смоделировать команду GOTO в Clipper/Harbour


То, что вы написали, работает хорошо (aMt = hb_param( 1, HB_IT_ARRAY ); и hb_itemRelease( hb_itemReturn( aResenja ) ); ).
Как мне получить доступ к элементам двумерной матрицы (area), aMt[m][n] ? Когда я пишу aMt[0][0] и aMt[0][1], программа зависает... И как мне зарезервировать меморию для матрицы aResenja ?

Спасибо: 0 
ПрофильЦитата Ответить
moderator


Пост N: 1602
Зарегистрирован: 06.07.06
ссылка на сообщение  Отправлено: 23.04.24 09:17. Заголовок: Передача и возврат м..


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

PHB_ITEM pArray = hb_param( 1, HB_IT_ARRAY )

Его формат хранения, тип данных - это не C массив, к нему нельзя обращаться как к C массиву, с помощью квадратных скобок.
Его можно пройти от начала до конца, из каждого элемента извлечь вложенный массив, этот вложенный массив тоже пройти от начала до конца и извлечь каждый его элемент - это уже будет число из вашей матрицы:
 
PHB_ITEM pArray = hb_param( 1, HB_IT_ARRAY ), pSubArr;
ULONG ul1, ulLen1 = hb_arrayLen( pArray ), ul2, ulLen2;
float myfloatNum;
for( ul1 = 1; ul1 <= ulLen1; ul1++ ) {
// вот так мы извлекаем вложенный массив:
pSubArr = hb_arrayGetItemPtr( pArray, ul );
ulLen2 = hb_arrayLen( pSubArr );
for( ul2 = 1; ul2 <= ulLen2; ul2++ ) {
// Вот так мы извлекаем float число:
myfloatNum = (float) hb_arrayGetND( pSubArr, ul2 );
// Далее надо вставить эту myfloatNum в ваш aMt
...
}
}


Если размерность aMt переменная, то для него надо предварительно зарезервировать место с помощью hb_xgrab примерно так:
aMt = (float**) hb_xgrab( sizeof(float) * m * n );

Если m и n - константы, то проще:
float aMt[m][n];

Ну а с возвратом ( aResenja) - похожая операция.

Создается массив:

PHB_ITEM aMetr = hb_itemArrayNew( m );
Потом для каждого элемента создается вложенный масиив и уже в каждый его элемент засовывается число.

Смотрите примеры в текстах Harbour, HwGUI

Спасибо: 1 
ПрофильЦитата Ответить
moderator


Пост N: 1603
Зарегистрирован: 06.07.06
ссылка на сообщение  Отправлено: 23.04.24 09:31. Заголовок: А можно, наверное, и..


А можно, наверное, и не создавать aMt и не заполнять его из pArray в цикле, а просто везде в программе вместо aMt[x][y] писать:


(float) hb_arrayGetND( hb_arrayGetItemPtr( pArray, x+1 ), y+1 );

Спасибо: 1 
ПрофильЦитата Ответить
Администратор




Пост N: 4161
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 23.04.24 09:45. Заголовок: Обращение к элемента..


Обращение к элементам массива aMatr[i, j] (aMt):

PHB_ITEM pArray = hb_param( 1, HB_IT_ARRAY );
PHB_ITEM pSub = hb_arrayGetItemPtr( pArray, i ); // подмассив

HB_LONG ll = hb_arrayGetNL( pSub, j );
или (зависит от типа данных)
double dd = hb_arrayGetND( pSub, j );

элементы массива нумеруются с единицы

Создание массива m*n:

   PHB_ITEM pRet = hb_itemArrayNew( m ), pSubArray; 

for( i = 1; i <= m; i ++)
{
pSubArray = hb_itemArrayNew( n );
for( j = 1; j <= n; j ++)
{
hb_arraySetNI( pSubArray, j, ll );
или
hb_arraySetND( pSubArray, j, dd );
}
hb_arraySet( pArray, i, pSubArray );
hb_itemRelease( pSubArray );
}



Возврат массива

hb_itemReturnRelease( pRet );

Спасибо: 1 
ПрофильЦитата Ответить





Пост N: 20
Зарегистрирован: 27.08.23
ссылка на сообщение  Отправлено: 23.04.24 13:59. Заголовок: Благодарность


Благодаря очень подробному объяснению Александра и Паши, подкрепленному соответствующими примерами, я понял, как работает передача и возврат многомерных матриц Hrb/C! Теперь я могу продолжать работать.
Большое спасибо всем, кто помог мне решить эту проблему!

P.S.
«Array» на сербском языке называется «матрица». Как правильно сказать по-русски - "матрица" или "массив" ?

Спасибо: 0 
ПрофильЦитата Ответить
moderator


Пост N: 1604
Зарегистрирован: 06.07.06
ссылка на сообщение  Отправлено: 23.04.24 14:28. Заголовок: Матрица (двумерный м..


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

Спасибо: 1 
ПрофильЦитата Ответить





Пост N: 21
Зарегистрирован: 27.08.23
ссылка на сообщение  Отправлено: 30.04.24 21:50. Заголовок: Проблема фокуса


Мне удалось перевести на C часть программы, написанную на BASIC, содержащую большое количество операторов GOTO, и она работает хорошо и корректно.
Но я столкнулся с новой проблемой: я не могу получать фокус там, где хочу. Я использую функцию hwg_SetFocus(), но она работает не так, как я бы хотел. Вот в чем дело - когда я запускаю часть своей программы, содержащую окно, то внутри окна BROWSE с двумерным массивом и под таблицей (внутри окна) три клавиши/кнопки, фокус всегда на первой клавише , и я бы хотел, чтобы оно было в BROWSE.
Итак, я попробовал следующее:

1) INIT DIALOG oDlg TITLE "Унос коефицијената система једначина " + Any2Str(n) + " x " + Any2Str(n) ;
AT 0, 0 SIZE nSirinaP, nVisinaP NOEXIT ICON oIcon ;
ON INIT { || oBtn2:Enabled:=.F., hwg_SetFocus(oBrwArr:handle ) } ;
STYLE WS_DLGFRAME + WS_SYSMENU + DS_CENTER

@ 0, 0 BROWSE oBrwArr ARRAY ;
STYLE WS_VSCROLL + WS_HSCROLL ;
SIZE nSirinaT, nVisinaT
....
....
....
@ 10, nVisinaP-70 BUTTON oBtn1 CAPTION "Реши систем" SIZE 100, 32 ON CLICK { || ResiSistem( oBrwArr, n ), oBtn2:Enabled:=.T. } FONT oFontBtn ;
TOOLTIP "Решавање система од " + ;
Any2Str(n) + IIF( n < 5, " једначине ", " једначина " ) + "са " + Any2Str(n) + IIF( n < 5, " непознате.", " непознатих." )
@ 120, nVisinaP-70 BUTTON oBtn2 CAPTION "Штампај" SIZE 100, 32 ON CLICK { || Stampa( oBrwArr, n ) } FONT oFontBtn ;
TOOLTIP "Штампање резултата прорачуна."

@ nSirinaP-110, nVisinaP-70 BUTTON oBtn3 CAPTION "Излаз" SIZE 100, 32 ON CLICK { || oDlg:Close() } FONT oFontBtn ;
TOOLTIP "Затварање табеле и повратак у Главни мени."

oDlg:Activate()
(Фокус находится на клавише oBtn1.)

2) .....
.....
.....

hwg_SetFocus(oBrwArr:handle )
oDlg:Activate()
(Фокус все еще находится на клавише oBtn1.)

3) .....
.....
.....
ACTIVATE DIALOG oDlg ON ACTIVATE { || hwg_SetFocus( oBrwArr:handle ) }
(Фокус все еще находится на клавише oBtn1.)

А потом я увидел, что не знаю, как получать фокус на oBrwArr, поэтому решил обратиться за помощью...

Спасибо: 0 
ПрофильЦитата Ответить
moderator


Пост N: 1608
Зарегистрирован: 06.07.06
ссылка на сообщение  Отправлено: Сегодня 10:03. Заголовок: Вставьте строку: oBr..


Вставьте строку:
oBrwArr:lInFocus := .T.

Спасибо: 1 
ПрофильЦитата Ответить





Пост N: 22
Зарегистрирован: 27.08.23
ссылка на сообщение  Отправлено: Сегодня 16:44. Заголовок: Проблема фокуса


Я вставил строку:
oBrwArr:lInFocus := .T.
и программа теперь работает так, как я хотел. Спасибо, alkresin!

Спасибо: 0 
ПрофильЦитата Ответить
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 256
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет