我遇到的问题是我的单词被用作输入。所以我的程序接受单词并按字母顺序对它们进行排序并删除重复项。但是我想改变单词大写并将它们降低到等于小写单词。
示例:Apple
更改为apple
我的意见:
./a.out Orange apple banana Apple banana
我的输出:
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;
}
答案 0 :(得分:3)
你有一个单词列表,你想输出它们排序,只有唯一的。而你想以不区分大小写的方式做到这一点。
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);
}
为了处理任何数据类型,比较函数采用void指针。他们需要被抛回char指针。并且它没有传递字符串(char *
)它传递了一个指向字符串(char **
)的指针,因此它可以处理任何数据类型。因此需要取消引用a
和b
。这就是为什么strcmp(*a, *b)
。
调用qsort
意味着告诉它要排序的数组,项目数,每个元素的大小以及比较函数。
qsort( strings, (size_t)num_strings, sizeof(char*), compare_strings );
习惯这种事情,你会经常使用它。这就是你如何使用C语言中的通用列表。
最后一部分是输出唯一的字符串。由于您对它们进行了排序,因此您只需检查前一个字符串是否与当前字符串相同。上一个字符串是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;
这可以避免大量的逐个错误并降低复杂性。
我认为你可以从那里把各个部分拼凑起来。
答案 1 :(得分:0)
有一组标准函数可用于检查和更改ctype.h
中的字符类型。您感兴趣的是tolower()
。您可以#include<ctype.h>
,然后在执行排序之前添加如下所示的代码段以预处理您的argv
:
for(i = 1; i < argc; i++) {
argv[i][0] = tolower(argv[i][0]);
}
这只会对每个单词的第一个字符进行操作。如果你需要标准化整个单词:
for(i = 1; i < argc; i++) {
for(j = 0; argv[i][j]; j++) {
argv[i][j] = tolower(argv[i][j]);
}
}
答案 2 :(得分:0)
愚蠢的我,在查看我的代码之后,我能够弄明白我意识到我可以做key[0] = tolower(key[0]);
之前我做了一个指针指向它。
for (i = 2; i < argc; i++) {
key = argv[i];
key[0] = tolower(key[0]);
j = i-1;
while (j >= 1 && strcmp(argv[j], key) > 0) {
argv[j+1] = argv[j];
j--;
}
argv[j+1] = key;
}
第一个字母的小写字母。如果我想小写所有字母,我会使用for循环。谢谢大家的贡献。 :)