如何对char的指针数组进行排序

时间:2015-12-01 18:51:59

标签: c arrays sorting pointers

新用户在这里进行堆叠交换,所以如果我不正确地问这个问题,我很抱歉。

我有一个创建程序的赋值,用于使用动态内存分配将用户输入的文本行分配给字符指针数组。

输入所有行后,将打印行。然后通过将第5行和第6行移动到末尾并且向前移动线('向上')来操纵它们。最后,行必须按字母顺序排序。我的问题在于:我无法获得一个排序函数来处理一个char指针数组。

我的代码发布在下面。我不确定我的sort函数是否正确引用了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;
}

2 个答案:

答案 0 :(得分: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);

答案 1 :(得分:0)

您的代码存在一些问题,特别是在处理指针和分配时,但最重要的是,您必须将其划分为更简单和有用的函数。 例如,当您应该编写函数时,您会多次重复代码来打印行:

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 */
}

您被分配使用动态分配,并且您显然希望将行存储在以null终止的char数组char**的数组中,大小足以存储40个(我认为)最多80个字符的行。但是,当你声明char *line_array[40];时,你会分配一个指向40个字符数组的指针,而不是指向char的40个指针。写一些函数代替:

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;
}

现在,要对比较两个字符串所需的行进行排序,但是重新编写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;
}

并在你的algorythm中使用它。顺便说一句,效率很低,但迟早你会学习(或谷歌)更好的选择。

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;
}

希望它有所帮助。