簡體   English   中英

str[i - 1] == ' ' 是什么意思?

[英]What does str[i - 1] == ' ' mean?

我一直在審查一個將字符串中每個單詞的首字母大寫的程序。 例如, "every single day"變成"Every Single Day"

我不明白部分str[i - 1] == ' ' 那有什么作用?

#include <stdio.h>

char    *ft_strcapitalize(char *str)
{
    int i;

    i = 0;
    while (str[i] != '\0')
    {
        if ((i == 0 || str[i - 1] == ' ') &&
                (str[i] <= 'z' && str[i] >= 'a'))
        {
            str[i] -= 32;
        }
        else if (!(i == 0 || str[i - 1] == ' ') &&
                (str[i] >= 'A' && str[i] <= 'Z'))
        {
            str[i] += 32;
        }
        i++;
    }
    return (str);
}

int   main(void)
{
  char str[] = "asdf qWeRtY ZXCV 100TIS";

  printf("\n%s", ft_strcapitalize(str));
  return (0);
}

i是您正在考慮大寫的當前字符的字符串中的索引(記住它從 0 開始)。

i-1是您正在考慮的前一個字符的字符串中的索引。

str[i-1]是您正在考慮的字符之前的 position 中的字符。

== ' '將該字符與空格字符進行比較。

所以str[i-1] == ' '意思是“這個左邊的字符是空格嗎?”

str[i - 1] == ' '是什么意思?

' '是空白字符的字符常量(ASCII 值 32)。

str是調用者中指向char的指針。 (實際上,它應該指向一個char數組,其中包含一個字符串,而不僅僅是一個char )。

i是櫃台。


請注意,C 語法允許您對指針使用數組表示法。 因此, str[1]等於*(str + 1)

str[i - 1] [i - 1]中的 [i - 1] 表示您在元素str[i]指向之前訪問該元素。

指向的元素str[i - 1]與空白字符進行比較(如果指向的元素str[i - 1]實際上包含空白)。

如果是這種情況,則條件評估為true ,否則條件為false


旁注:

  • 請注意,當i == 0時, str[i - 1]可能很危險。 然后,您將嘗試在指向數組的范圍之外訪問 memory。 但是在您的情況下,這是安全的,因為str[i - 1] == ' '僅在i == 0不是true時才被評估,這要歸功於邏輯 OR || .

     if ((i == 0 || str[i - 1] == ' ')

    因此,您的代碼中考慮了這種情況。

  • str[i] -= 32; 相當於str[i] -= 'a' - 'A'; . 后一種形式可以提高可讀性,因為大寫性質成為焦點。

它正在檢查空格,或者更准確地說,檢查行

if ((i == 0 || str[i - 1] == ' ')

檢查我們是否正在查看字符串開頭或其前一行是否為空格,即檢查是否遇到了新單詞。 在字符串“ e very single day”中, i = 0在粗體 position 處,在下一種情況下,
"every s ingle day", i = 6 and str[i-1] is ' '標記遇到一個新詞

在這里,您將str[i-1]與字符space進行比較,其 ASCII 碼為 32。

例如

if(str[i-1] == ' ')
{
 printf("Hello, I'm space.\n");
}
else
{
 printf("You got here, into the false block.\n");
}

執行此代碼段,如果比較結果為 1,則為真,否則為假。 str[] = "Ryan Mney"; 再對比一下你就明白了,這是怎么回事?

C 語言提供了許多有用的字符宏,它們可用於使代碼更便攜、更易讀。 盡管您正在查看的示例代碼不使用這些宏,但請考慮使用這些宏來使您的代碼更便攜、更健壯並且更易於其他人閱讀。

請使用 islower/isupper/isalpha 和 tolower/toupper 宏; 這些 ctype 宏使 C 語言字符串處理更易於閱讀。

  • islower(ch) - 檢查 ch 是否為小寫
  • isupper(ch) - 檢查 ch 是否為大寫
  • isalpha(ch) - 檢查 ch 是否為字母(小寫或大寫)
  • tolower(ch) - 將 ch 轉換為小寫(如果是字母)
  • toupper(ch) - 將 ch 轉換為大寫(如果是字母)

是的,它們是宏 - C 中 isupper 的宏定義是什么?

C 語言提供了“for”控制語句,它提供了一種很好的方式來表達字符串處理。 簡單的索引循環通常使用“for”而不是“while”來編寫。

#include <ctype.h>

char*
ft_strcapitalize(char *str)
{
    for( int i=0; (str[i] != '\0'); i++ )
    {
        if ((i == 0 || isspace(str[i - 1])) && islower(str[i]) )
        {
            str[i] = toupper(str[i]);
        }
        else if (!(i == 0 || str[i - 1] == ' ') && isupper(str[i]) )
        {
            str[i] = tolower(str[i]);
        }
    }
     return (str);
}

輕微的重構使代碼更具可讀性,

char*
ft_strcapitalize(char *str)
{
    for( int i=0; (str[i] != '\0'); i++ )
    {
        if( (i == 0 || isspace(str[i - 1])) )
        {
            if( islower(str[i]) ) str[i] = toupper(str[i]);
        }
        else if( !(i == 0 || isspace(str[i - 1]) )
        {
            if( isupper(str[i]) ) str[i] = tolower(str[i]);
        }
    }
    return(str);
}

或者,使用 isalpha(ch),

char*
ft_strcapitalize(char *str)
{
    for( int i=0; (str[i] != '\0'); i++ )
    {
        if( (i == 0 || isspace(str[i - 1])) )
        {
            if( isalpha(str[i]) ) str[i] = toupper(str[i]);
        }
        else if( !(i == 0 || isspace(str[i - 1]) )
        {
            if( isalpha(str[i]) ) str[i] = tolower(str[i]);
        }
    }
    return(str);
}

通過首先執行特殊情況(字符串的第一個字符)來進一步簡化條件表達式。

char*
ft_strcapitalize(char *str)
{
    if( islower(str[0]) ) str[0] = toupper(str[0]);

    for( int i=1; (str[i] != '\0'); i++ )
    {
        if( isspace(str[i - 1]) )
        {
            if( islower(str[i]) ) str[i] = toupper(str[i]);
        }
        else if( !isspace(str[i - 1]) )
        {
            if( isupper(str[i]) ) str[i] = tolower(str[i]);
        }
    }
    return(str);
}

同樣,備用 isalpha(ch) 版本,

char*
ft_strcapitalize(char *str)
{
    if( isalpha(str[0]) ) str[0] = toupper(str[0]);

    for( int i=1; (str[i] != '\0'); i++ )
    {
        if( isspace(str[i - 1]) )
        {
            if( isalpha(str[i]) ) str[i] = toupper(str[i]);
        }
        else if( !isspace(str[i - 1]) )
        {
            if( isalpha(str[i]) ) str[i] = tolower(str[i]);
        }
    }
    return(str);
}

更慣用的是,只需使用一個“狀態”標志來指示我們是否應該折疊為大寫或小寫。

char*
ft_strcapitalize(char *str)
{
    int first=1;
    for( char* p=str; *p; p++ ) {
        if( isspace(*p) ) {
            first = 1;
        }
        else if( !isspace(*p) ) {
            if( first ) {
                if( isalpha(str[i]) ) str[i] = toupper(str[i]);
                first = 0;
            }
            else {
                if( isalpha(str[i]) ) str[i] = tolower(str[i]);
            }
        }
    }
    return(str);
}

而你的主要測試驅動程序,

int   main(void)
{
    char str[] = "asdf qWeRtY ZXCV 100TIS";

    printf("\n%s", ft_strcapitalize(str));
    return (0);
}

' '是一個字符常量,表示執行集中空格字符的值。 使用' '而不是32可以提高系統的可讀性和可移植性,因為系統中空格的值可能與 ASCII 字符集中的值不同。 (i == 0 || str[i - 1] == ' ')如果i是空格分隔的單詞列表中單詞開頭的偏移量,則為真。

重要的是要盡可能簡單易讀。 當更具表現力的替代方案既簡單又便宜時,不建議使用像32這樣的魔法常數。 例如,您使用str[i] -= 32將小寫字符轉換為大寫:這個神奇的值32 (再次。)恰好是小寫字符和大寫字符之間的偏移量:這樣寫起來更易讀:

    str[i] -= 'a' - 'A';

類似地,您以相反的順序編寫了小寫和大寫的范圍測試:這容易出錯並且令讀者驚訝。

您還重復了單詞開頭的測試:僅在單詞開頭測試小寫字母並測試大寫字母,否則會使代碼更簡單。

最后,使用for循環比 function 中的while循環更簡潔,更不容易出錯,但我知道你們學校for本地編碼約定不允許循環 (.)。

這是修改后的版本:

#include <stdio.h>

char *ft_strcapitalize(char *str) {
    size_t i;

    i = 0;
    while (str[i] != '\0') {
        if (i == 0 || str[i - 1] == ' ') {
            if (str[i] >= 'a' && str[i] <= 'z') {
                str[i] -= 'a' - 'A';
            }
        } else {
            if (str[i] >= 'A' && str[i] <= 'Z') {
                str[i] += 'a' - 'A';
            }
        }
        i++;
    }
    return str;
}

int main(void) {
    char str[] = "asdf qWeRtY ZXCV 100TIS";

    printf("\n%s", ft_strcapitalize(str));
    return 0;
}

請注意,上面的代碼仍然假設字母從az以相同的順序形成兩個連續的塊。 這個假設適用於ASCII字符集,它在今天幾乎是通用的,但對於仍在某些大型機系統中使用的EBCDIC集僅部分如此,其中大小寫之間存在恆定偏移,但從az的字母不形成 a連續塊。

更通用的方法是使用<ctype.h>中的函數和宏來測試空格(空格和其他空格字符)、字符大小寫和轉換大小寫:

#include <ctype.h>

char *ft_strcapitalize(char *str) {
    for (size_t i = 0; str[i] != '\0'; i++) {
        if (i == 0 || isspace((unsigned char)str[i - 1]))
            str[i] = toupper((unsigned char)str[i]);
        else
            str[i] = tolower((unsigned char)str[i]);
    }
    return str;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM