我try 使用C中的argv从命令行中读取单词,然后根据它们的长度按降序对它们进行排序.然而,我的排序算法产生了意外的输出.

我使用的代码如下:

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

int main(int argc, char *argv[]) {

    for (int i = 1; i < argc - 1; i++) {
        for (int j = 1; j < argc - i - 1; j++) {
            if (strlen(argv[j]) < strlen(argv[j + 1])) {
                char temp_word[20];
                strcpy(temp_word, argv[j]);
                strcpy(argv[j], argv[j + 1]);
                strcpy(argv[j + 1], temp_word);
            }
        }
    }

    puts("\n");
    for (int i = 1; i < argc; i++) {
        printf("%s ", argv[i]);
    }

    return 0;
}
gcc test.c -o test
./test I put this words


puwordI wordI I  % 

不幸的是,输出被 destruct 了.我怀疑我的排序逻辑或处理命令行参数的方式可能有问题.谁能判断一下我的代码,并提供指导如何正确地按长度对单词进行排序?

推荐答案

您的代码有两个问题.首先,您试图交换argv数组中的content个字符串:这是行不通的,因为分配给要交换的两个字符串中的shorter的缓冲区不够大,不足以容纳来自longer的"替换",并且会因为缓冲区溢出而导致未定义的行为.相反,只要交换实际的指针即可.

第二,你没有测试整个数组;从两个for循环的极限中取出- 1.

下面是代码的更正版本:

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

int main(int argc, char* argv[])
{
    for (int i = 1; i < argc; i++) { // Use "argc" (not argc - 1)
        for (int j = 1; j < argc - i; j++) { // Similarly, no -1 here!
            if (strlen(argv[j]) < strlen(argv[j + 1])) {
                char* temp_word = argv[j];
                argv[j] = argv[j + 1];    // Just swap the pointers,
                argv[j + 1] = temp_word;  // not the string contents
            }
        }
    }

    puts("\n");
    for (int i = 1; i < argc; i++) {
        printf("%s ", argv[i]);
    }

    return 0;
}

编辑:根据关于修改argv个元素(如上面的代码)是否安全(或者它是否会导致未定义的行为)的 comments ,我提供了一个版本,如下所示,它首先生成copy的数组,然后使用它:

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

int main(int argc, char* argv[])
{
    // First, make a copy of the argv array ...
    char** argvCopy = malloc((size_t)argc * sizeof(char*));
    memcpy(argvCopy, argv, (size_t)argc * sizeof(char*));
    // Now sort that copy ...
    for (int i = 1; i < argc; i++) {
        for (int j = 1; j < argc - i; j++) {
            if (strlen(argvCopy[j]) < strlen(argvCopy[j + 1])) {
                char* temp_word;
                temp_word = argvCopy[j];
                argvCopy[j] = argvCopy[j + 1];
                argvCopy[j + 1] = temp_word;
            }
        }
    }

    puts("\n");
    for (int i = 1; i < argc; i++) {
        printf("%s ", argvCopy[i]);
    }

    free(argvCopy); // Don't forget to free the copy.
    return 0;
}

另请参阅此处的讨论:Is argv[n] writable?

C++相关问答推荐

getchar读css + z还是返回css?

MISRA C:2012 11.3违规强制转换(FLOAT*)到(uint32_t*)

将 typewriter LF打印到Windows终端,而不是隐含的CR+LF

为什么在Linux(特别是Ubuntu 20.04LTS)上,POSIX共享内存对象在重启后仍然存在,然后突然变成了根用户?

为什么在C中二维字符数组会有这样的行为?

为什么在4.9.37版的内核中,kfio还需要smp_wmb呢?

为什么cudaFree不需要数据 struct 的地址?

如何使用C for Linux和Windows的标准输入与gdb/mi进行通信?

如何使用指向 struct 数组的指针并访问数组中特定索引处的 struct

==284==错误:AddressSaniizer:堆栈缓冲区下溢

当b是无符号字符时,int a=(b<;<;2)>;>;2;和int a=b&;0x3F;之间有什么区别?

C语言中浮点数的取整方式浮点数尾数超过23位时如何取整剩余部分

C标准关于外部常量的说明

程序对大输入给出错误答案

为什么GCC 13没有显示正确的二进制表示法?

Matlab/Octave对conv2函数使用哪种方法?

atoi函数最大长-长误差的再创造

C 和 C++ 标准如何告诉您如何处理它们未涵盖的情况?

C/C++编译器可以在编译过程中通过按引用传递来优化按值传递吗?

C99 的 %zu 格式说明符不起作用