@alifar

Почему в C++ некорректная работа с переменными и указателями?

Доброго времени суток. Подскажите, что делать - наблюдается непонятная работа с переменными и указателями в VS C++ 15

В основной части программы в цикле DO содержимое переменной _data меняется на какую-то муть, после первого ее использования.
prntscr.com/7bnfmk - здесь все ОК. едем дальше, жму "продолжить".
prntscr.com/7bng9h - на экран возвращается какая-то ересь.
По идее, мне должна возвращаться строка, которую я ввел в консоли. Реализация в методе _setString

P.S. я первый день в C++, так что не пинайте

#include <conio.h> 
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <iostream>

using namespace std;

/* Перегрузка функция копирования */
char *strcat_s(char *_string, char _buffer[100]) {
	_string = _buffer;
	return _string;
}

/* Функция ввода строки */
char *setString(char *_string = (char *)malloc(1)) {

	char _buffer[100];
	int i, _lenght = 0;
	_string = '\0';

	cout << "Введите строку:\n";

	do
	{
		i = scanf_s("%99[^\n]", _buffer, 100);

		if (i < 0) {
			free(_string);
			_string = NULL;
			continue;
		}

		if (i == 0)
			scanf_s("%*c");
		else {
			_lenght += strlen(_buffer);
			_string = (char *)realloc(_string, _lenght + 1);
			_string = strcat_s (_string, _buffer);
		}

	} while (i > 0);

	return _string;

}

char *removeSpaces(char *_string) {
	/* Функция удаления пробелов из строки */
	/* Функция удаления лишних пробелов после знаков */
	/* Функция удаления лишних пробелов перед знаками */
	return _string;
}


int main() {

	char *_data, *_result;
	
	// Не забудем поменять настройки консоли при запуске программы - шрифт Lucida Console
	SetConsoleCP(1251);
	SetConsoleOutputCP(1251);
	
	do {
		_data = setString();
		//if (strlen(_data) < 1)
			cout << _data << "\n";
			//continue;
		_result = removeSpaces(_data);
		cout << _data << "\n";
		cout << _result << "\n";

		cout << "Преобразованная строка:\n";

		//for (int i = 0; _result[i] != '\0'; i++) {
			//printf("%c", _result[i]);
		//}
		cout << "\n\n===========\n\n";

	} while (_data[0] != '\0');

	system("pause");
	return 0;

}
  • Вопрос задан
  • 771 просмотр
Решения вопроса 2
Denormalization
@Denormalization
Как я написал выше - скомпилил это дело под gcc.

UPD:
Проблема решилась заменой непонятной strcat_s на стандартную strncpy(_string, _buffer, _lenght);

UPD2:
Всю суть ошибки можно осознать тут valera.asf.ru/cpp/book/c08.shtml
Конкретно пункт "8.3.1. Автоматические объекты"

После возврата в main() mainResult указывает на область памяти, не отведенную никакому объекту. (В данном примере эта область все еще может содержать правильное значение, поскольку мы не вызывали других функций после trouble() и запись ее активации, вероятно, еще не затерта.)
Ответ написан
@FloorZ
Сам принцип программы не правильный. Буффер работает как по мне - не правильно, мы передаем содержимое буффера без учета размера самого _string, в итоге наш массив _string несколько раз перезаписывается мусором из памяти. Плюс передача массива в массив не правильно сделана.
А вообще есть такая вещь как new (buffer) type, конечно не по теме, но интересная;

Копировать один массив в другой массив так грубо тоже не стоит. По сути ошибка тут:
char *strcat_s(char *_string, char _buffer[100]) {
_string = _buffer;
return _string;
}

А если мы попытаемся присвоить пустую строку - будет ОЧЕНЬ плохо.
Массив присваивать другому массиву нельзя.
Не забывай, когда мы пишем массив вот так:
_string, по сути это тоже самое что писать &_string[0].
Имя массивая является ссылкой на первый элемент массива.
Когда как указатель на имя массива ссылается на первый элемент. Проще говоря.
char ch[10];
*ch == ch[0];
ch == &ch[0]
Сам же адрес массива извлекается так:
&ch. //Хотя по сути это адрес первого элемента массива.
Еще мы присваиваем весь буффер к стрингу, а надо лишь до элемента '\0'
<code lang="cpp">
char *strcat_s(char *_string, char _buffer[100]) {
	for (int i = 0; i < 100; i++) {
		if (_string[i] == '\0')
			break;
		_string[i] = _buffer[i];
	}
	return _string;
}
</code>

А вообще, если передаешь в функцию переменную, то передавай ее по ссылке &_string, а лучше в класс запихай.

В char *setString тоже фигня какая та.
Сишные функции, плюс ошибка на пустую строку. Я так сделал.
char *setString(char *_string = (char *)malloc(1)) {

	char _buffer[100];
	int i, _lenght = 0;
	_string = '\0';

	cout << "Введите строку:\n";

	cin.getline(_buffer, 100);
	_lenght += strlen(_buffer);
	_string = (char *)realloc(_string, _lenght + 1);
	_string = strcat_s(_string, _buffer);

		//На всякий обнуляю буффер, а то малоли.
	for (int i = 0; i < 100; i++)
		_buffer[i] = '\0';
	return _string;
}


Ну и вот примерчик, который делал по книге прата, что бы прояснить ТСу, как работают ссылки, указатели и т.п.
int main() {
	int * a;
	int * b;
	char buffer[1000]; //буффер на 1000 байт
	a = new (buffer) int;
	*a = 100;
	cout << "A = " << *a << endl;
	cout << "Address A=" << a << endl;
	b = new (buffer) int;
	cout << "B = " << *b << endl;
	cout << "Address B=" << b << endl;
	*b = 99;
	cout << "A = " << *a << endl;
	cout << "B = " << *b << endl << endl;
	cout << "Address A=" << a << endl;
	cout << "Address B=" << b << endl << endl;
	char * ch = new (buffer) char;
	cout << "init char ch \n";
	cout << "CH = " << ch << endl;
	ch = "Hello World I am buffer ";
	cout << "CH = " << ch << endl;
	cout << "A = " << *a << endl;
	cout << "B = " << *b << endl << endl;

	cout << "Address A=" << a << endl;
	cout << "Address B=" << b << endl;
	cout << "Address CH=" << &ch << endl << endl;

	cout << "init float f \n";
	float * f = new (buffer) float;
	cout << "F = " << *f;
	*f = 3.14;
	cout << "F = " << *f << endl;
	cout << "CH = " << ch << endl;
	cout << "A = " << int(*a) << endl;
	cout << "B = " << int(*b) << endl << endl;

	cout << "Address A=" << a << endl;
	cout << "Address B=" << b << endl;
	cout << "Address F=" << f << endl;
	cout << "Address CH=" << &ch << endl << endl;


	// Адресация массивово.
	cout << "*ch		=" << *ch
		<< "\n ch		=" << ch
		<< "\n &ch		=" << &ch
		<< "\n &ch[0]		=" << &ch[0]
		<< "\n *ch == ch[0]. ch == &ch[0]";
	system("pause");
	return 0;
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@vilgeforce
Раздолбай и программист
Почему в C++ некорректная работа с переменными и указателями? - потому что тот, кто на нем пишет не умеет ими пользоваться.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы