繁体   English   中英

C大写到小写

[英]C upper case to lower case

我的小写字母出现问题,被用作输入。 因此,我的程序接受单词并将其按字母顺序排序,并删除重复项。 但是我想将单词大写更改为小写。

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

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

  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);
}

为了处理任何数据类型,比较函数采用void指针。 需要将它们强制转换回char指针。 而且它没有传递字符串( char * ),而是传递了指向字符串( char ** )的指针,因此它可以处理任何数据类型。 因此, ab需要取消引用。 这就是为什么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 ... )` if( i > 0 && strcmp ...了第一个循环的检查。


您会注意到我不使用argv ...除了我。 stringsnum_strings只是一些记账,所以如果我想传递字符串数组,我不必总是记住以argv[1]开头或使用argv+1

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

这样可以避免大量的一次性错误,并降低了复杂性。


我认为您可以从那里放在一起。

有一组标准函数用于检查和更改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]);
    }
}

愚蠢的我,在查看代码后意识到能够执行key[0] = tolower(key[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循环。 谢谢大家的贡献。 :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM