Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 23.07.2008, 18:17   #1
terminadoor
Пользователь
 
Регистрация: 26.06.2008
Сообщений: 86
По умолчанию ёщё одна задача

Задача: дана строка s, которая состоит из знаков +,-,*,/ и цифр. Вичислить значение примера. Например: 25+7 и ответ - 32.Помогите с алгоритмом. Думал сделать так: пока символ в строке s (s<>'-')or(s<>'+')or(s<>'*')or(S<>'/') ,будет цифра, заносим в одну переменную, знак в другую,второе число аналогично в третью. Потом вичисляем значения етого примера и.т.д. Но у меня всёравно не виходит.
Помогите пожалуйста. код:
Код:
program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils;
var s,s1,s2,s3,s4:string;
var a:array[1..100] of string;
var i,k,l,m:integer;
begin
readln(s);
i:=0;
k:=1;
l:=1;
for i:=1 to length(s) do begin
if (s[i]<>'+') or (s[i]<>'-') then s2:=s2+s[i] else begin
s3:=s3+s[i];
k:=i;
K:=k+1;
for l:=k to length(s) do begin
if (s[i]<>'+') or (s[i]<>'-') then s4:=s4+s[i]
end;
end;
end;
writeln(s2);
writeln(s3);
writeln(s4);
readln;
end.
TerMinAdoOR
terminadoor вне форума Ответить с цитированием
Старый 23.07.2008, 18:49   #2
Карась
Участник клуба
 
Аватар для Карась
 
Регистрация: 26.10.2007
Сообщений: 1,244
По умолчанию

Реение в лоб и прям в браузере:

Код:
Var A, B, I : Integer;
      Operation : Byte;
      S, Temp : String;

Begin
For I := 1 To Length(S) Do
Begin
// Оределяем действие над числами
If S[I] = '+' Then Operation := 1;
If S[I] = '-' Then Operation := 2;
If S[I] = '*' Then Operation := 3;
If S[I] = '/' Then Operation := 4;

// Заносим числа в переменые A и B
If S[I] = (Цифре) Then 
   Begin
      Temp := Temp + S[I]; Continue; 
   End
Else 
    Begin
       If B = 0 Then Begin A := StrToInt(Temp); Temp := ''; Continue; End;
       B := StrToInt(Temp);
       Break;
    End;
End;

// Выводим результат.
Case Operation of 
   1 : Writeln(A + B);
   2 : Writeln(A - B);
   3 : Writeln(A * B);
   4 : Writeln(A / B);

End.
Умом Россию не понять, пока не выпито ноль пять,
А если выпито ноль пять всё делом кажется не хитрым,
Попытка глубже понимать уже попахивает литром...
Карась вне форума Ответить с цитированием
Старый 23.07.2008, 18:56   #3
terminadoor
Пользователь
 
Регистрация: 26.06.2008
Сообщений: 86
По умолчанию

Карась,ето не тот алгоритм. Сам проверь: введи 5+2 и вместо 7 имеешь 5. В чём проблема?
TerMinAdoOR
terminadoor вне форума Ответить с цитированием
Старый 23.07.2008, 19:00   #4
Карась
Участник клуба
 
Аватар для Карась
 
Регистрация: 26.10.2007
Сообщений: 1,244
По умолчанию

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

И всёже яего отладил... считает правильно..... (задумка была для прстой формулы)
Умом Россию не понять, пока не выпито ноль пять,
А если выпито ноль пять всё делом кажется не хитрым,
Попытка глубже понимать уже попахивает литром...

Последний раз редактировалось Карась; 23.07.2008 в 19:02.
Карась вне форума Ответить с цитированием
Старый 23.07.2008, 19:05   #5
terminadoor
Пользователь
 
Регистрация: 26.06.2008
Сообщений: 86
По умолчанию

Хорошо. Но заработает твоя прога, если ввести 2+4+3+5? Можешь готовий код дать?
TerMinAdoOR
terminadoor вне форума Ответить с цитированием
Старый 23.07.2008, 19:18   #6
Карась
Участник клуба
 
Аватар для Карась
 
Регистрация: 26.10.2007
Сообщений: 1,244
По умолчанию

Цитата:
Сообщение от terminadoor Посмотреть сообщение
Хорошо. Но заработает твоя прога, если ввести 2+4+3+5? Можешь готовий код дать?
Она работает только для формул типа "A + B".
Для формул типа "A + B + C + ..... + n" надо создавать массив самих переменных и массив действий над ними.....
Ну и конечно в цикле пропускать обработку подсчёта конечного результата....

Цитата:
Можешь готовий код дать?
готовый код чего? Он практически весь во втором посте.

адд: но это в лоб. По уму надо сидеть и думать как разместить в одном цикле и как всё это оптимизировать....
Умом Россию не понять, пока не выпито ноль пять,
А если выпито ноль пять всё делом кажется не хитрым,
Попытка глубже понимать уже попахивает литром...
Карась вне форума Ответить с цитированием
Старый 23.07.2008, 19:26   #7
Greblin
Меркантильный кю
Участник клуба
 
Аватар для Greblin
 
Регистрация: 02.02.2008
Сообщений: 1,001
По умолчанию

Вот обсуждалось на форуме. Тут пример есть, а сам алгоритм посмотри в нете по теме обратнаая польская нотация
Росли вроде умными, выросли дурнями... (c)А.Васильев
Greblin вне форума Ответить с цитированием
Старый 23.07.2008, 20:52   #8
Игорь007
Пользователь Подтвердите свой е-майл
 
Аватар для Игорь007
 
Регистрация: 30.05.2008
Сообщений: 96
По умолчанию

Можете посмотреть еще и здесь.
Игорь007 вне форума Ответить с цитированием
Старый 23.07.2008, 21:17   #9
Mixasik
New Delphi Coder
Форумчанин Подтвердите свой е-майл
 
Аватар для Mixasik
 
Регистрация: 20.07.2008
Сообщений: 874
По умолчанию

Код:
  TRec = record
    num : real;
    znak : string
  end;
  TMas = array of Trec;
------------------
procedure Createarray(var st : string; var mas ; TMas);
var i : word; k :string;
begin
  i :=0;
  setlength(mas,length(mas)+1);
  while (i<length(st))and(st<>'+')and(st<>'-');
    begin
      inc(i);
      k := k + st[i];
    end;
  mas[length(mas)].num := strtofloat(k);
  if i <> length(st) then
    mas[length(mas)].znak := st[i];
  delete(st,1,length(k)+1);
  if length(st)<>0 then
    createarray(st,mas);
end;
Вот прям в браузере набросал создастся массив содержащий в себе число и знак(+,-), потом когда все это будет надо последовательно выполнить операции и все, последний элемент пустой(то есть число но последующего знака нет). С массивом удобно работать, но можно сделать отдельно массив с числами и знаками + для деления и умножения надо учесть что они первыми делаются но это уже легко(если число и знак в одном массиве - один задуман специально)!
Страх это слабость и потому, кто испугался уже побежден.
Mixasik вне форума Ответить с цитированием
Старый 23.07.2008, 22:50   #10
Olympian
Форумчанин
 
Аватар для Olympian
 
Регистрация: 06.06.2008
Сообщений: 105
По умолчанию

Код:
#include <stdio.h>
#include <conio.h>

#define NUM 1
#define OPER 2
#define ST_END 1
#define ST_OPER 2
#define ST_NUM 3
#define ERRORINEXPR 14812

/* Tip lineinogo spiska */
typedef struct tagTLIST TLIST;
struct tagTLIST
{
  int Type;
  char Oper;
  int Num;
  TLIST *Next;
};

/* Tip steka - Pervii prishel - pervii ushel */
typedef struct tagTSTACK
{
  TLIST *Beg;
} TSTACK;

/* Pishem element v nachalo */
int Push( TSTACK *S, TLIST L )
{
  TLIST *tmp;
  if (S->Beg == NULL)
  {
    S->Beg = new TLIST;  
    if (S->Beg == NULL)
      return 1;

    S->Beg->Type = L.Type;
    if (L.Type == OPER)
      S->Beg->Oper = L.Oper;
    else
      S->Beg->Num = L.Num;
    S->Beg->Next = NULL;
    return 0;
  }
  tmp = new TLIST;  
  if (tmp == NULL)
    return 1;

  tmp->Type = L.Type;
  if (L.Type == OPER)
    tmp->Oper = L.Oper;
  else
    tmp->Num = L.Num;
  tmp->Next = S->Beg;
  S->Beg = tmp;
  return 0;
}

/* Chitaem iz nachala */
TLIST Pop( TSTACK *S )
{
  TLIST tmp = {0, 0, 0, NULL};
  TLIST *tmp2;

  if (S->Beg == NULL)
    return tmp;
  
  tmp = *S->Beg;
  tmp.Next = NULL;
  tmp2 = S->Beg;
  S->Beg = tmp2->Next;
  delete tmp2;

  return tmp;
}

/* Poluchaem prioritet operacii */
int GetPrior( char Op )
{
  switch (Op)
  {
  case '+':
  case '-':
    return 1;
  case '*':
    return 2;
  }
  return -1;
}

