2015-12-01 31 views
0

新用戶堆棧交換在這裏,所以我道歉,如果我問這個問題不正確。如何排序指向char的指針數組

我有一個任務來創建一個程序,用於將用戶輸入的文本行分配給使用動態內存分配的字符指針數組。

一旦輸入了所有的行,行就會被打印回來。然後通過將第5行和第6行移動到末尾以及向前(「向上」)中間的行來操縱它們。最後,這些行必須按字母順序排序。我的問題在於:我無法獲得一個排序函數來處理一個char指針數組。

我的代碼張貼如下。我不確定我的排序函數是否正確地引用了char指針。我也不確定我的變量是否正確,並且我無法確定是否正確地將char字符串分配給char指針數組中的char指針。你能幫我解決這些問題嗎?

非常感謝, r4mulus

//Program to collect lines of text, shift them in various ways and sort them, and output all the lines at each stage 

// Declare libraries 

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

// Declaring macros 

#define len1 80 

// Prototpying functions 

void sortLine(char **, int size); 
void swap(char **, char **); 


// Main body of program 

int main (void){ 
    char *line_array[40]; 
    char *(*ptr_all) = &line_array[0]; 
    char buffer[80]; 
    int ch; 
    int counter = 0; 

    // Loop to intake lines of text 

    do { 
     // Ask user to input a line of text 

     printf("Please input a line of text to store into memory. Enter '#' to stop collecting lines:\n"); 
     fgets(buffer, len1+1, stdin); 

     // Check to make sure char '#' has not been entered 

     ch = buffer[0]; 
     if (ch == '#'){ 
      break; 
     } 

     // Measure the length of the line of text 

     unsigned long len = strlen(buffer); 

     // Allocate memory for the given line of text 

     line_array[counter] = (char *)malloc(len+1); 

     // Copy string in buffer into pointer to array of strings 

     strcpy(line_array[counter], buffer); 

     // Clear the buffer 

     for (int p = 0; p < (len1+1); p++){ 
      buffer[p] = '\0'; 
     } 

     // Increment the counter 

     counter++; 

    } while (counter < 40); 
    printf("\n"); 

    // Print the lines collected so far 

    for (int q = 0; q < counter; q++){ 
     printf("%s", line_array[q]); 
    } 
    printf("\n"); 

    // Move lines of text 5 and 6 to the end; Move all other following lines forward two line spaces 
    char *temp_ptr1; 
    char *temp_ptr2; 
    temp_ptr1 = line_array[4]; 
    temp_ptr2 = line_array[5]; 
    for (int r = 4; r < counter; r++){ 
     line_array[r] = line_array[r+2]; 
    } 
    line_array[counter-2] = temp_ptr1; 
    line_array[counter-1] = temp_ptr2; 

    // Print the rearranged lines 

    for (int s = 0; s < counter; s++){ 
     printf("%s", line_array[s]); 
    } 
    printf("\n"); 

    // Sort the lines alphabetically 

    sortLine(ptr_all, counter); 

    // Print the lines sorted alphabetically 

    for (int t = 0; t < counter; t++){ 
     printf("%s", line_array[t]); 
    } 
    printf("\n\n"); 

    // End the program 

    return 0; 
} 

功能

// Function to sort elements in an array 

void sortLine(char **a, int size){ 
    int i, j, compare; 
    for (i = 0; i < size; i++){ 
     for (j = i; j < size; j++){ 
      compare = strcasecmp((a[i]), (a[j])); 
      if (compare > 0) 
       swap(&a[i], &a[j]); 
     } 
    } 
} 

// Function to swap elements in an array 

void swap(char **a, char **b){ 
    char *temp = *a; 
    *a = *b; 
    *b = temp; 
} 
+0

您提供了太多的代碼。請提供一個簡短的示例程序,最低要求。 – Dai

+0

我在排序函數的任何地方都看不到'strcmp()'。另外,一般來說,你可以使用'buffer'而不是'&buffer [0]' –

+0

@WeatherVane是否必須與'strcmp()?'相比較?我想我可以通過引用提取第一個字符,但我不知道如何。我們應該儘可能少地使用這些庫函數。 – r4mulus

回答

0

計數的事實,新行會低於任何文本字符,你可以使用memcmp比較線。

void swap(char **a, char **b); 

void sortLine(char *a[], int size){ 
    int i, j; 
    for (i = 0; i < size; i++){ 
     for (j = i + 1; j < size; j++){ 
      if(memcmp(a[i], a[j], 80) > 0){ 
       swap(&a[i], &a[j]); 
      } 
     } 
    } 
} 

void swap(char **a, char **b){ 
    char *temp = *a; 
    *a = *b; 
    *b = temp; 
} 

調用應該是:

sortline(line_array, counter); 
+0

謝謝@rcgldr,但我在memcmp調用時得到了「Thread1:Exc_Bad_Address(Code = 1,Bad_Address = 0x0)」...... – r4mulus

+0

@ r4mulus - sortline()調用中的第二個參數應該是counter,而不是counter + 1。第一個參數可以是line_array。不需要使用ptr_all。我更新了我的答案以表明這一點。 – rcgldr

+0

謝謝!我實際上最終使用了strcasecmp(),而不是關於循環邏輯和函數調用錯誤!我現在開始工作了! – r4mulus

0

你的代碼中有一些問題,指針和分配處理expecially的時候,但最重要的是,你必須給它更多的simplier和有用的功能劃分。 比如你repeted幾次代碼打印線,當你應該寫的函數:

void printLines(char ** ppc, unsigned int n) { 
    for (int i = 0; i < n; i++) { 
     printf("%s", ppc[i]); 
    } 
    printf("\n");  /* Adds always an empty line at end */ 
} 

