当我输入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;
}
发布于 2021-06-30 20:09:56
简单的解决办法?
这里是一个简单的解决方案,,我猜您可能只是想知道它是还是不是,所以我已经将函数更改为布尔1:
#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' to 'z'以Decimal数字表示小写字母的范围,以ASCII表表示
for (i = 'a'; i < 'z'; ++i)
tolower
将arr[j]
char字符转换为小写和,然后将其与I进行比较:
if (tolower(arr[j]) == i)
stdbool.h
是为使用bool
(boolean)而引入的:
#include <stdbool.h>
发布于 2021-06-30 19:40:38
如果我知道你想做什么,那么这些嵌套循环
for (i = 0; i < strlen(arr); i++) {
for (j = i + 1; j < strlen(arr); j++) {
if (arr[i] == arr[j])
count--;
}
}
是不正确的。假设您有字符串"AAA“。因此,在前面的循环计数之后,将等于3。
在这些嵌套循环之后,计数将等于0而不是1,即i=0,对于j=1和j=2,arrj等于arri。所以计数会减少两倍。当i=1时,对于j=2,arrj = arri和计数将再减少一次。
此外,似乎你应该忽略信件的情况。
我可以建议下面的函数实现,如下面的演示程序所示。
#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;
}
发布于 2021-07-01 10:07:21
如果我们假设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;
}
https://stackoverflow.com/questions/68200504
复制相似问题