Member 14009930 Ответов: 1

Как отсортировать файл на языке Си


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
	struct details{
	char title[256] ;
	char platform [256];
	char score[256];
	char release_year[256];
}record[20000],temp;
int main ()
{
	int i =0,j=0,val=0;
	
  FILE * myfile;
  char a[512];
  
  myfile=fopen ("ign.txt","r");
 FILE *newFile = fopen("ign_new.txt", "w");

  if (myfile==NULL){
   perror (" empty file ");}
  else
  {
     	while ( fgets ( a, sizeof a, myfile ) != NULL ){
      
	  	switch(i) {
     

	   
   case 0  :
   	    strcpy(record[j].title,a);
    
        i++;
        break; 
	
	 case 1  :
	    
		
       strcpy(record[j].platform,a);
    
	   i++;
       break; 
	
	 case 2  :
   	     	   
         	     
        strcpy(record[j].score,a);
         
        i++;
        break; 
	
	 case 3  :
	 	strcpy(record[j].release_year,a);
       
	    i++;
        break; 
	
	 
    case 4:
	    i=0;
	    strcpy(record[j].title,a);
	    j++;
	    break;
	     
       
      
	  
	  
	  
		

}

	
	    
      
    }
    
     printf("%s",record[1].release_year);
     

    int n = j;
     
    
	for(i=1;i<n;i++){
		int flag=0;
		
		for( j=0;j<n-i;j++){
			if(atoi(record[j].score)<atoi(record[j+1].score)){
				strcpy(temp.title,record[j].title);
				strcpy(record[j].title,record[j+1].title);
				strcpy(record[j+1].title,temp.title);
				strcpy(temp.release_year,record[j].release_year);
				strcpy(record[j].release_year,record[j+1].release_year);
				strcpy(record[j+1].release_year,temp.release_year);
				strcpy(temp.platform,record[j].platform);
				strcpy(record[j].platform,record[j+1].platform);
				strcpy(record[j+1].platform,temp.platform);
				strcpy(temp.score,record[j].score);
				strcpy(record[j].score,record[j+1].score);
				strcpy(record[j+1].score,temp.score);
				flag=1;
			}
			
		}
		if(flag==0)break;
	}
       
    
    
    
    
    
    
    

    
    
    
    printf("\n %s",record[1].release_year);
    fclose (myfile);
    
  }
  return 0;
}






/*мой файл содержит 18000 записей, и некоторые из них являются
заглавие
платформа
Счет
release_year

140
ПК
8
2013

300
Беспроводной
8
2007

1942
Игра Мальчик Цвет
5
2000

1942
Беспроводной
5
2006
*/

Что я уже пробовал:

это не хранение данных столбца score в записи[j].оценка после сортировки, но до ее правильного хранения

Patrice T

"это не хранение данных столбца score в записи[j].оценка после сортировки, но до того, как она будет сохранена правильно"
Что заставляет вас думать, что это проблема ?

1 Ответов

Рейтинг:
0

Rick York

Если бы я был на вашем месте, я бы сделал небольшой набор функций для работы с вашей структурой данных. Это очень сильно очистит код! Я думаю, что вы сможете увидеть логические ошибки гораздо проще. Вот несколько примеров :

int ReadRecord( details * pd, FILE * pf )
{
    char a[512] = { 0 };
    int i = 0;
    while( ( i < 4 ) && fgets( a, sizeof a, pf ) )
    {
        if( ( a[0] == '\r' ) || ( a[0] == '\n' ) )
            continue;  // skip empty lines
        switch( i )
        {
            case 0  :
                strcpy( pd->title, a );
                break; 
            case 1  :
                strcpy( pd->platform, a );
                break; 
            case 2  :
                strcpy( pd->score, a );
                break;
            case 3  :
                strcpy( pd->release_year, a );
                break;
        }
        ++i;
    }
    return i;
}       

void CopyRecord( details *pddest, details *pdsource )
{
    strcpy( pddest->title,        pdsource->title );
    strcpy( pddest->platform,     pdsource->platform );
    strcpy( pddest->score,        pdsource->score );
    strcpy( pddest->release_year, pdsource->release_year );
}

void SwapRecords( details *pda, details *pdb )
{
    details temp = { 0 };
    CopyRecord( temp, pda );
    CopyRecord( pda, pdb );
    CopyRecord( pdb, temp );
}

int main()
{
   int j = 0;

   FILE * newFile = fopen( "ign_new.txt", "w" );
   FILE * myfile = fopen( "ign.txt", "r" );
   if( myfile == NULL )
   {
       perror (" empty file ");
       return -1;
   }

   // read the file

   while( ReadRecord( &records[j], myfile ) )
   {
       ++j;
   }

   fclose( myfile );
   myfile = NULL;

   printf( "read %d records\n", j );

   // sort the records

   int flag;
   int n = j;
   for( i = 1; i < n; i++ )
   {
      flag = 0;
      for( j = 0; j < n - i; j++ )
      {
          if( atoi( record[j].score ) < atoi( record[j+1].score ) )
          {
              SwapRecords( &record[j], &record[j+1] );
              flag = 1;
          }
      }
      if( flag == 0 )
          break;
   }

   // probably should do something with the records here
   // like write them to the new file.g

   fclose( newFile );
   return 0;
}
Я бы посоветовал создать функцию WriteRecord, которая работает в обратном направлении от ReadRecord, чтобы они могли обрабатывать ввод/вывод друг друга. Не забудьте написать пустую строку в WriteRecord. ;)

Кстати, я еще не оценил вашу логику. Я оставил это на ваше усмотрение. Моя цель состояла в том, чтобы создать функции для последовательностей логики, которые имеют дело со структурой данных. Это может упростить логику обработки, и тогда вы сможете увидеть ее внутреннюю работу гораздо яснее.

Один намек - Я думаю, что термины циклов for, используемых при сортировке, неверны.

Какого черта. Вот как бы я это сделал. Часто при сортировке используется функция сравнения сравниваемых данных. Вот один из них для этой структуры данных :
int CompareRecords( details *pda, details * pdb )
{
    // return true if record a's score is less than record b's
    return atoi( pda->score ) < atoi( pdb->score );
}
Теперь вы можете написать такую функцию сортировки :
void SortRecords( details * pd, int count )
{
    int i, j;

    for( j = 0; j < count - 1; ++j )
    {
         // The highest score record floats to the top so we don't have to check
         // the top any more -> start from the one after the outer loop index.

         for( i = j + 1; i < count; ++i )
         {
              if( CompareRecords( &pd[j], &pd[i] ) )
                  SwapRecords( &pd[j], &pd[i] );
         }
    }
}
Обратите внимание - я вообще не пробовал этот код. Вы можете либо попробовать его и отладить, либо использовать то, что вы хотите от него.


Rick York

Я только что заметил, что вы написали, что у вас есть 18000 записей в файле. Фу! Чтобы помочь сортировке, я бы внес следующие изменения.

struct details
{
    char title[256];
    char platform [256];
    char score[256];
    char release_year[256];
    int intscore;
};

void CopyRecord( details *pddest, details *pdsource )
{
    memcpy( pddest, pdsource, sizeof( details ) );
}

int CompareRecords( details *pda, details * pdb )
{
    // return true if record a's score is less than record b's
    return pda->intscore < pdb->intscore;
}

// change ReadRecord to have this in case 2 :

            case 2  :
                strcpy( pd->score, a );
                pd->intscore = atoi( a );
                break;
Функции подкачки и сортировки не нуждаются в изменении. Это действительно ускорит сортировку, потому что ему не придется преобразовывать счет из строки в целое число так много раз при сравнении - он может напрямую сравнивать два целочисленных значения.