你被分配到使用動態分配的,你顯然希望將線存儲空數組終止的字符數組,char**,足夠大以存儲40個(我認爲)最多80個字符的行。但是,當你聲明char *line_array[40];時,你分配一個指向40個字符數組的指針,而不是40個指向char的指針。寫一些功能來代替:

char ** allocLines(unsigned int n) { 
    char ** ppc = (char **) malloc(n * sizeof(char *)); 
    if (!ppc) { 
     printf("Error, unable to allocate memory for %d lines, malloc returned a null pointer!\n",n); 
     exit(1); 
    } 
    return ppc;  
} 

char * allocLine(unsigned int n) { 
    char * pc = (char *) malloc((n + 1) * sizeof(char)); 
     if (!pc) { 
      printf("Error, unable to allocate memory for %d chars, malloc returned a null pointer!\n",n + 1); 
      exit(1); 
     } 
} 

void freeLines(char ** ppc, unsigned int n) { 
    if (ppc) { 
     for (int i = 0; i < n; i++) 
      if (ppc[i]) free(ppc[i]); 
     free(ppc); 
    } 
} 

,並利用它們在另一個函數讀取行:

unsigned int readLines(char ** ppc, unsigned int max, FILE * stream) { 
    unsigned int counter = 0; 
    unsigned int length_of_line; 
    char buffer[MAX_LINE_LENGTH]; 
    char *pc; 

    printf("Please, input up to %d lines of text to store into memory. Enter '#' to stop collecting lines:\n", max); 
    while (counter < max 
      && fgets(buffer, MAX_LINE_LENGTH, stream)) { 
              /* fgets return NULL if no character is read when reaching EOF. Usefull if you read a file instead of stdin */ 
     if (buffer[0] == '#') break;  /* stop reading lines if user enter # */ 

     length_of_line = strlen(buffer); 
     pc = allocLine(length_of_line);  /* It automatically adds the extra space for the '\0' terminator */      
     strcpy(pc,buffer);   /* You can easily write your own version of strlen() and strcpy() if you're not allowed to use too many library functions */ 
     ppc[counter] = pc;   /* You don't really need pc, you can use ppc[counter] directly */ 
             /* Why do you clear the buffer? its values are overwritten by fgets() */ 
     counter++;     
    } 
    return counter; 
} 

現在,你需要比較兩個字符串的行進行排序,但insted的rewriing srtcmp我覺得你可以編寫更專門的功能:

char isFirstStringGreater(char * a, char * b) { 
    int i = 0; 
    while(a[i]!='\0' && b[i]!='\0') { 
     if (a[i] < b[i]) return 0; 
     else if (a[i] > b[i]) return 1; 
     i++; 
    } 
    return a[i]=='\0' ? 0 : 1; 
} 

並在你的排序algorory中使用它。順便說一句,這是相當低效的,但遲早你會學習(或谷歌)更好的選擇。

void sortLines(char ** a, int n) { 
    int i, j; 
    for (i = 0; i < n; i++){ 
     for (j = i + 1; j < n; j++) { 
      if (isFirstStringGreater(a[i], a[j])) 
       swap(&a[i], &a[j]); 
     } 
    } 
} 

你寫的swap(),正如我已經提到的,並沒有真正交換數組。

void swap(char ** a, char ** b) { 
    char * temp; 
    temp = *a; 
    *a = *b; 
    *b = temp; 
} 

滑動的元素,你被要求做的,你能想到概括先前的功能:

void shiftNLinesToEnd(char ** ppc, unsigned int s, unsigned int n, unsigned int max) { 
    char ** temp = allocLines(n); 
    unsigned int i; 

    for (i = 0; i < n; i++) 
     temp[i] = ppc[s+i]; 
    for (i = s + n; i < max; i++) /* it would be a good idea to check if max > n + s... */ 
     ppc[i-n] = ppc[i]; 
    for (i = 0; i < max; i++) 
     ppc[max - n + i] = temp[i]; 
    free(temp); 
} 

現在,你可以寫一個更清潔,更可讀的(我認爲)的main() :

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

void swap(char ** a, char ** b); 
void sortLines(char ** a, int size); 
char isFirstStringGreater(char * a, char * b); 
unsigned int readLines(char ** ppc, unsigned int max, FILE * stream); 
void printLines(char ** ppc, unsigned int n); 
void shiftNLinesToEnd(char ** ppc, unsigned int s, unsigned int n, unsigned int max); 
char ** allocLines(unsigned int n); 
char * allocLine(unsigned int n); 
void freeLines(char ** ppc, unsigned int n); 

#define MAX_LINE_LENGTH  82 /* enough space to store up to 80 character plus '\n', plus the '\0' */ 
#define MAX_N_OF_LINES  40 

int main(void) { 
    char **lines; 
    unsigned int n_of_lines; 

    lines = allocLines(MAX_N_OF_LINES); 
    n_of_lines = readLines(lines, MAX_N_OF_LINES,stdin); 

    printf("\n%d lines read:\n\n",n_of_lines);       
    printLines(lines, n_of_lines); 

    shiftNLinesToEnd(lines, 4, 2, n_of_lines); 
    printf("Rearranged, lines 5 and 6 have been moved to the end:\n\n"); 
    printLines(lines, n_of_lines); 

    sortLines(lines, n_of_lines); 
    printf("Alphabetically sorted:\n\n"); 
    printLines(lines, n_of_lines); 

    freeLines(lines, n_of_lines);  /* free memory before finish */ 
    return 0; 
} 

希望它有幫助。