void DoOper( TSTACK *N, TSTACK *O )
{
  TLIST N1, N2, Op;
  /* Schitivaem operaciu */
  Op = Pop(O);

  /* Schitivaem chisla */
  N1 = Pop(N);
  N2 = Pop(N);

  /* Vipolnaem */
  switch (Op.Oper)
  {
  case '+':
    N2.Num += N1.Num;
    break;
  case '-':
    N2.Num -= N1.Num;
    break;
  case '*':
    N2.Num *= N1.Num;
    break;
  }
  /* Rezultat na stek chisel */
  Push(N, N2);
}

/* Vipolnaem vse operacii na steke s prioritetom >= tekushego */
void DropOpers( TSTACK *N, TSTACK *O, int Prior )
{
  TLIST Op;
  Op = Pop(O);

  while (Op.Type != 0 && GetPrior(Op.Oper) >= Prior)
  {
    Push(O, Op);
    DoOper(N, O);  
    Op = Pop(O);
  }
  if (Op.Type != 0)
    Push(O, Op);

}

/* Schitaem virazhenie */
int Calc( char *expr )
{
  TSTACK N = {NULL}, O = {NULL};
  TLIST Cur;
  int State = ST_NUM;
  int Num;
  char Op;
  char Symb;
  int i = 0;


  while (State != ST_END)
  {
    /* Ojidaem chislo */
    if (State == ST_NUM)
    {
      /* Chitaem chislo */
      Num = 0;
      Symb = expr[i];      
      
      /* Propuskaem probeli */
      while (Symb == ' ')
      {
   
        Symb = expr[++i];
      }
      /* Schitivaem chislo po cifram */
      while (Symb >= '0' && Symb <= '9')
      {
        Num *= 10;
        Num += Symb - '0';
        i++;
        Symb = expr[i];
      }

      /* Dobavlaem v stek chisel */
      Cur.Next = NULL;
      Cur.Num = Num;
      Cur.Type = NUM;
      Push(&N, Cur);

      /* Esli konec stroki */
      if (Symb == 0)
      {
        /* Vipolnaem vse ostavshiesa operacii */
        DropOpers(&N, &O, 0);
        Cur = Pop(&O);
        /* Esli ostalis operacii - oshibka */
        if (Cur.Type != 0)
          return ERRORINEXPR;
        return N.Beg->Num;
      }

      /* Esli lishnii simvol - oshibka */
      if (Symb != ' ' && Symb != '+' && Symb != '-' && Symb != '*')
        return ERRORINEXPR;          
      /* Perehod k operacii */
      State = ST_OPER;
    }

    /* Ojidaem operaciu */
    if (State == ST_OPER)
    {
      /* Propusk probelov i chtenie operacii */
      Symb = expr[i++];      

      while (Symb == ' ')
        Symb = expr[i++];

      /* Proverka operacii, elsi ne operacia-  oshibka */
      if (Symb == '+' || Symb == '-' || Symb == '*')
        Op = Symb;
      else
      {
        if (Symb == 0)
        {
          DropOpers(&N, &O, 0);
          Cur = Pop(&O);
          if (Cur.Type != 0)
            return ERRORINEXPR;
          return N.Beg->Num;
        } 
        return ERRORINEXPR;
      }
      Cur.Next = NULL;
      Cur.Oper = Op;
      Cur.Type = OPER;


      /* Vipolnaem vse operacii s prior. >= tekushei */
      DropOpers(&N, &O, GetPrior(Cur.Oper));
                       
      /* Pishem operaciu v stek */
      Push(&O, Cur);
      /* Perehod k cifre */
      State =ST_NUM;
    }                
  }
  return 1;
}

int ReadStr( char *S, int N )
{
  int i = 0;
  char C;

  while ((C = getchar()) != '\n' && i++ < N)
    *S++ = C; 
  *S = 0;
  return i;
}
 

void main( void )
{
  int res;
  char Expression[300];

  printf("Vvedite virazenie\n");
  ReadStr(Expression, 300);
  res = Calc(Expression);
  if (res != ERRORINEXPR)
    printf("%i", res);
  else
    printf("Oshibka vvoda!");
  while (!kbhit())
    ;
}
Вот мой вариант разбора выражения. Работает 100% с целыми числами и знаками +/-/*//. Алгоритм стандартный - автомат с 4 состояниями:
1)Ожидание цифры(открыв. скобки в полном варианте)
2)Ожидание операции
3)ошибка
4)Выход
Olympian вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
еще одна задачка koston Помощь студентам 4 09.04.2008 18:43
Вот ещё одна,самая сложная: felice Паскаль, Turbo Pascal, PascalABC.NET 4 03.02.2008 17:21
Еще одна задача felice Паскаль, Turbo Pascal, PascalABC.NET 2 03.02.2008 14:32
еще одна задача в BP Jasper Паскаль, Turbo Pascal, PascalABC.NET 2 05.12.2006 15:13