Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
coder0
26 / 18 / 10
Регистрация: 26.09.2018
Сообщений: 128
1

Проблема с указателями

03.11.2018, 21:50. Просмотров 405. Ответов 16
Метки нет (Все метки)

Привет! Есть такой калькулятор:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <stdio.h>
#include "string2.h"
/////////////////////////////////////////////////
int firstpos(char c,char* str,int beg){
int i;
 for(i=beg;i<length(str);++i)
  if(str[i]==c)return i;
return -1;
}
int endpos(char c,char* str){
int i;
 for(i=length(str)-1;i>-1;--i)
  if(str[i]==c)return i;
return -1;
}
//////////////////////////////////////////////////
int calculate(char* expr){
char buffer[256];
int result=0,n=0;
int a=0,b=0;
 
 while((pos('(',expr)!=-1)and(pos(')',expr)!=-1)){
  copystr(buffer,IntToStr(calculate(copy(expr,pos('(',expr)+1,firstpos(')',expr,pos('(',expr))-pos('(',expr)-1))));
  n=pos('(',expr);
  _delete(expr,pos('(',expr),firstpos(')',expr,pos('(',expr))-pos('(',expr)+1);
  insert(buffer,expr,n);
 }
printf("%s\n",expr);
  if (pos('+',expr)!=-1) return calculate(copy(expr,0,endpos('+',expr))) + calculate(copy(expr,endpos('+',expr)+1,length(expr)-endpos('+',expr)-1));else
  if((pos('-',expr)!=-1)and
  ((expr[pos('-',expr)-1]>47)and(expr[pos('-',expr)-1]<58))
                        )return calculate(copy(expr,0,endpos('-',expr))) - calculate(copy(expr,endpos('-',expr)+1,length(expr)-endpos('-',expr)-1));else
  if (pos('*',expr)!=-1) return calculate(copy(expr,0,endpos('*',expr))) * calculate(copy(expr,endpos('*',expr)+1,length(expr)-endpos('*',expr)-1));else
  if (pos('/',expr)!=-1) return calculate(copy(expr,0,endpos('/',expr))) / calculate(copy(expr,endpos('/',expr)+1,length(expr)-endpos('/',expr)-1));else
  if (pos('^',expr)!=-1) return power(calculate(copy(expr,0,endpos('^',expr))),calculate(copy(expr,endpos('^',expr)+1,length(expr)-endpos('^',expr)-1)));else
   return StrToInt(expr);
}
///////////////////////////////////////////////////
void correct(char* s){
 int i;
 bool notcorrect=false;
 
for(i=0;i<length(s);++i)
  if(!(((s[i]>47)and(s[i]<58))or(s[i]=='+')or(s[i]=='-')or(s[i]=='*')or(s[i]=='/')or(s[i]=='^')or(s[i]=='(')or(s[i]==')')or(s[i]=='='))){
   _delete(s,i,1);
   notcorrect=true;
  }
 
while(posstr(s,"-+",1)!=-1)
_delete(s,posstr(s,"-+",1)+1,1);//4-+1=4-1
 
while(posstr(s,")(",1)!=-1)
 insert("*",s,posstr(s,")(",1)+1);//(2)(3)=(2)*(3)
 
for(i=1;i<length(s);++i){
  if(s[i]='('){
    if((s[i-1]>47)and(s[i]<58))
      insert("*",s,i);//2(1+1)=2*(1+1)
  }
     if(s[i]=')'){
       if((s[i+1]>47)and(s[i]<58))
         insert("*",s,i+2);//(1+1)2=(1+1)*2
     }
}
///======
if(pos('=',s)!=-1){
 if(calculate(copy(s,0,pos('=',s)-1))==calculate(copy(s,pos('=',s)+1,length(s)-pos('=',s))))
 printf("TRUE\n");else
 printf("FALSE\n");
}
///======
if(notcorrect)printf("Probarly you meaned: %s\n",s);
}
/////////////////////////////////////////////////////////////////////////
int main(){
 char exp[1024];
 while(true){
  gets(exp);
  if(length(exp)!=0){
     if(compare(exp,"q"))
         return 0;
     correct(exp);
     printf("%d\n",calculate(exp));
  }
 }
 return 0;
}
C
1
2
3
4
5
6
7
8
9
char* copy(char* source,int pos,int size){
char result[256];
int i;
 for(i=0;i<256;++i)result[i]=0;
 for(i=pos;i<pos+size;++i){
  result[i-pos]=source[i];
 }
return result;
}
И если закомментировать вызов функции correct то всё работает нормально, а если нет, то на экран выводится какая то ерунда. Судя по всему проблема в copy. Если заменить char result[256] на static char result[256], все еще хуже.
Если нужно могу выложить код insert-а _delete-а и т.д.

