KMA
Долгожитель
|
Перед тем, как отправить сообщение, обязательно просматривайте его содержимое, или хотя бы после того как отправили это сообщение посмотрите насколько правильно оно у вас отображается. Если ваше сообщение не приемле (т. е. видны крякобразы, непонятные символы) или выделено курсивом то, что не требовалось, то все сообщения впредь удаляются модераторами. Поэтому у вас два выбора: 1) Пишите все так, как надо, т. е. по правилам и получаете помощь; 2) Либо, вообще ничего не пишите, т. к. Вас не удовлетворяют наши правила.
|
Всего сообщений: 940 | Присоединился: декабрь 2005 | Отправлено: 19 фев. 2008 17:32 | IP
|
|
ewgen
Новичок
|
пардон конечно, не обратил внимания, впредь буду внимательным. И всё же помогите мне с задачей: нужно все цифры в строке сложить если между ними '+' и вычесть если '-', буквы игнорировать, если идут две подряд цифры, то воспринимать их как 2-х значное число; вот мои наработки: представил автомат, во 2-ое состояние вхожу если введены цифры иначе иду в 3-е(ошибка), далее остаюсь во втором если в строке цифра и перехожу в 4-ое если в строке'+' или в 5-ое если '-'. Из 4-ого и 5-ого перехожу обратно во 2-ое если текущий символ - цифра. currentNum - текущее значение, result - сумма begin result:=0; currentNum:=0; writeln('введите строку ');readln(st); n:=length(st); flag:=false; s:=1; while flag=true do begin case s of 1: begin if (st[ i ]='1') or (st[ i ]='2') then s:=2 currentNum:=val st[ i ]; else s:=3; writeln('error'); end; 2: begin {currentNum:=val(st[ i ]); result:=result+currentNum;z} if (st[ i ]='1') or (st[ i ]='2') then s:=2; begin if(st[ i ]='+') then s:= 4 end; begin if(st[ i ]='-') then s:= 5 end ; end; 3:flag:=true; end; end; end. KMA: еще раз, повторяю, что записывать [ i ] надо только так (т. е. с пробелами по бокам). Иначе, это читается как выделить курсивом, и код уже хуже воспринимается. (Сообщение отредактировал KMA 19 фев. 2008 23:52)
|
Всего сообщений: 6 | Присоединился: февраль 2008 | Отправлено: 19 фев. 2008 22:53 | IP
|
|
KMA
Долгожитель
|
Погоди, и чего ты добьешься своими переходами и автоматом? Давай я сделаю проще, может по времени это и займет больше, но суть от этого в принципе не поменяется. Вначале уберем весь "мусор", т. е. все буквы, и ненужные нам символы. В итоге у тебя получиться новая строка, красивая строка, вот функция, которая очищается строку от всякого мусора (я ее так и назвал, удалить мусор ):
Code Sample:
{возвращает строку содержащую только цифры и унарные операции сложения и вычитания} function deleteTrash (st: string): string; const number=['0'..'9']; var i, j: byte; s: string; Begin j:=0; s:=''; for i:=1 to length(st) do if (st[ i ] in number) or (st[ i ] ='+') or (st[ i ] ='-') then begin inc(j); {копирует символ, если он "правильный"} s:=s+st[ i ] end; deleteTrash:=s End;
В итоге, после применения этой процедуры, у тебя в строке не останется мусора, но остается не решенным вопрос о повторяющихся знаках (и о знаках в конце и начале). Как их удалить, смотри ниже (я оставляю последний знак, например, в последовательности знаков +--+--+, последний знак +, поэтому он и останется).
Code Sample:
function trimSingles(st:string): string; var i: byte; s: string; Begin //уберем знаки с конца i:=0; while (st[length(st)-i] in singles) and (i<=length(st)) do inc (i); st:=copy(st, 1, length(st)-i); //удаляем знаки с начала i:=1; while (st[ i ] in singles) and (i<=length(st)) do inc(i); if i=length(st) //если строка из знаков then trimSingles:='' else // если строка не из одних знаков begin s:=''; while i<=length(st) do if (st[ i ] in singles) and (st [i+1] in singles) then //проверяем на подряд идущие знаки begin //движемся пока не найдем конец знака inc(i); while (st[ i ] in singles) and (i<=length(st)) do inc (i); s:=s+st[i-1] //присвоим последний знак end else begin s:=s+st[ i ]; inc(i) end; trimSingles:=s; end; End;
Я конечно запихал константу number в const функции, однако, прошу, учти, что ее нужно вынести на уровень глобальных констант... и еще добавь такую константу: singles=['+', '-']; Тогда все будет работать. Теперь смотри, в итоге, чтобы получить чистенькую и готовую к обработке строку нужно сделать так:
Code Sample:
st:=trimSingles(deleteTrash(st));
Теперь у тебя чистенькая, без глюков строчка. Осталось ее обработать, а это дело плевое.
Code Sample:
function summInText(st: string): integer; var i, _beginN: byte; _currentNum: integer; // текущее число _result: integer; // результат _singleFlag: boolean; // знак _errCode: integer; //код ошибки Begin _beginN:=1; _currentNum:=0; _result:=0; _singleFlag:=true; for i:=1 to length(st) do if (st[ i ] in singles ) then begin val(copy(st, _beginN, i-_beginN), _currentNum, _errCode); if not _singleFlag then _currentNum:=_currentNum*(-1); _result:=_result+_currentNum; // "обнулим" переменные _beginN:=i+1; if st[ i ]='+' then _singleFlag:=true else _singleFlag:=false end; // повторим для последней цифры val(copy(st, _beginN, length(st)-_beginN+1), _currentNum, _errCode); if not _singleFlag then _currentNum:=_currentNum*(-1); _result:=_result+_currentNum; summInText:=_result End;
В итоге вся твоя задача свелась к вводу данных и одной строки:
Code Sample:
writeLn(summInText(trimSingles(deleteTrash(s))));
Мое решение не претендует на самое быстрое и возможно красивое, но оно более или менее жизненно. Во первых, если бы ты использовал переходы, то конечно уменьшил бы в три раза количество циклов, но сколько было бы у тебя условий??? А каждый лишний шаг в цикле утяжеляет программу. Конечно, можно многое подредактировать, и где-то написать лучше, но моя задача была показать тебе алгоритм и его решение. Плюсом оптимизировать не стал, дабы не потерялась читаемость задачи, где мог, в сложных местах ставил комментарии. Твое решение сложно тем, что у тебя много-много будет условий. Захочешь свой вариант, давай попробуем разобрать его. Только скажи.
|
Всего сообщений: 940 | Присоединился: декабрь 2005 | Отправлено: 20 фев. 2008 2:10 | IP
|
|
ewgen
Новичок
|
Cпасибо за подсказку, идея мне понравилась. Я еще подумаю над своим способом ( от нас требуют почему то именно автомат, возможно это связано с тем что в этом семестре у нас курсовой - написать компилятор а там должен быть кусок программы который итерпритирует определённые последовательности символов как команды это как я понимаю может я и не прав ), если возникнут трудности я напишу. И еще, что бы вы посоветовали для повышения моей квалификации ( в программировании я не силен а хотелось бы достичь более высоких результатов ), помимо литературы может еще упражнения какие или разобранные примеры решенных задач.
|
Всего сообщений: 6 | Присоединился: февраль 2008 | Отправлено: 20 фев. 2008 13:06 | IP
|
|
KMA
Долгожитель
|
Учи С++ и разбирай исходник ядра Линукса. По поводу компиляторов и т. п., всегда можно посмотреть исходники внешняя ссылка удалена. Конечно, базовые знания надо иметь, и такого рода задачи тоже решать. Но это все дело опыта и старания. Начни с мелких задач, потом начинай писать крупные проекты, учись разбивать задачу на отдельные части, писать все процедурно, много много читать и разбирать уйму кодов. Я здесь то сижу ради того, чтобы паскаль не забывать и хоть иногда на нем писать. Всяко что-нибудь пригодиться.
|
Всего сообщений: 940 | Присоединился: декабрь 2005 | Отправлено: 20 фев. 2008 19:35 | IP
|
|
ewgen
Новичок
|
Благодарю за совет.
|
Всего сообщений: 6 | Присоединился: февраль 2008 | Отправлено: 21 фев. 2008 7:55 | IP
|
|
Guest
Новичок
|
Всем привет и с праздником! У кого-нить есть идеи по решению этой задачи. Задача: Имеется n населенных пунктов, пронумерованных от 1 до n. Некоторые пары пунктов соединены дорогами. Определить, можно ли попасть по этим дорогам из 1-го пункта в n-й. Информация о дорогах задается в виде последовательности пар чисел i и j (i<j), указывающих, что i-й и j-й пункты соединены дорогой. Заранее СПАСИБО!
|
Всего сообщений: Нет | Присоединился: Never | Отправлено: 23 фев. 2008 14:10 | IP
|
|
bekas
Долгожитель
|
#include "stdafx.h" #define LEN 20 int path [ LEN * 2 ]; // Симметричная матрица связности: graph [ i ] [ j ] == 1, если есть путь из i в j // В данном случае задано 7 вершин, пронумерованных от 0 до 6 chargraph [ LEN ] [ LEN ] = { {0,1,0,0,0,1,1}, {1,0,1,0,0,0,0}, {0,1,0,1,1,0,0}, {0,0,1,0,1,0,0}, {0,0,1,1,0,1,1}, {1,0,0,0,1,0,0}, {1,0,0,0,1,0,0} }; char visited [ LEN ]; int index, n = 7; bool searchR(int v, int w) { int t; if(v == w) return true; visited [ v ] = 1; for(t = 0; t < n; ++t) { if(graph [ v ] [ t ] == 0 || visited [ t ]) continue; if(searchR(t, w)) { if(index == 0) { path [ index ] = t; path [ index + 1 ] = v; index += 2; } else { path [ index++ ] = v; } return true; } } return false; } void getpath(int n1, int n2) { int i; printf("PATH: %d-%d\n", n1, n2); if(n1 < 0 || n1 >= n || n2 < 0 || n2 >= n) { printf("Bad param!\n" ) ; return; } for(i = index = 0; i < n; ++i) { visited [ i ] = 0; } if(searchR(n2, n1)) { printf("%d", path [ 0 ] ) ; for(n1 = 1; n1 < index; ++n1) { printf("-%d", path [ n1 ] ) ; } printf("\n" ) ; } else { printf("Path not found!\n" ) ; } } int main(int argc, char* argv[]) { // Делается попытка найти путь из вершины 6 в вершину 2 (не обязательно ближайший) getpath(6, 2); // Делается попытка найти путь из вершины 2 в вершину 6 (не обязательно совпадающий с 6-2) getpath(2, 6); return 0; } P.S. Не заметил, что эта тема по Паскалю, но думаю разницы особой нет - главное в самом алгоритме... (Сообщение отредактировал bekas 23 фев. 2008 16:34)
|
Всего сообщений: 379 | Присоединился: январь 2006 | Отправлено: 23 фев. 2008 16:24 | IP
|
|
Guest
Новичок
|
Да забыл сказать, что ее с помощью рекурсии нужно решить! А здесь я как понял с помощью графа.Но все равно спасибо! Если кто знает как в паскале с помощью рекурсии решить напишите пожалуйста! Спасибо!
|
Всего сообщений: Нет | Присоединился: Never | Отправлено: 23 фев. 2008 17:36 | IP
|
|
Siriusss
Новичок
|
Задача работает, не получается немного совсем. А может кардинально поменять ее решение - а времени на это нет. Не получается вывести значения xi, ПРИБЛИЖЕННЫЕ и точные значения функции в точках xi (i=0,1,29/4). __________________________________________________ program lin_inter; const h=0.0001;n=29; type mas=array[0..n]of real; var x,y,z,L:mas; a,b:real; i:integer; begin {Ввод значений функции с рассчитанным шагом на интервале} {a=3} write('a='); readln(a); {b=3.003} write('b='); readln(b); for i:=0 to n do begin x[ i ]:=a+i*h; y[ i ]:=54*sin(x[ i ]/3); - функция моя writeln('x[', i ,']=',x[ i ]:10:4,', f(x)=',y[ i ]:10:6,';'); end; writeln; {Вычисление значения функции в точках z i-тое с помощью линейной интерполяции} for i:=0 to n-1 do begin z[ i ]:=3+i*h+(i mod 4+1)/5*h; - задание точек L[ i ]:=y[ i ]+(z[ i ]-x[ i] )*(y[ i+1 ]-y[ i ])/h; - интерполяция - вычисление приближенного решения end; for i:=0 to n do begin if ((i=0)or(i=1)) then writeln('x[', i ,']=',x[ i ]:10:4,', точное значение функции f(x)=',y[ i ]:10:6,';',' приближенное значение функции f(x)=',L[ i ]:10:6); end; writeln('x[',29/4:6:4,']=',a+29/4*h:10:4,', f(x)=',54*sin((a+29/4*h)/3):10:6); readln; end. __________________________________________________ Не получается вывести приближенное значение функции в точке 29/4 и как следует вывести его же точное значение. Очень хочется доделать эту задачку... (Сообщение отредактировал Siriusss 23 фев. 2008 23:29)
|
Всего сообщений: 28 | Присоединился: апрель 2007 | Отправлено: 23 фев. 2008 19:40 | IP
|
|
|