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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 03.01.2010, 15:45   #1
Serjuk
Форумчанин
 
Регистрация: 06.08.2009
Сообщений: 136
По умолчанию функция malloc() для разного типа переменной.

Здравствуйте, встала проблема выделения памяти для разного типа переменной (Float,char,int),т.е. выделяя память под int - char и float работать не будут,аналогично будет, если поменять.
Суть вопроса:
с клавиатуры,ну или из файла получаем массив длинной n (a[n]).Можно ли выделить для пустых массивов размерности n память для 3
видов,например:

Код:
int*a;
int *z;
char*r;
float*e;
    scanf("%d", &n);
       
z = (int*) malloc(sizeof(int)*n);
e = (float*) malloc(sizeof(float)*n);
r = (char*) malloc(sizeof(char)*n);
 
for(i = 0 ; i < n; i++) {
        scanf("%d", &a[i]);
а потом в зависимости от типа a[n] присваивать в тот массив в который была выделена память:
например для символьных:
Код:

If(isalpha(a[i])){

for(i=0;i<n;i++)
r[i]=a[i];}
/*аналогично и с другими типами*/
2 вопрос:
После выполнения программы память должна освобождаться с помощью функции free().
Как правильно освобождать массив:
Код:

free(a);
/*или*/
for (i=0;i<n;i++)
free(a[i]);
Serjuk вне форума Ответить с цитированием
Старый 03.01.2010, 17:03   #2
liljon
Форумчанин
 
Регистрация: 03.01.2010
Сообщений: 229
По умолчанию

очевидно, что ты ешо не понял что такое массив!
подпись
liljon вне форума Ответить с цитированием
Старый 03.01.2010, 17:48   #3
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от Serjuk Посмотреть сообщение
Здравствуйте, встала проблема выделения памяти для разного типа переменной (Float,char,int),т.е. выделяя память под int - char и float работать не будут,аналогично будет, если поменять.
Суть вопроса:
с клавиатуры,ну или из файла получаем массив длинной n (a[n]).Можно ли выделить для пустых массивов размерности n память для 3
видов,например:

Код:
int*a;
int *z;
char*r;
float*e;
    scanf("%d", &n);
       
z = (int*) malloc(sizeof(int)*n);
e = (float*) malloc(sizeof(float)*n);
r = (char*) malloc(sizeof(char)*n);
 
for(i = 0 ; i < n; i++) {
        scanf("%d", &a[i]);
а потом в зависимости от типа a[n] присваивать в тот массив в который была выделена память:
например для символьных:
Код:

If(isalpha(a[i])){

for(i=0;i<n;i++)
r[i]=a[i];}
/*аналогично и с другими типами*/
2 вопрос:
После выполнения программы память должна освобождаться с помощью функции free().
Как правильно освобождать массив:
Код:

free(a);
/*или*/
for (i=0;i<n;i++)
free(a[i]);
А зачем это? Скажите цель, может быть есть более логичное и простое решение, нежели заводить с десяток массивов различного типа. Ну а в принципе malloc выделяет память, то есть просто набор байт, что писать в эти байты(float, char, int) решает исключительно программист и в одну и ту же память можно писать и то и другое и третье, важно указать компилятору как именно эту память интерпретировать(как указатель на int, float или char) но это можно сделать простым приведением.
По второму вопросу:
Код:
char* a = (char*)malloc(100);
...
free(a);
Код:
int i;
char** a = (char**)malloc(10);
for(i = 0; i < 10; i++)
   a[i] = (char*)malloc(100);
...
for(i = 0; i < 10; i++)
   free(a[i]);
free(a);
То есть сколько раз мы malloc, столько и free
netrino вне форума Ответить с цитированием
Старый 03.01.2010, 17:59   #4
Serjuk
Форумчанин
 
Регистрация: 06.08.2009
Сообщений: 136
По умолчанию

ну мне нужно отсортировать массив, который поступает либо с клавиатуры, либо с файла , т.е. тип массива не известен - он может быть 3 видов, либо float либо int либо char,поэтому приходится сделать проверку на тип и выделить память,ведь нельзя выделять память под integer и сувать туда массив из char или можно?))Можно ли сделать проще или по-другому?
Serjuk вне форума Ответить с цитированием
Старый 03.01.2010, 18:05   #5
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от Serjuk Посмотреть сообщение
ну мне нужно отсортировать массив, который поступает либо с клавиатуры, либо с файла , т.е. тип массива не известен - он может быть 3 видов, либо float либо int либо char,поэтому приходится сделать проверку на тип и выделить память,ведь нельзя выделять память под integer и сувать туда массив из char или можно?))Можно ли сделать проще или по-другому?
Как так трёх видов? Если там только цифры, при этом могут быть вещественные, то стоит взять самый вместительный тип из этих - float, или лучше double. Или Вам по заданию нужно сделать для трёх разных типов? Если тип массива неизвестен, то как узнавать каков этот тип? Это задаётся пользователем? Массив типа char будет содержать в себе буквы?
Цитата:
ведь нельзя выделять память под integer и сувать туда массив из char
вообще говоря конечно можно, но не наоборот ) так что особо увлекаться подобным не стоит
netrino вне форума Ответить с цитированием
Старый 03.01.2010, 18:20   #6
Serjuk
Форумчанин
 