P.S На паскале работало
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.11.2018, 21:50
Ответы с готовыми решениями:

Путаница с указателями
#include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #define LEN 100 void new_line(char (**line), int n) {...

Задача с указателями
Помогите написать программу а) которая читает два Integer-числа и создать два указателя,которые...

Ошибка с указателями
Необходимо отсортировать одномерный массив. Написал функцию, но компилятор выдаёт ошибку в строке...

Работа с указателями
#define*_CRT_SECURE_NO_WARNINGS #include*&lt;stdio.h&gt; #include*&lt;malloc.h&gt; #include*&lt;stdlib.h&gt;...

Задача с указателями
Доброго времени. 1. Необходимо написать функцию int remGetMax(int**this); которая сохраняет...

16
coder0
26 / 18 / 10
Регистрация: 26.09.2018
Сообщений: 128
04.11.2018, 17:32  [ТС] 2
Что ж это? Паскаль круче си?
0
sharpey
363 / 153 / 37
Регистрация: 21.09.2008
Сообщений: 505
04.11.2018, 18:54 3
Выкладывайте первоисходники.

Добавлено через 1 минуту
Цитата Сообщение от coder0 Посмотреть сообщение
Что ж это? Паскаль круче си?
Не совсем. Благодаря строгой типизации сложнее "отстрелить себе ногу".
0
_SayHello
616 / 363 / 114
Регистрация: 30.07.2015
Сообщений: 1,281
04.11.2018, 19:22 4
coder0,
в функции
C
1
char* copy(char* source,int pos,int size)
вы объявляете локальный массив, возвращаете указатель на него. при этом при выходе из функции все локальный переменные уничтожаются, так что ваш указатель указывает куда-то. ВЫделяйте память в функции динамически функцией malloc.
Паскаль не круче/не хуже. Си позволяет более гибко работать с памятью.
0
coder0
26 / 18 / 10
Регистрация: 26.09.2018
Сообщений: 128
04.11.2018, 19:55  [ТС] 5
А можно как-нибудь без сторонних функций и библиотек?

Добавлено через 4 минуты
Просто не понимаю, как сделать так что-бы при выходе из функции память не замусоривалась, а static все совсем портит.
Глобальную переменную объявить?
0
_SayHello
616 / 363 / 114
Регистрация: 30.07.2015
Сообщений: 1,281
04.11.2018, 19:59 6
coder0, создай массив в main и передавай указатель на него в функцию. Что то типа того
C
1
2
3
4
5
void copy(char* src, char * dst, int pos, int size)
{
    for(int i= 0; i < size; i++)
       *(dst + i) = *(source+ i + pos);
}
А при чем тут static? У него совсем другое предназначение. Он тут и не поможет
0
coder0
26 / 18 / 10
Регистрация: 26.09.2018
Сообщений: 128
04.11.2018, 20:04  [ТС] 7
Ну получается результат передаётся в один из аргументов. Можно ли сделать так чтобы результат именно возвращался?
0
_SayHello
616 / 363 / 114
Регистрация: 30.07.2015
Сообщений: 1,281
04.11.2018, 20:08 8
coder0, написал выше - резервируй память.
0
coder0
26 / 18 / 10
Регистрация: 26.09.2018
Сообщений: 128
04.11.2018, 20:10  [ТС] 9
А средствами языка - никак? Обязятельно для этого подключать либы?
0
_SayHello
616 / 363 / 114
Регистрация: 30.07.2015
Сообщений: 1,281
04.11.2018, 20:18 10
coder0, ну вообще эта функция находится в стандартной библиотеке си stdlib
0
coder0
26 / 18 / 10
Регистрация: 26.09.2018
Сообщений: 128
04.11.2018, 20:20  [ТС] 11
Если результат будет возвращаться через аргумент, то надо будет очень сильно изменить calculate(char*). Код будет совсем ужасным.

Добавлено через 1 минуту
Ну хорошо. Тогда как работает malloc? Надо же знать как работает моя программа. Хотелось бы знать алгоритм malloc-а.
0
_SayHello
616 / 363 / 114
Регистрация: 30.07.2015
Сообщений: 1,281
04.11.2018, 20:30 12
coder0,
вы сами построили такие конструкции
C
1
copystr(buffer,IntToStr(calculate(copy(expr,pos('(',expr)+1,firstpos(')',expr,pos('(',expr))-pos('(',expr)-1))));
кто ж вас заставлял. Это красивости коду не придает, скорее наоборот.
вы же используете библиотеку stdio в чем проблема подключить stdlib?

Добавлено через 3 минуты
coder0, http://www.cplusplus.com/reference/cstdlib/malloc/
C
1
2
3
4
5
6
7
char* copy(char* source,int pos,int size)
{
    char * result = (char*)malloc(sizeof(char) * 256); 
    for(i=pos;i<pos+size;++i)
        result[i-pos]=source[i];
    return result;
}
0
coder0
26 / 18 / 10
Регистрация: 26.09.2018
Сообщений: 128
04.11.2018, 20:30  [ТС] 13
Вы меня убедили, но как printf делает свою работу я примерно представляю. А как malloc не знаю, только знаю как им пользоваться.
0
sharpey
363 / 153 / 37
Регистрация: 21.09.2008
Сообщений: 505
04.11.2018, 20:30 14
Цитата Сообщение от coder0 Посмотреть сообщение
Тогда как работает malloc? Надо же знать как работает моя программа. Хотелось бы знать алгоритм malloc-а.
Зачем здесь использовать кучу (heap), вызывая malloc()? Их же потом придётся всё равно отслеживать и возвращать через free().
Где обещанные Вами исходники на Паскале?
0
coder0
26 / 18 / 10
Регистрация: 26.09.2018
Сообщений: 128
05.11.2018, 00:03  [ТС] 15
да на пасцкале все точно также, я имел ввиду исходники функций для работы со строками типа strtoint insert delete posstr и т.д.

Добавлено через 38 секунд
просто на паскале не возникает проблем со всеми этими указателями

Добавлено через 5 минут
ну ладно, если Вы так хотите паскаля то вот:
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
uses Sysutils;
var exp:string;
 
function lastpos(c:char;var s:string):integer;
var i:integer;
begin
 result:=0;
 for i:=length(s) downto 1 do
  if s[i]=c then
   result:=i;
end;
function firstpos(c:char;var s:string;start:integer):integer;
var i:integer;
begin
 result:=0;
 if start>length(s)then exit;
 for i:=start to length(s) do
  if s[i]=c then
  begin
   result:=i;
   exit;
  end;
end;
 
function endpos(c:char;s:string):integer;
var i:integer;
begin
 result:=0;
for i:=length(s)downto 1 do
  if s[i]=c then begin
   result:=i;
   exit;
  end;
end;
 
function power(base,_power:integer):integer;
var buff,i:integer;
begin
 buff:=base;
 for i:=1 to _power-1 do
 base:=base*buff;
 if _power=0 then base:=1;
 result:=base;
end;
/////////////////////////////////////////////////////
function calculate(expr:string): integer;
var buffer:string;
    n:integer;
