c - 使用 fget 对字符串数组进行排序

标签 c arrays

我正在尝试创建一个程序,该程序采用整数值,然后确定可以输入的字符串数量,这会循环两次。输入两组字符串后,我的程序应该对它们进行排序,并根据它们的长度按降序排列输出它们。当我输出结果时,我没有得到我应该得到的结果。

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

int main(void)
{

    int i, num_of_str;
    //int j;
    //int a;
    //int n;
    char input[100];

    scanf("%d", &num_of_str);

    char** strings = malloc(num_of_str * sizeof(char*));

    for (i = 0; i < num_of_str; i++) {

        fgets(input, 100, stdin);
        strings[i] = malloc(strlen(input) * sizeof(char*));
        strcpy(strings[i], input);
    }

    scanf("%d", &num_of_str);

    for (i = 0; i < num_of_str; i++) {

        fgets(input, 100, stdin);
        strings[i] = malloc(strlen(input) * sizeof(char*));
        strcpy(strings[i], input);
    }

    int a;
    int b;
    char* temp;

    for (a = 0; a < num_of_str; a++) {
        for (b = a + 1; b < num_of_str; b++) {
            if (strlen(strings[a]) < (strlen(strings[b]))) {

                temp = strings[a];
                strings[a] = strings[b];
                strings[b] = temp;
            }
        }
    }

    for (a = 0; a < num_of_str; a++) {
        printf("%s\n", strings[a]);
    }
    return EXIT_SUCCESS;
}

最佳答案

以下是您的代码中的一些问题:

  • 返回指针malloc()没有被检查。需要检查为void*它的指针可以返回 NULL如果不成功。您可以查看malloc()像这样:

    ptr = malloc(......);
    if (ptr == NULL) {
        /* handle error */
    }
    
  • 返回值scanf()没有被检查。这需要检查 numstr 是否有 1 个整数值被找到。您可以这样验证:

    if (scanf("%d", &numstr) != 1) {
        /* handle error */
    }
    
  • strings[i]没有被正确分配。因为这是 char*指针,需要分配多个char字节,而不是 char*指针。您还需要添加+1到您的分配,以确保它们有足够的空间用于空终止符 \0 。所以代替:

    strings[i] = malloc(strlen(input) * sizeof(char*));
    

    你可以这样做:

    strings[i] = malloc(strlen(input)+1);
    

    注意: sizeof(char)始终为 1,因此无需在此处包含它。

  • 您的代码未更新 **strings在第二个numstr 。如果 numstr 这将导致问题最终变得更大,您将访问超出 **strings 的限制。您可能需要使用 realloc(3) 在这里,调整你的内存块的大小。执行此操作的一种方法是跟踪第一个 numstr ,然后对照第二个 numstr 进行检查,如果它们不同,则调整 strings 的大小。 这是一个例子:

    prev_numstr = numstr;
    
    printf("Enter number of strings for set 2:\n");
    if (scanf("%zu ", &numstr) != 1) {
        /* handle exit */
    }
    
    if (numstr != prev_numstr) {
        void *temp = realloc(strings, numstr * sizeof(*strings));
        if (temp == NULL) {
            /* handle exit */
        }
        strings = temp;
    } 
    
  • scanf()留下 \n输入缓冲区中的字符,您需要在调用 fgets() 之前删除它。您只需添加一个空格即可 scanf("%d ", &num_of_str) ,这将消耗缓冲区中剩余的所有空白空间。

  • fgets()必须检查,因为它可以返回 NULL无法读取行的指针。它还附加了 \n缓冲区末尾的字符,因此您有时可能需要删除此换行符。

  • 使用 malloc() 进行的任何堆分配和realloc()必须用 free(3) 取消分配在最后。

  • void *malloc(size_t size)预计size_t ,最好使用size_t此处改为变量。

由于您的代码没有排序问题,因此这里是一些使用这些点的示例代码:

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

#define LINESIZE 100

int main(void) {
    char input[LINESIZE];
    size_t numstr, prev_numstr, slen;
    void *temp = NULL;

    printf("Enter number of strings for set 1:\n");
    if (scanf("%zu ", &numstr) != 1 || numstr < 1) {
        fprintf(stderr, "Invalid value\n");
        exit(EXIT_FAILURE);
    }

    char **strings = malloc(numstr * sizeof(*strings));
    if (strings == NULL) {
        fprintf(stderr, "Cannot allocate %zu strings\n", numstr);
        exit(EXIT_FAILURE);
    }

    /* Set 1 */
    for (size_t i = 0; i < numstr; i++) {
        if (fgets(input, LINESIZE, stdin) != NULL) {
            slen = strlen(input);

            /* removes newline */
            if (slen > 0 && input[slen-1] == '\n') {
                input[slen-1] = '\0';
            }

            strings[i] = malloc(strlen(input)+1);
            if (strings[i] == NULL) {
                fprintf(stderr, "Cannot allocate %zu bytes for string\n", strlen(input)+1);
                exit(EXIT_FAILURE);
            }

            strcpy(strings[i], input);
        }       
    }

    /* keeps track of previous number of strings */
    prev_numstr = numstr;

    printf("Enter number of strings for set 2:\n");
    if (scanf("%zu ", &numstr) != 1 || numstr < 1) {
        fprintf(stderr, "Invalid value\n");
        exit(EXIT_FAILURE);
    }

    /* only enters if size is different */
    if (numstr != prev_numstr) {
        temp = realloc(strings, numstr * sizeof(*strings));
        if (temp == NULL) {
            fprintf(stderr, "Cannot reallocate %zu spaces\n", numstr);
            exit(EXIT_FAILURE);
        }
        /* perhaps temp could could freed here */
        strings = temp;
    } 

    /* Set 2 */
    for (size_t i = 0; i < numstr; i++) {
        if (fgets(input, LINESIZE, stdin) != NULL) {
            slen = strlen(input);
            if (slen > 0 && input[slen-1] == '\n') {
                input[slen-1] = '\0';
            }

            strings[i] = malloc(strlen(input)+1);
            if (strings[i] == NULL) {
                fprintf(stderr, "Cannot allocate %zu bytes for string\n", strlen(input)+1);
                exit(EXIT_FAILURE);
            }

            strcpy(strings[i], input);
        }       
    }

    /* printing and freeing strings */
    for (size_t i = 0; i < numstr; i++) {
        printf("%s\n", strings[i]);
        free(strings[i]);
        strings[i] = NULL;
    }

    /* freeing double pointer 'strings' itself */
    free(strings);
    strings = NULL;

    exit(EXIT_SUCCESS);
}

注意:我假设您仍然想接受 2 组,并用第二组覆盖第一组,但这确实看起来很奇怪。

关于c - 使用 fget 对字符串数组进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42552302/

相关文章:

c - 为什么 C 标准未定义不确定变量的使用?

无法理解为什么我不断收到此代码的段错误

c - C语言中free的奇怪(未定义?)行为

php - 将MySQL表与多维数组相关转换

c - 如何用C中的函数打印二维数组?

c - 如何在c中将数组的值从一个函数传递给另一个函数

php - 多个文本输入到 MySQL 数据库

c - 为什么我会遇到段错误(多维数组 C)

c - 如何用c通过rabbitmq发送和接收protobuf数据

arrays - Numpy argsort 同时区分 0 的值