在C中使用函数

xbp102n0  于 2023-06-05  发布在  其他
关注(0)|答案(5)|浏览(147)

当我输入The quick brown fox jumps over the lazy dog时,下面的程序打印not a pangram。然而,我希望s是26,并且printf("pangram")将被执行。我做错了什么?

#include <ctype.h>
#include <stdio.h>
#include <string.h>

char findpan(char arr[]) {
    int i, j, count = 0;
    for (i = 0; i < strlen(arr); i++) {
        if (isalpha(arr[i]))
            count++;
    }
    for (i = 0; i < strlen(arr); i++) {
        for (j = i + 1; j < strlen(arr); j++) {
            if (arr[i] == arr[j])
                count--;
        }
    }
    return (count);
}

int main() {
    int s;
    char str[60];
    fgets(str, 60, stdin);
    s = findpan(str);
    if (s == 26)
        printf("pangram");
    else
        printf("not a pangram");
    return 0;
}
lkaoscv7

lkaoscv71#

如果我已经理解了你想做什么,那么这些嵌套循环

for (i = 0; i < strlen(arr); i++) {
    for (j = i + 1; j < strlen(arr); j++) {
        if (arr[i] == arr[j])
            count--;
    }
}

是不正确的。假设你有一个字符串“AAA”。所以在前面的循环之后计数将等于3。
现在在这些嵌套循环之后,count将等于0而不是1。也就是说,当i = 0时,对于j = 1和j = 2,arr[j]等于arr[i]。因此计数将减少两倍。当i = 1时,则对于j = 2,再次arr[j] = arr[i],并且count将再减少一个。
你也应该忽略字母的情况。
我可以建议如下函数实现,如下面的演示程序所示。

#include <stdio.h>
#include <ctype.h>

size_t findpan( const char *s )
{
    size_t count = 0;
    
    for ( const char *p = s; *p; ++p )
    {
        if ( isalpha( ( unsigned char ) *p ) )
        {
            char c = tolower( ( unsigned char )*p );
            
            const char *q = s;
            while ( q != p && c != tolower( ( unsigned char )*q ) ) ++q;
            
            if ( q == p ) ++ count;
        }
    }
    
    return count;
}

int main(void) 
{
    printf( "%zu\n", findpan( "The quick brown fox jumps over the lazy dog" ) );
    
    return 0;
}

程序输出为

26

如果不使用指针,函数可以如下所示

size_t findpan( const char *s )
{
    size_t count = 0;
    
    for ( size_t i = 0; s[i] != '\0'; i++ )
    {
        if ( isalpha( ( unsigned char ) s[i] ) )
        {
            char c = tolower( ( unsigned char )s[i] );
            
            size_t j = 0;
            while ( j != i && c != tolower( ( unsigned char )s[j] ) ) ++j;
            
            if ( j == i ) ++count;
        }
    }
    
    return count;
}
arknldoa

arknldoa2#

简单解决方案?

这里有一个简单的解决方案,我猜你可能只是想知道它还是不是一个pangram,所以我把你的函数改成了boolean

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

bool findpan(char arr[]) {
    int i,j;
    for (i = 'a'; i < 'z'; ++i) { // goes through the alphabet
        for (j = strlen(arr); j > 0; j--) // goes through the arr[] 
            if (tolower(arr[j]) == i) // checks if the letter exists
                break; // breaks the inner for-loop if letter found
          
        if (j == 0) // if letter not found
            return false;  
    }
    return true;
}

int main() {
    bool isPangram;
    char str[60];
    
    fgets(str, 60, stdin);
    isPangram = findpan(str);
    
    if (isPangram)
        printf("pangram");
    else
        printf("not a pangram");
    return 0;
}

说明

  • *'a''z'表示Dec**小数中小写字母的范围,在ASCII table中:
for (i = 'a'; i < 'z'; ++i)

tolowerarr[j]char字符转换为小写,然后将其与i进行比较:

if (tolower(arr[j]) == i)

stdbool.h是为了使用bool而引入的,也就是boolean:

#include <stdbool.h>
2ledvvac

2ledvvac3#

限制自己使用纯ASCII,您可以创建一个简单的数组,每个字母一个元素,每个元素初始化为零。然后循环遍历字符串,并为每个字母将其转换为数组的索引,并增加相应的元素值。
输入字符串完成后,循环遍历数组,并为每个非零值增加一个计数器,然后返回该值。
也许是这样的:

#include <stdio.h>
#include <ctype.h>

