Сортировка данных на языке Си - PullRequest
0 голосов
/ 30 апреля 2010

Мне не требуется помощь в выполнении следующего требования, поскольку я очень мало знаю о синтаксисе языка Си.

У меня есть данные в таком файле

73 54 57 [52]
75 73 65 [23]
65 54 57 [22]
22 59 71 [12]
22 28 54 [2]
65 22 54 73 [12]
65 28 54 73 [52]
22 28 65 73 [42]
65 54 57 73 [22]
22 28 54 73 [4]

Где значения в скобках обозначают вхождение этой серии. Мне нужно отсортировать эти данные на основе появления данных по убыванию с максимальным количеством элементов сверху.

65 28 54 73 [52]
22 28 65 73 [42]
65 54 57 73 [22]
65 22 54 73 [12]
22 28 54 73 [4]
28 59 71 [122]
73 54 57 [52]
22 28 65 [26]
..
.
.
.

И так далее ...

Что такое быстрый код для этого?

Я пытаюсь это

#include<string.h>
#include <stdio.h>
int main() {

    FILE *infile;
    char fname[40]="resultFile1.txt";
    char line[100];
    int lcount=0;
    if((infile = fopen(fname, "r")) == NULL) {
        printf("Error Opening File.\n");
    }
    char *Arr[23];// need to be dynamic
    while( fgets(line, sizeof(line), infile) != NULL ) {
        stringArray[lcount]=line;
        lcount++;
        Arr[lcount]=line;
    } fclose(infile);
    int i;
    for (i = 0; i < lcount; i++) {
        printf(Arr[i]);// not able to get Arr
    }
}

Ответы [ 6 ]

10 голосов
/ 30 апреля 2010

Я бы:

  1. Загрузка текста в память в виде большого блока текста.
  2. Найти начало каждой строки, создавая массив строковых указателей в блок данных.
  3. Напишите функцию сравнения, которая сравнивает две строки, ища шаблон «[число]».
  4. Вызовите qsort() в моем массиве указателей строк, используя функцию сравнения.
  5. Готово. :)
2 голосов
/ 14 мая 2010

Проще всего разобрать проблему на мелкие части (как сказано выше). Это важная часть разработки в целом (будь то программное обеспечение или иное).

Проблемы примерно такие:

  • Прочитать файл
  • вывод результата
  • подсчитать количество элементов в строке
  • извлечь номер в конце строки
  • Сохранить файл
  • сортировка файла по количеству элементов в строке
  • сортировка файла по номеру в конце файла

После этого все просто!

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

#define BUFFER_SIZE 100
#define MAX_NODES 1000



int count_spaces( char * s ) {
  int spaces = 0;
  int i;
  for( i = 0; i < strlen( s ) ; i ++ ) {
    if( s[ i ] == ' ' ) {
      spaces++;
    }
    i++;
  }
  return spaces;
}

/* sort by number of spaces */
int sort1( char  *a, char  * b ) {
  int spaces_a = count_spaces( a );
  int spaces_b = count_spaces( b );

  if( spaces_a < spaces_b )
    return -1;
  if( spaces_a > spaces_b )
    return 1;
  return 0;

}

int get_digits( char *s ) {
  char buffer[ 10 ];
  memset( buffer, 0, 10 );
  int state = 0;
  int i = 0, j = 0;
  int number = 0;
  for( i = 0; i < strlen( s ) ; i ++ ) {
    if( state == 0 && s[ i ] == '[' ) {
      state = 1;
    }
    if( state == 1 && s[ i ] != ']' ) {
      buffer[ j ] = s[ i ];
      j++;
    }
    if( state == 1 && s[ i ] == ']' ) {
      break;
    }
  }
  sscanf( buffer, "%d", &number );

}

/* sort by digits in brackets at the end of the line */
int sort2( char  *a, char  * b ) {
  int a_num = get_digits( a );
  int b_num = get_digits( b );

  if( a_num < b_num )
    return -1;
  if( a_num > b_num )
    return 1;
  return 0;


}




int main() {
  FILE *infile;
  char line[ BUFFER_SIZE ];
  int i = 0;
  char *nodes[ MAX_NODES ];

  if( (infile = fopen( "data.txt", "r" )) == NULL ) {
    printf( "Error opening file\n" );
    return -1;
  }

  while( fgets( line, BUFFER_SIZE, infile ) != NULL ) {
    if( (nodes[ i ] = malloc( strlen( line ) + 1 )) == NULL ) {
      printf( "Malloc failed\n" );
      return -1;
    }
    strcpy( nodes[ i ], line );
    i++;
  }
  // sort by # of items in a line
  qsort( nodes, i, sizeof( char *), (void *)(&sort1) );
  // sort by number
  qsort( nodes, i, sizeof( char *), (void *)(&sort2) );
  /* output results */
  i--;
  do {
    printf( "%s", nodes[i] );
    i--;
  } while( i >= 0 );


}
2 голосов
/ 30 апреля 2010

Вас может заинтересовать функция qsort . По сути, вам нужно сначала проанализировать ваш файл так, чтобы он был в массиве структур, где каждая структура имеет последовательность и "вхождение" (ключ), как вы его назвали.

Затем вы можете определить собственную функцию сравнения, например:

int compare_file_entries(void* data1, void* data2)
{
    struct file_entry* entry1 = (struct file_entry*) data1;
    struct file_entry* entry2 = (struct file_entry*) data2;
    if ( entry1->occurence < entry2->occurence ){
        return -1;
    } else if ( entry2->occurence > entry2->occurence ){
        return 1;
    } else{
        return 0;
    }
}

Тогда, если у вас есть массив file_entry объектов, скажем, struct file_entry* entries, и у вас есть entrycount таких записей, то вы бы отсортировали этот список, используя:

qsort(entries,entrycount,sizeof(struct file_entry),&compare_file_entries);

После того как вы отсортировали представление в памяти, вы можете записать его обратно в файл.

1 голос
/ 10 мая 2010

Если вам не обязательно делать это в C (что может быть так, это не имеет значения), вы можете использовать стандартные инструменты UNIX:

cat test | sed -r 's/.*\[(.+)\]$/\1 \0/' | sort -n -r | cut -d ' ' -f 2-

"кошачий тест": не очень нужен, просто чтобы кинуть файл на трубу "sed ....": дублировать последний номер в скобках в начале строки "sort -n -r": сортировка с первым номером в обратном порядке «вырезать ...»: удалить дублирующееся поле в начале строки

Из C вы можете вызвать это с помощью system(), и он выдаст результат на стандартный вывод, но если вам нужно прочитать результат обратно в вашей программе, вам потребуется больше, чем это (каналы ..) *

0 голосов
/ 14 мая 2010

Вот мой ответ. Извините за огромное количество кода!

Сначала немного struct с

// contains the whole line as well as the series for ease of id
struct _Payload
{
   char *line;      // the line of text
   int series;      // the number in [ ] at the end of that line
   int numElements; // the number of elements in the line
};

// a tree sorted by the series of the Payloads within
struct _PayloadTree
{
   struct _Payload *payload;
   struct _PayloadTree *left;
   struct _PayloadTree *right;
};

// a tree sorted by the number of elements in the PayloadTree subtrees
struct _Tree
{
   int numElements;  // for sorting
   struct _PayloadTree *payloadTree;
   struct _Tree *left;
   struct _Tree *right;
};

typedef struct _Payload Payload;
typedef struct _PayloadTree PayloadTree;
typedef struct _Tree Tree;

Далее, некоторые вспомогательные функции:

Payload *createPayload(char *line, int series, int numElements)
{
   Payload * payload = (Payload *)malloc(sizeof(Payload));
   payload->line = line;
   payload->series = series;
   payload->numElements = numElements;
   return payload;
}

PayloadTree *createPayloadTree(Payload *p)
{
   PayloadTree * payloadTree = (PayloadTree *)malloc(sizeof(PayloadTree));
   payloadTree->payload = p;
   payloadTree->left = payloadTree->right = NULL;
   return payloadTree;
}

Tree *createTree(int numElements)
{
   Tree * tree = (Tree *)malloc(sizeof(Tree));
   tree->numElements = numElements;
   tree->payloadTree = NULL;
   tree->left = tree->right = NULL;
   return tree;
}

Теперь, чтобы добавить вещи в дерево. Сначала мы находим количество элементов корзины, затем в этом месте в соответствующей серии блоков (PayloadTree)

void addPayloadToPayloadTree(Payload *p, PayloadTree *payloadTree)
{
   // these are sorted according to the value in 'series'
   if(payloadTree == NULL) return;

   PayloadTree *pt = payloadTree;
   while(pt != NULL)
   {
      // should this happen?
      if(p->series == pt->payload->series) break;
      else if(p->series < pt->payload->series)
      {
         if(pt->left == NULL) pt->left = createPayloadTree(p);
         else pt = pt->left;
      }
      else
      {
         if(pt->right == NULL) pt->right = createPayloadTree(p);
         else pt = pt->right;
      }
   }
}

// Main way to add a line to the tree
void addPayload(Payload *p, Tree **tree)
{
   if(*tree == NULL) *tree = createTree(p->numElements);

   Tree *t = *tree;
   while(t != NULL)
   {
      if(t->numElements == p->numElements) break;

      else if(t->numElements > p->numElements)
      {
         // look left
         if(t->left == NULL)
         {
            t->left = createTree(p->numElements);
            break;
         }
         t = t->left;
      }
      else
      {
         // look right
         if(t->right == NULL)
         {
            t->right = createTree(p->numElements);
            break;
         }
         t = t->right;
      }
   }

   // now t points to the right bucket
   if(t->payloadTree == NULL) t->payloadTree = createPayloadTree(p);
   addPayloadToPayloadTree(p, t->payloadTree);
}

Наконец методы печати. Печать справа налево:

void printPayloadTree(PayloadTree *pt)
{
   if(pt == NULL) return;

   printPayloadTree(pt->right);
   printf("%s\n", pt->payload->line);
   printPayloadTree(pt->left);
}

void printTree(Tree *t)
{
   if(t == NULL) return;

   printTree(t->right);
   printPayloadTree(t->payloadTree);
   printTree(t->left);
}

Я пропустил функции clear и реализацию main, потому что это, конечно, решать вам. Вот метод, который я использовал для разбора строки. Вы бы назвали его с parseLine(theLine, &series, &numElements), где вы ранее объявили series и numElements типа int.

void parseLine(char *line, int *series, int *numElements)
{
   char *tok = strtok(line, " ");
   int n = 0;
   while(tok != NULL)
   {
      if(tok[0] == '[')
      {
         // found the series
         tok[ strlen(tok) - 2 ] = '\0';
         *series = atoi(tok + 1);
      }
      else
      {
         n++;
      }
      tok = strtok(NULL, " ");
   }
   *numElements = n;
}
0 голосов
/ 11 мая 2010

Bucket сортирует их по номеру элемента (: считывает длину массива после анализа), затем выбирает сортировку, которая подходит вам по вкусу, для сортировки сегментов, или, что еще лучше, создайте бинарные деревья поиска по блокам, ключевым значением которых является число в скобках и вуаля. Проблема решена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...