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

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

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

Восстановить пароль

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

Ответ
 
Опции темы Поиск в этой теме
Старый 27.11.2016, 14:00   #1
Pirat_bolot
Новичок
Джуниор
 
Регистрация: 26.11.2014
Сообщений: 1
Сообщение Разбить строку-выражение на токены (Си, VisualStudio)

Доброго времени суток!

Начал писать программку для вычисления значения выражения-строки. Усложнение в том, что аргументы могут быть больше, чем long (unsigned long), соответственно нужно использовать динамическое выделение памяти и сохранять каждый аргумент в качестве массива char.

В качестве математических символов могут быть использованы '(', ')', '+', '-', '*', '/'

P.S Все отрицательные числа окаймляются кавычками, для того, чтобы не было проблем при хранении отрицательных чисел, а также вычислении выражения в обратной польской записи (в проекте присутствует функция приведения отрицательных чисел к виду: (-11) -> (0-11) )
Если вы знаете менее костыльные способы работы с отрицательными числами в данном случае, пожалуйста поделитесь, буду очень благодарен!

Проблема заключается в том, что при вводе некоторых входных значений программа аварийно приостанавливается с сообщением:
Ошибка.jpg

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

Привожу код:

Код:
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

typedef struct
{
	int size;
	char *str;
}Str;

Str* createNewString();
void scanfStr(Str *s);
void printStr(Str* str1);
char **AddPtr(char **pp, int size, char *ptr);
char **create_Arr_ptr(Str* str1);
void correct_Negative_numbers(Str* str1);

int main(int argc, char* argv[])
{
	Str *line = createNewString();

	scanfStr(line);
	
	correct_Negative_numbers(line);

	char **mass = create_Arr_ptr(line);
	
	printStr(line);

	free(line->str);
	free(line);

	system("pause");
	return 0;
}

Str* createNewString()
{
	Str* s = (Str*)malloc(sizeof(Str));
	s->size = 1;
	s->str = (char*)calloc(s->size, sizeof(char));
	return s;
}

void scanfStr(Str *s)
{
	if (strlen(s->str) > 0) {
		free(s->str);
		s->size = 1;
		s->str = (char*)calloc(s->size, sizeof(char));
	}

	char c, previous_c;
	int length = 0;
	while ((c = getchar()) != '\n') {
		if (c != ' ' && c != '\t')
		{
			if (length + 1 > s->size) {
				s->size += 20;
				s->str = (char*)realloc(s->str, s->size);
			}
			s->str[length] = c;
			length++;
			previous_c = c;
		}

	}

	s->str[length] = '\0';
	s->size = length + 1;
	s->str = (char*)realloc(s->str, s->size);
}

char **AddPtr(char **pp, int size, char *str)
{
	if (size == 0) {
		pp = (char**)malloc(size + 1);
	}
	else {
		char **copy = (char**)malloc(size + 1);
		for (int i = 0; i < size; i++)
		{
			copy[i] = pp[i];
		}
		pp = copy;
	}

	pp[size] = (char*)malloc(sizeof(str) + 1); // Ошибка тут
	strcpy(pp[size], str);
	
	return pp;
}

void printStr(Str* str1)
{
	printf("%s\n", str1->str);
}

char **create_Arr_ptr(Str* str1)
{
unsigned int i = 0;
char *ptr = str1->str;
unsigned int size_of_arr_token = 0;
char **arr_tok = 0;
char *buffer = 0;

while (*(ptr + i) != '\0')
{
if (!isdigit(*(ptr + i)))
{
buffer = (char*)malloc(2);
strncpy_s(buffer, 2, ptr, 1);
buffer[1] = '\0';

arr_tok = AddPtr(arr_tok, size_of_arr_token, buffer);
size_of_arr_token++;

ptr = ptr + 1;
i = 0;
free(buffer);
}
else
{
while (isdigit(*(ptr + i)))
i++;

buffer = (char*)malloc(i + 1);
strncpy_s(buffer, i + 1, ptr, i);
buffer[i] = '\0';

arr_tok = AddPtr(arr_tok, size_of_arr_token, buffer);
size_of_arr_token++;

ptr = ptr + i;
i = 0;
free(buffer);
}
}

arr_tok = AddPtr(arr_tok, size_of_arr_token, "End");
size_of_arr_token++;

return arr_tok;
}

void correct_Negative_numbers(Str* str1)
{
	char *pointer;

	while ((pointer = strstr(str1->str, "(-")) != NULL)
	{
		if (str1->size == strlen(str1->str) + 1)
		{
			(str1->size)++;
			str1->str = (char*)realloc(str1->str, str1->size);
		}
		*((str1->str) + (str1->size - 1)) = '\0';
		*((str1->str) + (str1->size - 2)) = ' ';
		char bufferIn, bufferFrom;

		bufferIn = '0';
		pointer++;
		while (bufferIn != ' ')
		{
			bufferFrom = *pointer;
			*pointer = bufferIn;
			bufferIn = bufferFrom;
			pointer++;
		}
	}
}
Дополнительный вопрос: В функции AddPtr мы создаем временный указатель на массив указателей copy, который на 1 больше, чем pp. Затем мы копируем данные из pp в copy, присваиваем pp = copy. Получается, что где-то в памяти у нас остается массив, на который раньше указывал pp. По хорошему мы должны сделать так: free(pp), однако это действие затронет и copy, что неприемлемо. Можно как-то "безопасно" проделать этот трюк с освобождением неиспользуемой памяти?

Если будут любые замечания, то, пожалуйста, скажите! Постараюсь больше не совершать таких ошибок

Последний раз редактировалось Pirat_bolot; 27.11.2016 в 15:48.
Pirat_bolot вне форума Ответить с цитированием
Ответ


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

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Разбить математическое выражение на токены и занести их в массив строк Afaq1990 C# (си шарп) 3 11.09.2014 13:30
Разбить строку der90 PHP 4 18.02.2014 22:02
Разбить по функциям ( VisualStudio 2010) St@ter Помощь студентам 0 24.12.2012 09:39
php регулярное выражение - разбить строку на слова [MoNAMur] PHP 0 09.03.2012 15:20
разбить строку Ceprey Общие вопросы C/C++ 10 24.12.2009 20:47