2010-04-30 41 views
0

我對C語法知之甚少,因此對以下要求只需要一點幫助。用C語言對數據進行排序

我在這樣

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 
    } 
} 
+3

您的意思是說,您想先按每行中的_number_個元素排序? – 2010-04-30 12:17:50

+0

請在此處和下面提供評論中所需的全部信息。 – 2010-05-10 14:27:44

+0

不知道你是如何提供100聲望的賞金。在聲譽上你和我差不多。小於60. – Gulshan 2010-05-14 16:39:38

回答

2

如果將問題分解爲小部分(如上所述),這是最容易的。這是一般工程(無論是軟件還是其他)的重要組成部分。

的問題是大致爲:

  • 讀取文件
  • 輸出結果
  • 計數在一條線上
  • 項目的數量在該行的末尾提取數
  • 存儲文件
  • 按行數排序文件數
  • 按文件末尾的數字排序文件

之後,它很簡單!

#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); 


} 
10

我想:

  1. 加載文本到內存中,作爲文本的大塊。
  2. 找到每行的開始,在數據塊中創建一個字符串指針數組。
  3. 通過查找「[number]」模式,編寫比較兩行的比較函數。我使用比較函數在我的線指針數組上調用qsort()
  4. 完成。 :)
+0

你能爲此提出一個代碼,那將會很棒。我真的厭倦了語法。 – 2010-04-30 12:18:13

+6

@ ANIL:這聽起來像是作業。如果你展示你的嘗試,並詢問爲什麼它不起作用,那麼人們會幫助你。如果你沒有表現出任何努力,人們將會無情。 – 2010-04-30 12:21:42

+1

@ ANIL,這裏涉及到一些工作。 Stackoverflow是一個問答網站,而不是一個車身商店。 – 2010-04-30 12:23:02

2

您可能會感興趣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

如果不嚴格必須這樣做,在C(這可能是這種情況,所以這是無關緊要的),你可以使用標準的UNIX工具:

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

「貓考」:不真正需要的,只是扔在管道上的文件 「sed ....」:複製在線開頭的胸罩中的最後一個號碼 「sort -n -r」:按照相反的順序排序第一個數字 「cut ...」:刪除行首的重複字段

從C中,您可以使用system(),它會在stdout上輸出結果,但是如果你需要在程序中讀回結果,你將需要更多的東西(管道..)

+0

它沒有考慮元素的數量。 – 2010-05-12 02:44:44

0

存儲桶通過元素編號(:讀取數組長度解析一次)對它們進行排序,然後選擇一種適合您的花式來排序桶的排序,或者更好的方法是使桶的二進制搜索樹的關鍵值是數量在括號內,和瞧。問題解決了。

0

這是我的答案。很抱歉代碼太多!

首先,一些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),您之前在此聲明seriesnumElements的類型爲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; 
}