我对用作输入的单词的小写有疑问。所以我的程序接受单词并按字母顺序对它们进行排序并删除重复项。但我想将单词更改为大写并将其降低为等于小写单词。
示例:Apple
更改为 apple
我的输入:
./a.out 橘子苹果香蕉苹果香蕉
我的输出:
Apple
Orange
apple
banana
这是我想要实现的目标
输出:
apple
banana
orange
这是我的代码
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[]) {
int i, j, k, size;
size = argc -1;
char *key;
char* a[argc-1];
for (i = 2; i < argc; i++) {
key = argv[i];
j = i-1;
while (j >= 1 && strcmp(argv[j], key) > 0) {
argv[j+1] = argv[j];
j--;
}
argv[j+1] = key;
}
if (argc > 1){
for (i = 1; i < argc;){
puts(argv[i]);
while (argv[++i] != NULL && strcmp(argv[i - 1], argv[i] ) == 0)
continue;
}
}
return 0;
}
最佳答案
您有一个单词列表,您希望将它们排序后输出,并且只输出唯一的单词。并且您想以不区分大小写的方式进行。
- 获取所有字符串到相同的大小写。
- 对字符串列表进行排序。
- 不要输出重复。
C 没有将字符串小写的内置函数,但它确实有小写字符:tolower .因此,我们编写了一个函数,通过遍历整个字符串并将每个字符小写化,从而将整个字符串小写化。
void str_lower(char *str) {
for( ; str[0] != NULL; str++ ) {
str[0] = (char)to_lower(str[0]);
}
}
然后我们需要排序。这是由内置 qsort 处理的功能。要使用它,您需要编写一个函数来比较两个字符串并像 strcmp 一样返回。 .事实上,您的比较函数只是对 strcmp
的包装。制作qsort
快乐。
int compare_strings( const void *_a, const void *_b ) {
/* The arguments come in as void pointers to the strings
and must be cast. Best to do it early. */
const char **a = (const char **)_a;
const char **b = (const char **)_b;
/* Then because they're pointers to strings, they must
be dereferenced before being used as strings. */
return strcmp(*a, *b);
}
为了处理任何数据类型,比较函数采用空指针。它们需要被转换回 char 指针。它没有传递字符串 ( char *
),它传递了一个指向字符串 ( char **
) 的指针,因此它可以处理任何数据类型。所以a
和 b
需要取消引用。这就是为什么 strcmp(*a, *b)
.
调用 qsort
意思是告诉它你要排序的数组,项目的数量,每个元素有多大,以及比较函数。
qsort( strings, (size_t)num_strings, sizeof(char*), compare_strings );
习惯这种东西,你会经常使用它。这就是您在 C 中使用泛型列表的方式。
最后一 block 是只输出唯一的字符串。由于您已对它们进行排序,因此您可以简单地检查前一个字符串是否与当前字符串相同。前一个字符串是 strings[i-1]
但一定不要尝试检查 strings[-1]
.有两种方法可以解决这个问题。首先是仅在 i < 1
时进行比较.
for( int i = 0; i < num_strings; i++ ) {
if( i < 1 || strcmp( strings[i], strings[i-1] ) != 0 ) {
puts(strings[i]);
}
}
另一种方法是始终输出第一个字符串,然后从第二个开始循环。
puts( strings[0] );
for( int i = 1; i < num_strings; i++ ) {
if( strcmp( strings[i], strings[i-1] ) != 0 ) {
puts(strings[i]);
}
}
这意味着一些重复的代码,但它简化了循环逻辑。这种权衡是值得的,复杂的循环意味着错误。我通过编写 if( i > 0 && strcmp ...
自己搞砸了第一个循环的检查)`.
您会注意到我没有使用 argv
……除了我。 strings
和 num_strings
只是一些簿记,所以我不必总是记住从 argv[1]
开始或使用 argv+1
如果我想传递字符串数组。
char **strings = argv + 1;
int num_strings = argc-1;
这避免了一大堆差一错误并降低了复杂性。
我想你可以从那里把各个部分组合起来。
关于C大写转小写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40750121/