如何基于C语言命令行参数实现字符串唯一字符保留(去重)
问题描述
我希望实现字符串的字符去重功能,即每个字母仅保留一个(例如输入"send more money"时输出"sendmory")。现有以下两段C语言代码:
第一段代码(读取命令行参数)
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { if (argc < 2) { printf("USAGE: <porgram name> <word sum>"); return 1; } for (int i = 1; i < argc; i++) { printf("%s\n", argv[i]); //prints the command line input } return 0; }
我已编写好从标准输入读取字符串并完成去重的代码(如下所示),且结果正确,但不清楚如何修改为从命令行参数(argv)获取输入并实现相同功能,请问是需要将argv存入单独数组,还是直接对argv进行检查?具体该如何实现?
第二段代码(标准输入去重)
char str[100]; int i, j, k; printf("\n Please Enter any String : "); scanf("%s", str); for(i = 0; i < strlen(str); i++) { for(j = i + 1; str[j] != '\0'; j++) { if(str[j] == str[i]) { for(k = j; str[k] != '\0'; k++) { str[k] = str[k + 1]; } } } }
解决方案
不需要单独将argv存入数组,你可以根据需求选择两种实现方式:
方式1:合并所有命令行参数后整体去重
适合将所有输入的单词合并为一个字符串再去重的场景(比如你给出的"send more money"示例):
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { if (argc < 2) { printf("USAGE: %s <字符串1> <字符串2> ...\n", argv[0]); return 1; } // 计算所有参数的总长度,分配内存 int total_len = 0; for (int i = 1; i < argc; i++) { total_len += strlen(argv[i]); } char *combined_str = (char*)malloc(total_len + 1); if (combined_str == NULL) { perror("内存分配失败"); return 1; } combined_str[0] = '\0'; // 拼接所有命令行参数 for (int i = 1; i < argc; i++) { strcat(combined_str, argv[i]); } // 执行去重逻辑(修复原逻辑的小问题) int i, j, k; for(i = 0; i < strlen(combined_str); i++) { for(j = i + 1; combined_str[j] != '\0';) { if(combined_str[j] == combined_str[i]) { // 删除重复字符 for(k = j; combined_str[k] != '\0'; k++) { combined_str[k] = combined_str[k + 1]; } } else { // 仅当当前字符不重复时才移动j j++; } } } printf("去重结果:%s\n", combined_str); free(combined_str); return 0; }
方式2:逐个处理每个命令行参数的去重
如果需要分别对每个输入的单词去重并输出,可以将去重逻辑封装为函数,对每个argv元素单独处理:
#include <stdio.h> #include <stdlib.h> #include <string.h> // 封装去重函数 void remove_duplicates(char *str) { int i, j, k; for(i = 0; i < strlen(str); i++) { for(j = i + 1; str[j] != '\0';) { if(str[j] == str[i]) { for(k = j; str[k] != '\0'; k++) { str[k] = str[k + 1]; } } else { j++; } } } } int main(int argc, char *argv[]) { if (argc < 2) { printf("USAGE: %s <字符串1> <字符串2> ...\n", argv[0]); return 1; } for (int i = 1; i < argc; i++) { // argv指向只读内存,必须复制到可修改区域 char *temp_str = strdup(argv[i]); if (temp_str == NULL) { perror("内存分配失败"); return 1; } remove_duplicates(temp_str); printf("原字符串:%s → 去重后:%s\n", argv[i], temp_str); free(temp_str); } return 0; }
关键注意点
- 不能直接修改argv字符串:argv指向的是程序启动时的只读内存区域,强行修改会导致未定义行为,必须先复制到可写内存(如
strdup分配的空间)。 - 修复原去重逻辑的bug:原代码中删除字符后
j仍会自增,会跳过下一个待检查的字符,调整为仅当字符不重复时才移动j即可解决。
内容的提问来源于stack exchange,提问作者ds778104
相关产品推荐
相关产品推荐

