C大写转小写

标签 c pointers

我对用作输入的单词的小写有疑问。所以我的程序接受单词并按字母顺序对它们进行排序并删除重复项。但我想将单词更改为大写并将其降低为等于小写单词。

示例: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;
}

最佳答案

您有一个单词列表,您希望将它们排序后输出,并且只输出唯一的单词。并且您想以不区分大小写的方式进行。

  1. 获取所有字符串到相同的大小写。
  2. 对字符串列表进行排序。
  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);
}

为了处理任何数据类型,比较函数采用空指针。它们需要被转换回 char 指针。它没有传递字符串 ( char * ),它传递了一个指向字符串 ( char ** ) 的指针,因此它可以处理任何数据类型。所以ab需要取消引用。这就是为什么 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 ……除了我。 stringsnum_strings只是一些簿记,所以我不必总是记住从 argv[1] 开始或使用 argv+1如果我想传递字符串数组。

char **strings = argv + 1;
int num_strings = argc-1;

这避免了一大堆差一错误并降低了复杂性。


我想你可以从那里把各个部分组合起来。

关于C大写转小写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40750121/

相关文章:

c - Tic Tac Toe 阻止用户进入拍摄地点

c - 在 Linux 上使用 `splice`……其他系统还有什么?

android - C 编译器 "clang.exe"无法编译简单的测试程序

c - C线程自增安全吗?

Java反射嵌套方法不修改底层对象

c - 将不需要的数据保存到错误文件

c - 当我在 for 循环之外声明变量时,为什么我的代码不起作用?

C 错误 : invalid operands of types 'int*' and 'unsigned int' to binary 'operator*' |

c++ - 指针问题

c - 将 ptr 赋给 char 指针