C:函数声明
C : Function Declaration
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int count_letters(string text[]);
int main(void)
{
string text= get_string("Please enter text: ");
printf("%i Letter(s) \n",countl);
}
int count_letters(string text[])
{
int countl= 0;
for (int i = 0, n = strlen(text); i < n; i++)
{
if (isalpha(text[i]) != 0)
{
countl++;
}
}
return countl;
}
大家好,我查阅了我的教科书和各种教育资源“如何在C中声明一个函数”,我仍然无法实现。在此代码中,我希望函数 count_letters 到 return 值“countl”,然后我可以将其打印在屏幕上。请帮助我了解如何正确声明此功能。
查看 cs50.h
header 了解 string
是如何定义的:
typedef char *string;
所以
int count_letters(string text[]);
定义了一个char
.
的指针数组
当索引 text[i]
时,编译器 returns 一个 string
而像 isalpha
这样的函数期望一个 char
。输入中的一维过多。
你只需要一个字符指针(常量也更好)。没有 cs50
包含,因为 count_letters
没有修改 text
数据,我会写:
int count_letters(const char *text);
所以如果你真的想使用 cs50
类型,请选择:
int count_letters(const string text);
因为 string
是类型 char *
的别名,所以这个函数声明
int count_letters(string text[]);
相当于声明
int count_letters( char * text[] );
这又等同于
int count_letters( char ** text );
所以在函数中,例如这些表达式
strlen(text)
和
isalpha(text[i])
是不正确的,因为在第一个表达式中使用的参数具有类型 char **
而不是类型 char *
并且在第二个表达式中参数具有类型 char *
而不是 char
.
而且 strlen
的调用是多余的。
函数应按以下方式声明和定义
size_t count_letters( string text );
和
size_t count_letters( string text )
{
size_t countl = 0;
for ( ; *text; ++text )
{
if ( isalpha(( unsigned char )*text ) ) ++countl;
}
return countl;
}
注意函数声明如下方式更正确
size_t count_letters( const char *text );
因为传递的字符串在函数中没有改变。写 const string text
没有意义,与 const char *
不一样
而且你忘了调用main中的函数。你必须写
printf("%zu Letter(s) \n", count_letters(text ) );
您的程序有两个主要问题。
1.
count_letters
的参数 text
类型错误。 string
是 char *
的 cs50.h
别名。 text
需要是 string
或 char *
或 char []
类型之一,在这种情况下作为函数参数等同于 char *
.
使用其中之一
int count_letters (string text)
或
int count_letters (char* text)
或
int count_letters (char text[])
但不是
int count_letters (string text[])
With string text[]
text
将是 char **
类型,这是错误的,因为您不想修改 count_letters
.[=52 中的指针本身=]
可选地,您也可以将指针 and/or 设为指向对象 const
以确保不会被误用或覆盖。
2.
您永远不会在 main
中调用函数 count_letters
。您需要调用它以获取其 returned 值。
int main(void)
{
string text = get_string("Please enter text: ");
printf("%i Letter(s) \n", count_letters(text));
}
旁注:
您应该将 isalpha()
的参数转换为 unsigned char
以确保在未传递适当的字符时不会出现 undefined behavior。
n = strlen(text); i < n;
在 count_letters
中的 for
循环中可以只用条件 text[i] != '[=39=]'
或更简单的 text[i]
.
由于您不打算提供负 return 值,因此您可以使用 return 类型的 unsigned int
或 size_t
check_letters
。您也需要将 main
中 printf()
调用中的格式说明符更改为 %u
for unsigned int
或 %zu
for size_t
.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
unsigned int count_letters (const string text);
int main (void)
{
const string text = get_string("Please enter text: ");
putchar('\n');
printf("%u Letter(s) \n", count_letters(text));
}
unsigned int count_letters (const string text)
{
unsigned int countl = 0;
for (unsigned int i = 0; text[i] ; i++)
{
if (isalpha((unsigned char)text[i]))
{
countl++;
}
}
return countl;
}
执行:
./a.out
Please enter text: hello
5 Letter(s)
参数的类型需要与您传递的表达式的类型相匹配 - 在这种情况下,您将传递类型 string
的表达式,因此原型需要是
int count_letters(string text)
要获得该计数,您必须调用 来自main
的函数。您可以在 printf
内调用:
printf("%i Letter(s) \n", count_letters(text));
或者您可以创建另一个变量来存储该结果:
string text = get_string( ... );
int len = count_letters( text );
printf( "%i Letter(s) \n", len );
变量 countl
是 count_letters
函数的局部变量,无法从 main
访问。
<无端咆哮>
CS50 string
typedef 名称是一个 谎言 因为它别名 不是字符串 ,并且在看够了之后参加CS50课程的人的问题我认为这实际上是学习C的障碍;它 完全 歪曲了字符串的表示和处理方式,如果您在本课程之外进行任何 C 编程,您将完全没有准备好如何处理字符串(以及 I/O 一般而言)实际工作。
放松点,这需要一段时间。
在 C 语言中,字符串 是一个包含零值 终止符 的字符序列。字符串 "hello"
表示为序列 {'h', 'e', 'l', 'l', 'o', 0}
.
字符串(包括像 "hello"
这样的字符串文字)存储在字符类型的数组中:
char text[] = "hello"; // array size is determined by the length of the initializer
或
char text[SOME_SIZE]; // where SOME_SIZE is large enough to store what we need
strcpy( text, "hello" );
由于字符串存储在数组中,您不能使用 =
运算符来分配它们(如上所示在初始化器之外,但这仅对 声明有效).您要么需要使用像 strcpy
(对于包含字符串的数组)或 memcpy
(对于包含任何其他内容的数组)这样的库函数,要么您需要单独分配每个元素:
text[0] = 'h';
text[1] = 'e';
...
text[5] = 0;
现在,在大多数情况下,类型为“T
的数组”(包括像 ”hello"
这样的字符串文字)的 表达式 将被转换为 (" decay”)到类型为“指向T
”的表达式,表达式的值将是第一个元素的地址。所以,如果我们调用一个像
这样的函数
count_letters( text );
写的完全一样
count_letters( &text[0] );
而count_letters
实际接收到的是指针类型char *
,我们将原型声明为
int count_letters( char *str ) {...}
当你写类似
的东西时
char *str = "hello";
您将字符串第一个字符的 地址 分配给 str
,而不是字符串内容本身。
string
是 cs50.h
中定义的类型 char *
的 typedef 名称或别名。它不是 C 语言或标准 C 库的一部分。问题是 char *
不是字符串 。它可能指向字符串的第一个字符。它可能指向 不是 字符串的序列的第一个字符。它可能指向一个不属于更大序列的单个字符。当我们处理字符串时,我们经常处理 char *
类型的表达式,但是 char *
类型的表达式本身并不是字符串。
get_string
函数(同样是 cs50
库的一部分,而不是标准的 C 库函数)在幕后执行了很多魔法 动态地 分配一个数组来存储字符串和 returns 一个 指针 到第一个元素(这是你实际分配的)。它很漂亮,很方便,但同样,它 完全 歪曲了 C 实际做事的方式。
无端咆哮>
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int count_letters(string text[]);
int main(void)
{
string text= get_string("Please enter text: ");
printf("%i Letter(s) \n",countl);
}
int count_letters(string text[])
{
int countl= 0;
for (int i = 0, n = strlen(text); i < n; i++)
{
if (isalpha(text[i]) != 0)
{
countl++;
}
}
return countl;
}
大家好,我查阅了我的教科书和各种教育资源“如何在C中声明一个函数”,我仍然无法实现。在此代码中,我希望函数 count_letters 到 return 值“countl”,然后我可以将其打印在屏幕上。请帮助我了解如何正确声明此功能。
查看 cs50.h
header 了解 string
是如何定义的:
typedef char *string;
所以
int count_letters(string text[]);
定义了一个char
.
当索引 text[i]
时,编译器 returns 一个 string
而像 isalpha
这样的函数期望一个 char
。输入中的一维过多。
你只需要一个字符指针(常量也更好)。没有 cs50
包含,因为 count_letters
没有修改 text
数据,我会写:
int count_letters(const char *text);
所以如果你真的想使用 cs50
类型,请选择:
int count_letters(const string text);
因为 string
是类型 char *
的别名,所以这个函数声明
int count_letters(string text[]);
相当于声明
int count_letters( char * text[] );
这又等同于
int count_letters( char ** text );
所以在函数中,例如这些表达式
strlen(text)
和
isalpha(text[i])
是不正确的,因为在第一个表达式中使用的参数具有类型 char **
而不是类型 char *
并且在第二个表达式中参数具有类型 char *
而不是 char
.
而且 strlen
的调用是多余的。
函数应按以下方式声明和定义
size_t count_letters( string text );
和
size_t count_letters( string text )
{
size_t countl = 0;
for ( ; *text; ++text )
{
if ( isalpha(( unsigned char )*text ) ) ++countl;
}
return countl;
}
注意函数声明如下方式更正确
size_t count_letters( const char *text );
因为传递的字符串在函数中没有改变。写 const string text
没有意义,与 const char *
而且你忘了调用main中的函数。你必须写
printf("%zu Letter(s) \n", count_letters(text ) );
您的程序有两个主要问题。
1.
count_letters
的参数 text
类型错误。 string
是 char *
的 cs50.h
别名。 text
需要是 string
或 char *
或 char []
类型之一,在这种情况下作为函数参数等同于 char *
.
使用其中之一
int count_letters (string text)
或
int count_letters (char* text)
或
int count_letters (char text[])
但不是
int count_letters (string text[])
With string text[]
text
将是 char **
类型,这是错误的,因为您不想修改 count_letters
.[=52 中的指针本身=]
可选地,您也可以将指针 and/or 设为指向对象 const
以确保不会被误用或覆盖。
2.
您永远不会在 main
中调用函数 count_letters
。您需要调用它以获取其 returned 值。
int main(void)
{
string text = get_string("Please enter text: ");
printf("%i Letter(s) \n", count_letters(text));
}
旁注:
您应该将
isalpha()
的参数转换为unsigned char
以确保在未传递适当的字符时不会出现 undefined behavior。n = strlen(text); i < n;
在count_letters
中的for
循环中可以只用条件text[i] != '[=39=]'
或更简单的text[i]
.由于您不打算提供负 return 值,因此您可以使用 return 类型的
unsigned int
或size_t
check_letters
。您也需要将main
中printf()
调用中的格式说明符更改为%u
forunsigned int
或%zu
forsize_t
.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
unsigned int count_letters (const string text);
int main (void)
{
const string text = get_string("Please enter text: ");
putchar('\n');
printf("%u Letter(s) \n", count_letters(text));
}
unsigned int count_letters (const string text)
{
unsigned int countl = 0;
for (unsigned int i = 0; text[i] ; i++)
{
if (isalpha((unsigned char)text[i]))
{
countl++;
}
}
return countl;
}
执行:
./a.out
Please enter text: hello
5 Letter(s)
参数的类型需要与您传递的表达式的类型相匹配 - 在这种情况下,您将传递类型 string
的表达式,因此原型需要是
int count_letters(string text)
要获得该计数,您必须调用 来自main
的函数。您可以在 printf
内调用:
printf("%i Letter(s) \n", count_letters(text));
或者您可以创建另一个变量来存储该结果:
string text = get_string( ... );
int len = count_letters( text );
printf( "%i Letter(s) \n", len );
变量 countl
是 count_letters
函数的局部变量,无法从 main
访问。
<无端咆哮>
CS50 string
typedef 名称是一个 谎言 因为它别名 不是字符串 ,并且在看够了之后参加CS50课程的人的问题我认为这实际上是学习C的障碍;它 完全 歪曲了字符串的表示和处理方式,如果您在本课程之外进行任何 C 编程,您将完全没有准备好如何处理字符串(以及 I/O 一般而言)实际工作。
放松点,这需要一段时间。
在 C 语言中,字符串 是一个包含零值 终止符 的字符序列。字符串 "hello"
表示为序列 {'h', 'e', 'l', 'l', 'o', 0}
.
字符串(包括像 "hello"
这样的字符串文字)存储在字符类型的数组中:
char text[] = "hello"; // array size is determined by the length of the initializer
或
char text[SOME_SIZE]; // where SOME_SIZE is large enough to store what we need
strcpy( text, "hello" );
由于字符串存储在数组中,您不能使用 =
运算符来分配它们(如上所示在初始化器之外,但这仅对 声明有效).您要么需要使用像 strcpy
(对于包含字符串的数组)或 memcpy
(对于包含任何其他内容的数组)这样的库函数,要么您需要单独分配每个元素:
text[0] = 'h';
text[1] = 'e';
...
text[5] = 0;
现在,在大多数情况下,类型为“T
的数组”(包括像 ”hello"
这样的字符串文字)的 表达式 将被转换为 (" decay”)到类型为“指向T
”的表达式,表达式的值将是第一个元素的地址。所以,如果我们调用一个像
count_letters( text );
写的完全一样
count_letters( &text[0] );
而count_letters
实际接收到的是指针类型char *
,我们将原型声明为
int count_letters( char *str ) {...}
当你写类似
的东西时char *str = "hello";
您将字符串第一个字符的 地址 分配给 str
,而不是字符串内容本身。
string
是 cs50.h
中定义的类型 char *
的 typedef 名称或别名。它不是 C 语言或标准 C 库的一部分。问题是 char *
不是字符串 。它可能指向字符串的第一个字符。它可能指向 不是 字符串的序列的第一个字符。它可能指向一个不属于更大序列的单个字符。当我们处理字符串时,我们经常处理 char *
类型的表达式,但是 char *
类型的表达式本身并不是字符串。
get_string
函数(同样是 cs50
库的一部分,而不是标准的 C 库函数)在幕后执行了很多魔法 动态地 分配一个数组来存储字符串和 returns 一个 指针 到第一个元素(这是你实际分配的)。它很漂亮,很方便,但同样,它 完全 歪曲了 C 实际做事的方式。
无端咆哮>