int main(void)
{
    char input[512];

    if (!fgets(input, sizeof input, stdin))
        return 1;  // Failed to read input

    int letters[26] = { 0 };  // 26 letters in the English alphabet

    for (unsigned i = 0; input[i] != '\0'; ++i)
    {
        if (isalpha(input[i]))
        {
            // Limiting myself to e.g. plain ASCII here
            ++letters[tolower(input[i]) - 'a'];
        }
    }

    // Count the number of non-zero elements in the letters array
    unsigned counter = 0;
    for (unsigned i = 0; i < 26; ++i)
    {
        counter += letters[i] != 0;
    }

    // Print result
    printf("Counter = %d\n", counter);
}

对于示例输入(The quick brown fox jumps over the lazy dog),它输出

Counter = 26

这只对输入字符串进行一次遍历,然后对letters数组进行一次遍历。没有嵌套循环,没有多次传递输入字符串。

am46iovg

am46iovg4#

如果我们假设8位字符,并且可以暂时在堆栈上分配256个字节,那么这是可读的,紧凑的并且相当有效:

bool is_pangram (const char* str)
{
  char used [256]={0};
  for(; *str!='\0'; str++)
  {
    used[*str]=1;
  }
  return memchr(&used['a'], 0, 26)==NULL; // 26 letters in the alphabet
}

256字节的清零可能看起来效率很低,但主流的x86编译器在16条指令中运行它。该函数也不假设'a''z'相邻。要添加对大写字母的支持,只需执行used[tolower(*str)]=1;,尽管这可能会引入大量分支。
测试代码:

#include <stdio.h>
#include <stdbool.h>
#include <string.h>

bool is_pangram (const char* str)
{
  char used [256]={0};
  for(; *str!='\0'; str++)
  {
    used[*str]=1;
  }
  return memchr(&used['a'], 0, 26)==NULL;
}

int main (void) 
{
  const char* test_cases[] = 
  {
    "",
    "hello, world!",
    "the quick brown fox jumps over the lazy dog",
    "the quick brown cat jumps over the lazy dog",
    "junk mtv quiz graced by fox whelps",
    "public junk dwarves hug my quartz fox",
  };

  for(size_t i=0; i<sizeof test_cases/sizeof *test_cases; i++)
  {
    printf("\"%s\" is %sa pangram\n", test_cases[i], is_pangram(test_cases[i])?"":"not ");
  }

  return 0;
}
u0sqgete

u0sqgete5#

要检查一个字符串是否是一个Pangram,即它是否包含英语字母表中的所有字母,那么你可以检查下面的步骤如何在C中实现这一点。
1.初始化一个包含英语字母表中所有字符的大小为26的布尔数组,并将其设置为false
1.循环遍历输入字符串中的字符,并在上面声明的数组中将该字符的索引设置为true
1.循环遍历上面修改过的布尔数组,并检查是否有任何值为false。如果任何索引处的值为false,则向调用函数返回false。
1.在上面的循环之外返回一个真布尔值,如果数组中没有任何值为假,则将到达该语句。
分析下面的C代码以获得更多细节。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

//implement pangram function
bool isPangram(char * chr){
    /*1. declare an array of booleans equal to the size of the English alphabet 
      2. each index represents a corresponding character in the English alphabet
      3. When the boolean value in an index is set to true then that means, the character for that index in the alphabet exists in the input string 
    */
    bool alphas[26] = {false};
    //loop through characters in that string and update its value in the array
    for(int i=0;chr[i]!='\0';i++){
        //get the char at this index
        char c = chr[i];
        //check if its in the alphabet
        if(c>='a' && c<='z'){
            //get the index of that letter 
            int index = c-'a';
            //set that index to true in our array
            alphas[index] = true;
          //process capital letters
        }else if(c>='A' && c<='Z'){
            int index = c-'A';
            //set that index to true
            alphas[index] = true;   
        }
    }
    //loop through the boolean array and check for false(es) if any
    for(int i=0;i<26;i++){
        if(alphas[i]== false){
            return false;
        }
    }
    return true;
}
int main(int argc, char *argv[])
{
    //initialize an input string 
    char buff[1000];
    //read input from the user
    fgets(buff, sizeof(buff),stdin);
    //check if string is pangram
    if(isPangram(buff)){
        printf("%s %s",buff, " is a pangram");
    }else{
            printf("%s %s",buff, " is not a pangram");
    }
}

你可以用来检查输入字符串是否是pangram的最常见的输入字符串是The quick brown fox jumps over the lazy dog

相关问题