Страница 1 из 1

Работа с записями С

Добавлено: 05 дек 2010, 22:29
vani2
Необходимо реализовать программу на языке С(ANSI), которая фильтрует записи некоторого
файла, передаваемого как параметр программы. Результат фильтрации исходного файла
записываются в файл с именем - res.txt.
Записи результата должны быть отсортированы с использованием наперед заданного
алгоритма сортировки. Используемый в задании алгоритм сортировки определяется
вариантом задания.
Исходный файл с данными формально представляет собой матрицу размера m×n , где
m - строки матрицы (число записей файла), n - число столбцов матрицы (поля записи,
разделенные символом форматирования).m,n наперед неизвестны.
Поля записи разделены ";",строки "\n".
Значение элементов матрицы может быть трех типов:
1. Целое.
2. Вещественное.
3. Строка символов(могут быть пробелы).
Фильтрация осуществляется по одному столбцу по условию <,> или =.
Например:FIELD:1 > 0(по первому полю)

Основные операции должны быть разнесены по отдельным функциям.
Так же должно быть реализовано динамическое распределение памяти.
В оперативной памяти исходный файл должен храниться в виде структуры.

Вот текст моей программы, она еще не полная, в ней полно ошибок и недостающих функций.
Основной мой вопрос: как считать из файла информацию в структуру, чтобы было пригодно затем фильтровать, сортировать данные. Сделал структуру из 3х типов с адресом последующей. Но не приложу ума, как после этого в нормальном порядке, а не с конца, анализировать файл и фильтровать его.Или стоит использовать лругую структуру?
Сохранение и сортировку представляю как делать.
Компилирую на gcc.
Жду любых предложений,вопросов по заданию. Надеюсь вы мне поможете. Заранее спасибо.

Код: Выделить всё

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

struct itabl{
	int cl;
	char sim[20];
	double dr;}

struct tablic { struct itabl tabl;
		struct tablic *inf; }

int read(char name[20],int,char,char kr[20]);
int krit(char);
void write(void);

int main(int argc, char **argv)
{
int t;
krit(argv[1]);
write(void);
}

int krit(char fname[20]) {
int f,v;
char z,k[50]; 
if (q==0) exit(2);
printf(“ Enter the filter\n FIELD: ”);
scanf(“%d [<>=]%s”,f,z,k);
read(fname,f,z,k);
return 0;
}

int read(char fn[20],ff,zz,kk) {
FILE *d,*r;
int tt,flag,k,m,n,ff;
char c;s[20],zz,kk[20];
struct tabl tb;
if ((d=fopen(fn,”r”))&&(r=fopen(“res.txt”,”w”))==NULL) {
	printf(“Open error\n”);
	tt=0;
	exit(1); }
else {
	printf(“Reading…\n”);
	tt=1; }
tmp1=tmp2=NULL
while ((c=fgetc(d))!=EOF) {
flag=0;
if (!(tmp1=(struct tablic*)malloc(sizeof(struct tablic)))) {
	printf("No memory\n");
	exit(3); }
if ((c!='\n') {
if ((c!=';') {
	s[i]=c;
	i++; }
	k=0;
	m=0;
	n=0;
	if (isdigit(s[1])) {
		for (j=0;j<i;j++) {
			if (s[j]=='.') {
			tmp1->tabl.dr=atof(s);
			tmp1->inf=tmp2;
			tmp2=tmp1
			k++;
			flag=1; } }
		if (flag==0) {
			tmp1->tabl.cl=atoi(s);
			tmp1->inf=tmp2;
			tmp2=tmp1			
			m++;
			flag=1; } 
	if (flag==0) {
		strcpy(tabl.sim,s);
		tmp1->inf=tmp2;
		tmp2=tmp1
		n++; }
for(j=0;i<j;j++) free(s[j]);}
else // проверяем фильтр, затем сохраняем
}
return tt;
}

void write(void) {
/*Описание переменных*/
if (fclose(r)) {
	printf(“Save error\n”);
	exit(2); }
else 
	printf(“Saving…\n”);
fclose(d);
}

Re: Работа с записями С

Добавлено: 06 дек 2010, 18:58
azrael
Основной мой вопрос: как считать из файла информацию в структуру, чтобы было пригодно затем фильтровать, сортировать данные. Сделал структуру из 3х типов с адресом последующей. Но не приложу ума, как после этого в нормальном порядке, а не с конца, анализировать файл и фильтровать его.Или стоит использовать лругую структуру?
Не очень понятно, что значит в нормальном порядке. Какая разница, с какого конца читать файл, если в задаче нужно разместить все структуры в памяти? Делаете массив структур, последовательно читаете в него все структуры из файла (хранить указатель на следующую в этом случае нет необходимости). Затем определяете три функции сравнения (по одной на каждый тип данных в структуре), которые принимают пару указателей на структуры и выясняют, какая из них должна стоять в списке выше (или ниже). Затем, в зависимости от алгоритма сортировки, пишете функцию сортировки, которой указываете, по какому полю сортировать (т.е. какую функцию сравнения использовать).

Re: Работа с записями С

Добавлено: 07 дек 2010, 22:25
vani2
При таком объявлении выдаёт ошибку в последней строчке:two types specified in one empty declaration.Почему?
struct itabl {
int cl;
char sim[20];
double dr; }

struct tablic { struct itabl tabl;
struct tablic *next; };

И ещё: какое значение будет у переменных,входящих в структуру,если я их объявил, а значение им не присваивал?

Re: Работа с записями С

Добавлено: 08 дек 2010, 19:11
BulldozerBSG
struct itabl {
int cl;
char sim[20];
double dr; } ; <-- забыл точку с запятой

значение зависит от того где создается переменная записи. Если глобальная переменная то будет заполнена нулями, иначе неопределенно...

Re: Работа с записями С

Добавлено: 08 дек 2010, 19:47
vani2
BulldozerBSG, спасибо.

Компилируется без ошибок, но при запуске ехе выдаёт ошибку памяти.
Подскажите, пожалуйста, что может быть не так.
И ещё такой вопрос:как динамически выделять память под массив списков (связанных между собой структур)?

Код: Выделить всё

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

struct itabl {
	int cl,fl;
	double dr;
	char *sim;};

struct tablic { struct itabl tabl;
				struct tablic *next; };
struct tablic *start=NULL,*tmp1=NULL,*tmp2=NULL,*tmp=NULL;

char fname[20],c,*s,z,k[20],str[50],field[3];

int read(char*,int,char,char*);
int krit(char *);
int filter(struct tablic *,int,char,char*);
int write(struct tablic *);

main(int argc, char *argv[]){
strcpy(fname,argv[1]);
krit(fname);}

int krit(char *fname) {
int f,v,i=0,n=0,j;
FILE *d,*r;
if ((d=fopen(fname,"r"))==NULL) {
	printf("Open error\n");
	exit(0); }
else printf("Reading...\n");
printf("Enter the filter:\nFIELD: ");
gets(str);
while (str[i]!=' '){ 
	field[i]=str[i];
	++i;}
f=atoi(field);
z=str[++i];
for (j=i+1;j<strlen(str);j++){ 
	k[n]=str[j];
	++n;}
read(fname,f,z,k);
return 0;
}

int read(char *fname,int f,char z,char *k) {
int flag=0,i=0,j;
FILE *d,*r;
if (!(tmp1=(struct tablic*)malloc(sizeof(struct tablic)))) {
	printf("No memory\n");
	exit(0); }
if (!(start=(struct tablic*)malloc(sizeof(struct tablic)))) {
	printf("No memory\n");
	exit(0); }
if (!(s=(char*)malloc(20*sizeof(char)))) {
	printf("No memory\n");
	exit(0); }
start=tmp1;
while ((c=fgetc(d))!=EOF) {
if (strcmp(&c,"\n")!=0) {
	if (strcmp(&c,";")!=0) {
		*(s+i)=c;
		i++;}
	if (isdigit(*s)) 
		for (j=0;j<i;j++); {			//Проверка на тип данных 
			if (strcmp(s+j,".")==0) {
				tmp1->tabl.dr=atof(s);
				tmp1->tabl.fl=2;
				flag=1; };};
			if (flag==0) {
				tmp1->tabl.cl=atoi(s);
				tmp1->tabl.fl=1;}
	else {
		strcpy(tmp1->tabl.sim,s);
		tmp1->tabl.fl=3;};
	free(s);
	tmp2=tmp1;
	if (!(tmp1=(struct tablic*)malloc(sizeof(struct tablic)))) {
		printf("No memory\n");
		exit(0); };
	tmp2->next=tmp1;}
else filter(start,f,z,k);}
return 0;
}

int filter(struct tablic *start,int f,char z,char *k){
int i;
tmp1=start;
for (i=0;i<f;i++){
tmp2=(tmp1->next);
tmp1=tmp2;}
if (strlen(tmp1->tabl.sim)==0){     
	if (tmp1->tabl.fl==1){				// Для целых 
		if (strcmp(&z,"=")==0){
			if (tmp1->tabl.cl==atoi(k)) write(start);}
		else if (strcmp(&z,"<")==0){
			if ((tmp1->tabl.cl)<atoi(k)) write(start);}
		else if ((tmp1->tabl.cl)>atoi(k)) write(start);}
	else if (tmp1->tabl.fl==2){			//Для дробных 
		if (strcmp(&z,"=")==0){
			if (tmp1->tabl.dr==atof(k)) write(start);}
		else if (strcmp(&z,"<")==0){
			if ((tmp1->tabl.dr)<atof(k)) write(start);}
		else if ((tmp1->tabl.dr)>atof(k)) write(start);}
else{ 											//Для строки
	if (strcmp(&z,"=")==0){
		if (strcmp(tmp1->tabl.sim,k)==0) write(start);}
	else if (strcmp(&z,"<")==0){
		if (strcmp(tmp1->tabl.sim,k)<0) write(start);}
	else if (strcmp(tmp1->tabl.sim,k)>0) write(start);}
}}			
	
int write(struct tablic *start) {
FILE *d,*r;
tmp=start;
while (tmp->next){
	if (&((tmp->tabl.sim))==NULL){     
		if (&((tmp->tabl.cl))!=NULL) fprintf(r,"%d;",tmp->tabl.cl);	// Для целых 
		else fprintf(r,"%f;",tmp->tabl.dr);}						//Для дробных
	else fprintf(r,"%s;",tmp->tabl.sim);							//Для строки
	tmp=tmp->next;}								
if (&((tmp->tabl.sim))==NULL){     									//Для последней записи, чтобы перейти на новую строку
	if (&((tmp->tabl.cl))!=NULL) fprintf(r,"%d;\n",tmp->tabl.cl);	// Для целых 
	else fprintf(r,"%f;\n",tmp->tabl.dr);}						//Для дробных
else fprintf(r,"%s;\n",tmp->tabl.sim);								//Для строки
if (fclose(r)) {
	printf("Save error\n");
	exit(0);}
else {
	printf("Saving…\n");
	fclose(d);}
}

Re: Работа с записями С

Добавлено: 11 дек 2010, 19:12
Romeo
А дебагер не помогает?

Re: Работа с записями С

Добавлено: 12 дек 2010, 12:50
vani2
Исправил указатели, ошибок нет, но почему то отказывается сохранять в файл.
Прошу, гляньте, что не так.

Код: Выделить всё

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

struct itabl {
	int cl,fl;
	double dr;
	char *sim;};

struct tablic { struct itabl tabl;
				struct tablic *next;
				char t;	};
struct tablic *start=NULL,*mstart,*tmp1=NULL,*tmp2=NULL,*tmp3=NULL,*tmp=NULL;

int read(char*,int,char,char*);
int krit(char *);
int filter(struct tablic *,int,char,char*);
int write(struct tablic *);
FILE *d,*r;

main(int argc, char *argv[]){
char fname[20];
strcpy(fname,argv[1]);
r=fopen("res.txt","w");
krit(fname);
if (fclose(r)) {
	printf("Save error\n");
	exit(0);}
else printf("Saving…\n");
return 0;
}

int krit(char *fname) {
int f,i=0,n=0,j;
char z,k[20],str[50],field[3];
if ((d=fopen(fname,"r"))==NULL) {
	printf("Open error\n");
	exit(0); }
else printf("Reading...\n");
printf("Enter the filter:\nFIELD: ");
gets(str);
while (str[i]!=' '){ 
	field[i]=str[i];
	++i;}
f=atoi(field);
z=str[++i];
for (j=i+1;j<strlen(str);j++){ 
	k[n]=str[j];
	++n;}
read(fname,f,z,k);
return 0;
}

int read(char *fname,int f,char z,char *k) {
int flag=0,i=0,j,n,o=0;
char c,*s;
d=fopen(fname,"r");
if (!(tmp1=(struct tablic*)malloc(sizeof(struct tablic)))) {
	printf("No memory\n");
	exit(0); }
start=tmp1;
mstart=tmp1;
while (c!=EOF) {
	c=fgetc(d);
	if (c!=EOF){
		if (c=='\n') tmp1->t='\n';		//заполняем t, чтобы знать, где конец записи
		while (c!=';') {
			s[i]=c;
			++i;
			c=fgetc(d);}
			s[i+1]='\0';					//завершаем строку
//printf("%s\n",s);
		for (i=0;i<strlen(s);i++) if (isdigit(s[i])) ++o; 
		if (o>=(strlen(s)-1)) {
			for (i=0;i<strlen(s);i++) {			//Проверка на тип данных и заполнение структуры
				if (s[i]=='.') {
					tmp1->tabl.dr=atof(s);
					tmp1->tabl.fl=2;
					flag=1;}}
				if (flag==0) {
					tmp1->tabl.cl=atoi(s);
					tmp1->tabl.fl=1;}}
		else {
			strcpy(tmp1->tabl.sim,s);
			tmp1->tabl.fl=3;}
		free(s);							//очистка переменной
		if ((tmp1->t)=='\n') {
			tmp3=tmp1;
			filter(mstart,f,z,k);
			tmp1=tmp3;}
		tmp2=tmp1;
		if (!(tmp1=(struct tablic*)malloc(sizeof(struct tablic)))) {
			printf("No memory\n");
			exit(0);}
		tmp2->next=tmp1;}}
return 0;
}

int filter(struct tablic *mstart,int f,char z,char *k){
int i;
tmp1=mstart;
for (i=0;i<f;i++){
	tmp2=(tmp1->next);
	tmp1=tmp2;}
if ((tmp1->tabl.fl)!=3) {
	if (tmp1->tabl.fl==1){				// Для целых 
		if (z=='=') {
			if (tmp1->tabl.cl==atoi(k)) write(mstart);}
		else if (z=='<') {
			if ((tmp1->tabl.cl)<atoi(k)) write(mstart);}
		else if ((tmp1->tabl.cl)>atoi(k)) write(mstart);}
	else if (tmp1->tabl.fl==2){			//Для дробных 
		if (z=='='){
			if (tmp1->tabl.dr==atof(k)) write(mstart);}
		else if (z=='<') {
			if ((tmp1->tabl.dr)<atof(k)) write(mstart);}
		else if ((tmp1->tabl.dr)>atof(k)) write(mstart);}}
else { 											//Для строки
	if (z=='=') {
		if (strcmp(tmp1->tabl.sim,k)==0) write(mstart);}
	else if (z=='<') {
		if (strcmp(tmp1->tabl.sim,k)<0) write(mstart);}
	else if (strcmp(tmp1->tabl.sim,k)>0) write(mstart);}
	return 0;
}			
	
int write(struct tablic *mstart) {
//int *k;
tmp=mstart;
//(*k)++;
while ((tmp->t)!='\n'){
	if ((tmp->tabl.fl)!=3){     
		if ((tmp->tabl.fl)==1) fprintf(r,"%d;",tmp->tabl.cl);	// Для целых 
		else fprintf(r,"%f;",tmp->tabl.dr);}						//Для дробных
	else fprintf(r,"%s;",tmp->tabl.sim);							//Для строки
	tmp=tmp->next;}								
if ((tmp->tabl.fl)!=3){	     									//Для последней записи, чтобы перейти на новую строку
	if ((tmp->tabl.cl)==1) fprintf(r,"%d;\n",tmp->tabl.cl);		// Для целых 
	else fprintf(r,"%f;\n",tmp->tabl.dr);}						//Для дробных
else fprintf(r,"%s;\n",tmp->tabl.sim);							//Для строки
//printf("Kolichestvo zapisey-%d\n",*k);
//return *k;
return 0;
}