Регистрация: 06.08.2009
Сообщений: 136
По умолчанию

ну в задании сказано,что массив может содержать только вещественные или только символьные(буквы) или только целые числа.В том то и дело,что массив из каких элементов состоит не сказано,т.е. можно вводить любой и память должна выделяться под любой,а узнать поидее по 1 элементу этого массива можно.поэтому я пытаюсь сделать 3 массива пустых и выделить под них память под каждый адрес - чтобы потом в них присвоить эти массивы,тип которых опознаю.Только вот еще вопрос возник,будет ли память выделяться под пустые массивы? поидее же если мы используем указатели,то память зависит от адресов - насколько я понимаю..А если выделить под double - то туда можно и int и float пихать?
Serjuk вне форума Ответить с цитированием
Старый 03.01.2010, 20:02   #7
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Код:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

#define UNDEFINED (-1)
#define ALPHA      0
#define REAL       1
#define INTEGER    2

int   check_type(FILE* input_stream);
void* get_array(FILE* input_stream, int array_type, int* n);
void  sort_array(void* array, int array_type, int n);
void  print_array(void* array, int array_type, int n);


int main()
{
	FILE* input = fopen("input.txt", "r"); // пытаемся открыть файл
	void* array = 0;
	int   array_type;
	int   array_len = 0;

	if(input == 0)                // если не получилось 
		input = stdin;    // то будем брать массив из консоли

	array_type = check_type(input);  // узнаём тип массива(символьный, вещественный или целочисленный)
	if( array_type == UNDEFINED ) {   // если неопределён 
		printf("Error: undefined type of array\n");  // то сообщение об ошибке
		exit(-1);   // и выход
	}

	array = get_array(input, array_type, &array_len); // получаем массив и его длину
	if( array == 0 ) {
		printf("Error: have no memory\n");
		exit(-1);
	}

	sort_array(array, array_type, array_len); // сортируем
	print_array(array, array_type, array_len); // выводим на консоль

	free(array); // освобождаем память

	getchar();
	return 0;
}


int check_type(FILE* input_stream) // Ф-ция определения типа массива(целочисленный, вещественный, символьный)
{
	char c[80];
	int  i = 0;
	int  type = UNDEFINED; // по умолчанию тип неопределён
	
	fscanf(input_stream, "%s", c); // читаем первый элемент массива в строку
	if( isalpha(c[i]) )                   // если встречаем в нём букву, то это символьный массив
		type = ALPHA;
	else if( isdigit(c[i]) ) {             // если же цифру, то это либо целочисленный, либо вещественный тип
		type = INTEGER;         // предполагаем, что целочисленный
		for(; c[i] != 0; i++ ) {
			if( c[i] == '.' ) {         // но если находим точку, то это вещественный
				type = REAL;
				break;
			}
		}
	}

	for(i = strlen(c)-1; i >= 0; i--)          // возвращаем считанный элемент обратно в поток(в файл либо в консоль)
		ungetc(c[i], input_stream);

	return type;
}

void* get_array(FILE* input_stream, int array_type, int* n) // ф-ция выделения и заполнения памяти массивом 
{
	int   i = 0;
	int   fin_input = 1;
	void* memory = malloc(1000); // выделяем 1000 байт

	switch(array_type) {
		case ALPHA:
			while( fin_input > 0 ) { // fscanf в случае удачного чтения возвращает значение больше нуля
				fin_input = fscanf(input_stream, "%c", &((char*)memory)[i]); // читаем 1 элемент в память
				if(fin_input > 0)
					fin_input = !( ((char*)memory)[i] == 13 || ((char*)memory)[i] == 10 ); // завершить также, если встречен перевод строки
				if( isalpha( ((unsigned char*)memory)[i] ) ) // если считанный символ буква, то оставляем в массиве
					i++;
			}
			break;
		case REAL:
			while( fin_input > 0 ) {
				fin_input = fscanf(input_stream, "%f", &((float*)memory)[i]); // то же самое если вещественный
				i++;
			}
			break;
		case INTEGER:
			while( fin_input > 0 ) {
				fin_input = fscanf(input_stream, "%d", &((int*)memory)[i]); // и целочисл.
				i++;
			}
			break;
		default:
			free(memory); // если тип неопределён, то освобождаем выделенную память
			memory = 0;   
	}

	*n = i-1; // возвращаем через указатель кол-ство элементов в массиве
	return memory; // и сам массив
}

int sort_rule_int(const void* a, const void* b) // правила сортировки, необходимо для qsort
{
	return *(int*)a - *(int*)b;
}

int sort_rule_flo(const void* a, const void* b)
{
	if(*(float*)a == *(float*)b)
		return 0;
	return (int) ((*(float*)a - *(float*)b) * 100);
}

int sort_rule_cha(const void* a, const void* b)
{
	return *(char*)a - *(char*)b;
}

void sort_array(void* array, int array_type, int n)
{
	switch(array_type) {
		case ALPHA:
			qsort(array, n, sizeof(char), &sort_rule_cha); // вместо этого можно написать и вызывать собственную ф-цию
                                                                                              // сортировки символьного массива
			break;
		case REAL:
			qsort(array, n, sizeof(float), &sort_rule_flo); // вещественного массива
			break;
		case INTEGER:
			qsort(array, n, sizeof(int), &sort_rule_int);  // целочисленного массива
			break;
	}

	return;
}

void  print_array(void* array, int array_type, int n) // ф-ция для вывода массива на консоль
{
	int i;

	switch(array_type) {
		case ALPHA:
			for( i = 0; i < n; i++ )
				printf("%c ", ((char*)array)[i]); // вывод, если массив символьный
			break;
		case REAL:
			for( i = 0; i < n; i++ )
				printf("%.2f ", ((float*)array)[i]); // вещественный
			break;
		case INTEGER:
			for( i = 0; i < n; i++ )
				printf("%d ", ((int*)array)[i]); // целочисленный
			break;
		default:
			printf("Not recognized type of array\n"); // если тип неопределён, то вывод соответствующего сообщения
	}

	return;
}

Последний раз редактировалось netrino; 04.01.2010 в 14:48.
netrino вне форума Ответить с цитированием
Старый 03.01.2010, 20:30   #8
Serjuk
Форумчанин
 
Регистрация: 06.08.2009
Сообщений: 136
По умолчанию

Мне еще вывод из файла нужен и вывод в файл с использованием аргументов командной строки,т.е. например myprog filename filename2,где filename и filename2 задаются любыми.В этом файле на 1 строке кол-во элементов массива,а на второй уже идет массив,который надо отсортировать..Что-то у меня лажа какая то получается..

Код:
main(int argc,char *argv[])
{ 
for (i=0;i<argc;i++)//
        {
            if (strcmp(argv[i],"filename")==0)

pF=fopen(argc.filename,"r");
/*открытие файла, чтение*/
fscanf(pF,"%i",&Size);
/*форматный ввод/чтение */
i=0;
/*счётчик размера файла (символов, чисел)*/
while(!feof(pF)){
fscanf(pF,"%f",&D[i]);
i++;
}
fclose(pF);
/*закрытие файла, чтения*/
}
Serjuk вне форума Ответить с цитированием
Старый 04.01.2010, 12:20   #9
Serjuk
Форумчанин
 
Регистрация: 06.08.2009
Сообщений: 136
По умолчанию

netrino, спасибо тебе,что помогаешь,но у меня тут еще возник вопрос)
Цитата:
Тут для сортировки я использовал библиотечную qsort, но не составит труда заменить этот вызов собственной процедурой сортировки.
т.е. это можно сделать таким образом:
Код:

/*Заменить :*/

int sort_rule_cha(const void* a, const void* b)
{
	return *(char*)a - *(char*)b;
}

			qsort(array, n, sizeof(char), &sort_rule_cha);
			break;
/*на*/
for (i=0;i<argc;i++)//сортировка по возрастанию с прим опции -а
        
            if (strcmp(argv[i],"-a")==0)
            {
sort(array, n, sizeof(char));
}
sort(array,n,sizeof(char))
{
 for( i=0; i < n; i++) {            // i - номер прохода
		           for( j = n-1; j > i; j-- ) {     // внутренний цикл прохода
			           if (strcmp(array[j-1],array[j])>0){
				         x=array[j-1];
				            array[j-1]=array[j];
				              array[j]=x;
			}
		}
	}
            }
     
        }
Правильно ли я понял?)Только что-то символьные не сортирует
И второй вопрос: Как с использованием аргументов командной строки сделать,чтобы можно было сортировать любой файл применимо к твоей программе?На сколько я понимаю,это выглядит так:
Код:
FILE* input 
for (i=0;i<argc;i++)
        {
input=fopen(argc.filename,"r");
fscanf(input_stream, "%s", c);//не совсем понимаю,эта строчка нужна для нахождения длины массива из файла?
for(i = strlen(c)-1; i >= 0; i--)
		ungetc(c[i], input_stream);//вытаскивание массива из файла,так?)
И можешь еще объяснить строчки?
Код:
/*Насколько я понимаю тут идет выделение динамической памяти под каждый тип данных*/

switch(array_type) {
		case ALPHA:
			while( fin_input > 0 ) //не совсем понимаю что такое  fin_input
{
				fin_input = fscanf(input_stream, "%c", &((char*)memory)[i]);//вытаскивание из файла и выделение памяти?
				if(fin_input > 0)
					fin_input = !( ((char*)memory)[i] == 13 || ((char*)memory)[i] == 10 ); // 13 и 10 - что это?)))				if( isalpha( ((unsigned char*)memory)[i] ) )//это выделение конечной памяти?
					i++;
			}
			break;
		case REAL:
			while( fin_input > 0 ) {
				fin_input = fscanf(input_stream, "%f", &((float*)memory)[i]);
				i++;
			}
			break;
		case INTEGER:
			while( fin_input > 0 ) {
				fin_input = fscanf(input_stream, "%d", &((int*)memory)[i]);
				i++;
			}
			break;
		default:
			free(memory);
			memory = 0;
Код:
void* memory = malloc(1000);//тип void используется разве не для подпрограмм/функций?Ты тут выделил 1000 байт под память так?а можно ли сделать не определенное кол-во ,а подстраиваться под информацию?
void* memory = malloc(n) , где n количество элементов массива
Объясни пожалуйста,если не сложно,ты мне многим поможешь)

Последний раз редактировалось Serjuk; 04.01.2010 в 12:59.
Serjuk вне форума Ответить с цитированием
Старый 04.01.2010, 14:59   #10
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Добавил комментарии. Я написал фиксированный размер выделяемой памяти, но естественно, раз длину массива можно узнать из самого файла, то можно выделять ровно столько, сколько необходимо для того, чтобы держать этот массив, также упростится и процедура заполнения массива.
Цитата:
Код:
sort(array,n,sizeof(char))
{
 for( i=0; i < n; i++) {            // i - номер прохода
		           for( j = n-1; j > i; j-- ) {     // внутренний цикл прохода
			           if (strcmp(array[j-1],array[j])>0){
				         x=array[j-1];
				            array[j-1]=array[j];
				              array[j]=x;
			}
		}
	}
            }
     
        }
}
зачем же передавать размер типа char, если вы это потом не используете? и зачем использовать strcmp для сравнения двух символов? ни то ни другое не нужно.
Цитата:
Код:
FILE* input 
for (i=0;i<argc;i++)
        {
input=fopen(argc.filename,"r");
fscanf(input_stream, "%s", c);//не совсем понимаю,эта строчка нужна для нахождения длины массива из файла?
for(i = strlen(c)-1; i >= 0; i--)
		ungetc(c[i], input_stream);//вытаскивание массива из файла,так?)
Нет, не для нахождения длины из файла, когда я это писал, вы ещё не сказали, что его длина находится в нём самом первым элементом. И это не вытаскивание массива из файла, оно происходит в другой процедуре(в комментариях написано)
Тип void действительно может быть только в контексте описания ф-ции, но void* - указатель на нетипизированную память.
Насчёт параметров командной строки - гляньте в интернете, много раз обсуждалось, не составит труда разобраться
netrino вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как создать массив от переменной длины без mAlloc? TwiX Общие вопросы C/C++ 5 27.10.2009 16:50
функция для подсчета количества символов в строке типа std::string a Артэс Общие вопросы C/C++ 3 06.07.2009 17:43
считать данные из переменной типа String 1o1man Помощь студентам 13 17.04.2009 22:34
Выравнивание высоты таблицы для разного разрешения Svetix HTML и CSS 10 03.04.2009 17:00
Определение типа переменной Игорь007 Общие вопросы C/C++ 7 10.01.2009 13:01