begin
 result:=0;
 
 while((pos('(',expr)<>0)and(pos(')',expr)<>0))do
 begin
  buffer:=IntToStr(calculate(copy(expr,lastpos('(',expr)+1,firstpos(')',expr,lastpos('(',expr))-lastpos('(',expr)-1)));
  n:=lastpos('(',expr);
  delete(expr,lastpos('(',expr),firstpos(')',expr,lastpos('(',expr))-lastpos('(',expr)+1);
  insert(buffer,expr,n);
 end;
 
  if(pos('+',expr)<>0) then result:=calculate(copy(expr,1,endpos('+',expr)-1))    +calculate(copy(expr,endpos('+',expr)+1,length(expr)-endpos('+',expr)))else
  if(pos('-',expr)<>0) and(expr[pos('-',expr)-1]in['0'..'9'])
                       then result:=calculate(copy(expr,1,endpos('-',expr)-1))    -calculate(copy(expr,endpos('-',expr)+1,length(expr)-endpos('-',expr)))else
  if(pos('*',expr)<>0) then result:=calculate(copy(expr,1,endpos('*',expr)-1))    *calculate(copy(expr,endpos('*',expr)+1,length(expr)-endpos('*',expr)))else
  if(pos('/',expr)<>0) then result:=calculate(copy(expr,1,endpos('/',expr)-1)) div calculate(copy(expr,endpos('/',expr)+1,length(expr)-endpos('/',expr)))else
  if(pos('^',expr)<>0) then result:=power(calculate(copy(expr,1,endpos('^',expr)-1)),calculate(copy(expr,endpos('^',expr)+1,length(expr)-endpos('^',expr))))else
  result:=StrToInt(expr);
 {
 if(pos('+',expr)<>0) then result:=calculate(copy(expr,1,pos('+',expr)-1))    +calculate(copy(expr,pos('+',expr)+1,length(expr)-pos('+',expr)))else
 if(pos('-',expr)<>0) and(expr[pos('-',expr)-1]in['0'..'9'])
                      then result:=calculate(copy(expr,1,pos('-',expr)-1))    -calculate(copy(expr,pos('-',expr)+1,length(expr)-pos('-',expr)))else
 if(pos('*',expr)<>0) then result:=calculate(copy(expr,1,pos('*',expr)-1))    *calculate(copy(expr,pos('*',expr)+1,length(expr)-pos('*',expr)))else
 if(pos('/',expr)<>0) then result:=calculate(copy(expr,1,pos('/',expr)-1)) div calculate(copy(expr,pos('/',expr)+1,length(expr)-pos('/',expr)))else
 if(pos('^',expr)<>0) then result:=power(calculate(copy(expr,1,pos('^',expr)-1)),calculate(copy(expr,pos('^',expr)+1,length(expr)-pos('^',expr))))else
 result:=StrToInt(expr);
 }
 
end;
////////////////////////////////////////////////////////////
function foundn(strin,source:string;begpos:integer):byte;
var
i,n:integer;
currents:string;
begin
  result:=0;
  if begpos>length(strin)-length(source)+1 then exit;
 
  for i:=begpos to length(strin)-length(source)+1 do
  begin
   currents:='';
   for n:=i to i+length(source)-1 do currents:=currents+strin[n];
   if currents=source then
   begin
   result:=i;
   exit;
   end;
  end;
end;
 
procedure correct(var s:string);
var i,x:integer;
    notcorrect:boolean;
begin
 notcorrect:=false;
for i:=1 to length(s)do
  if not(s[i] in ['0'..'9','+','-','*','/','^','(',')','='])then
  begin
   delete(s,i,1);
   notcorrect:=true;
  end;
 
while (foundn(s,'-+',1)<>0) do
 delete(s,foundn(s,'-+',1)+1,1);//4-+1=4-1
 
while (foundn(s,')(',1)<>0) do
 insert('*',s,foundn(s,')(',1)+1);//(2)(3)=(2)*(3)
 
