簡體   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