for x:=1 to length(s)do
 if(s[x]='(')then
 begin
  if(s[x-1] in ['0'..'9'])then
   insert('*',s,x);//2(1+1)=2*(1+1)
 end else
 if(s[x]=')')then
  if(s[x+1] in ['0'..'9'])then
   insert('*',s,x+2);//2(1+1)=2*(1+1)
 
///======
if(pos('=',s)<>0)then
begin
 if(calculate(copy(s,1,pos('=',s)-1))=calculate(copy(s,pos('=',s)+1,length(s)-pos('=',s))))then
 writeln('TRUE')            else
 writeln('FALSE');
end;
///======
 
if notcorrect then writeln('Probarly you meaned: ',s);
end;
 
begin
 while true do
 begin
  readln(exp);
   if exp<>'' then
   begin
    correct(exp);
     if(pos('=',exp)=0)then
       writeln(calculate(exp));
   end;
 end;
end.
Добавлено через 3 часа 25 минут
Кривенько наверно, но решение я придумал:
C
1
2
3
4
5
6
7
8
char* copy(char* source,int pos,int size,char*addr){
int i;
 for(i=0;i<256;++i)addr[i]=0;
 for(i=pos;i<pos+size;++i){
  addr[i-pos]=source[i];
 }
return addr;
}
в main:
extern char buff[512] чтоб была доп память, и в вызовы copy добавить &buff[0] || buff.
Получается что мы для фун-ии резервируем память, но она при этом не только записывает результат в аргумент, но и возвращает его, при этом память не замусоривается. Так что не придется сильно изменять calculate.
0
sharpey
363 / 153 / 37
Регистрация: 21.09.2008
Сообщений: 505
05.11.2018, 11:37 16
coder0, третью строку в функции copy() можно заменить на
C
1
memset(addr, 0, 256);
Однако в Вашей функции copy нет проверок на корректность входных данных. Что будет, если индекс (номер позиции pos) будет больше длины строки? Что будет, если остаток строки (разность длины строки и индекса) будет меньше числа копируемых символов (параметр size)?
Цитата Сообщение от coder0 Посмотреть сообщение
extern char buff[512] чтоб была доп память, и в вызовы copy добавить &buff[0] || buff.
И в каком модуле Вы определяете эту дополнительную память? Это ошибка.
В Паскале длина строки строго меньше 256 символов, причём в нулевом индексе хранится длина строки. Можно ограничиться этим значением, либо использовать динамическое размещение строк в куче посредством malloc (а в случае нехватки перераспределить через realloc), не забыв по окончании освободить их через free(), иначе будет утечка памяти.
0
coder0
26 / 18 / 10
Регистрация: 26.09.2018
Сообщений: 128
06.11.2018, 22:34  [ТС] 17
Цитата Сообщение от sharpey Посмотреть сообщение
extern char buff[512] чтоб была доп память, и в вызовы copy добавить &buff[0] || buff.
Если переменная локальная то после выхода из функции результат кем-нибудь перезапишется, а так мы дадим функции память, которая не будет использоваться другими функциями и по адресу на который указывает указатель ничего не изменится. Есть например функция itoa, она работает также. Если результат просто будет выводится в addr, то придется сильно изменить calculate.

Добавлено через 8 минут
Цитата Сообщение от sharpey Посмотреть сообщение
malloc
Цитата Сообщение от sharpey Посмотреть сообщение
realloc
Цитата Сообщение от sharpey Посмотреть сообщение
free()
Не люблю подключать библиотеки, если без них можно обойтись, нравится по максимуму самому писать.
0
06.11.2018, 22:34
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.11.2018, 22:34

Не работает функция с указателями
Массив из 20 элементов, выводится автоматически, 2 функции: 1) считает пары рядом стоящих...

Быстрая сортировка с указателями
Здрауствуйте, подскажите пожадуйста, я сделал быструю сортировку с указателями, оно вроде работет -...

Обработка строк с указателями
Почему вот эта строчка(while(*w1)) не работает ?? , вроде *w1 это значение элемента по этому...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru