为什么strlen(s)与s的大小不同,为什么cout-char显示的是字符而不是数字

Why is strlen(s) different from the size of s, and why does cout char display a character not a number?

本文关键字:为什么 数字 cout-char 显示 字符 strlen      更新时间:2023-10-16

我写了一段代码来计算一堆单词中有多少'e'字符。

例如,如果我键入"I read the news",那么有多少个e的计数器应该是3。

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char s[255],n,i,nr=0;
cin.getline(s,255);
for(i=1; i<=strlen(s); i++)
{
if(s[i-1]=='e') nr++;
}
cout<<nr;
return 0;
}

关于C++中的字符,我有两件不清楚的事情:

  1. 在上面的代码中,如果我用255替换strlen(s),我的代码就不起作用了。我只能键入一个单词,程序就会停止。我在学校里被教导strlen(s)是字符串s的长度,在这种情况下,正如我所宣称的,它是255。那么,为什么我不能只键入255,而不是strlen(s)呢?

  2. 如果我正常运行上面的程序,它不会像它应该做的那样向我显示数字。它会向我显示一个字符(我相信它来自ASCII表,但我不确定),就像一颗心或一颗钻石。它应该从单词中打印出e的编号。

有人能向我解释一下吗?

  1. strlen(s)为您提供s变量中包含的字符串的长度,最长可达第一个NULL字符。因此,如果您输入"hello",则长度将为5,即使s的容量为255
  2. CCD_ 12被显示为字符,因为它被声明为CCD_。例如,要么将其声明为int,要么在couting时将其强制转换为int,您就会看到一个数字

strlen()计算字符串的实际长度-第一个字符(标记字符串结束)之前的实际字符数。

所以,如果你输入"你好":

sizeof(s) == 255
strlen(s) == 5

对于第二个问题,您将nr声明为char类型。CCD_ 20将CCD_ 21识别为单个字母并尝试将其打印为单个字母。在打印前将变量声明为int类型或强制转换以避免这种情况。

int nr = 42;
std::cout << nr; 
//or
char charNr = 42;
std::cout << static_cast<int>(charNr);

其他人未提及的其他错误,以及注意事项:

  • 在尝试使用结果之前,您应该始终检查流操作是否成功
  • i被声明为char,并且在通用平台上不能保持大于127的值。通常,char的最大值可以作为CHAR_MAXstd::numeric_limits<char>::max()获得。因此,在常见平台上,i <= 255将始终为真,因为255大于CHAR_MAX。然而,一旦达到CHAR_MAX,就增加i是未定义的行为,永远不应该这样做。我建议将i至少声明为int(保证对于这个特定用例有足够的范围)。如果你想安全起见,可以使用类似std::ptrdiff_t的东西(在程序开始时添加#include <cstddef>),它保证足够大,可以容纳任何有效的数组大小
  • n已声明但从未使用。这本身是无害的,但可能表明存在设计问题。它也可能导致错误,例如尝试使用n而不是nr
  • 您可能希望在最后输出一个换行符('n'),因为程序的输出可能看起来很奇怪
  • 还要注意,重复调用可能代价高昂的函数(如strlen)(如循环条件)可能会对性能产生负面影响(不过,strlen通常是一个内部函数,编译器可能能够优化大多数调用)
  • 您不需要strlen,可以使用cin.gcount()
  • return 0;没有什么问题,只是它是多余的——这是一种特殊情况,仅适用于main函数

以下是您的程序的改进版本,不需要过多地更改代码样式:

#include <iostream>
#include <cstring>
#include <cstddef>
using namespace std;
int main()
{
char s[255];
int nr=0;
if ( cin.getline(s,255) )
{ // only if reading was successful
for(int i=0; i<cin.gcount(); i++)
{
if(s[i]=='e') nr++;
}
cout<<nr<<'n';
}
return 0;
}

为了便于说明,以下是使用std::string(用于任意长度的输入)和标准算法的更简洁、更具表现力的版本。(作为一名面试官,我会把这个模块化的微小风格差异设置为标准答案,即值得充分赞扬。)

#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
if ( getline(cin, s) )
{
cout << std::count(begin(s), end(s), 'e') << 'n';
}
}

关于C++中的字符,我有两件不清楚的事情:1)在上面的代码中,如果我用255替换"strlen(s)",我的代码就不起作用了,我只能键入一个单词,程序就会停止,我在学校认为"strlen(s)"是字符串s的长度,在这里正如我所说,这个案子是255。那么,为什么我不能直接输入255呢个strlen;

没错,但字符串只使用null终止符,即使分配了更多的空间。例如:

char buf[32];
strcpy(buf, "Hello World!");

有32个字符的空间,但我的字符串只有12个字符长。这就是strlen在本例中返回12的原因。这是因为它不知道缓冲区有多长,只知道字符串的地址并对其进行解析,直到找到null终止符。

因此,如果您输入255,您将通过cin设置的内容,然后读取缓冲区的其余部分。在这种情况下,它是未初始化的。这是未定义的行为——在这种情况下,它很可能会读取一些垃圾值,而这些值可能恰好具有'e'值,从而给您一个错误的结果。

2)如果你在正常情况下运行程序,它不会显示数字,就像它应该做的那样,它向我展示了一个角色(我相信它来自ASCII表,但我不确定),就像一颗心或一颗钻石,但它应该打印单词中e的数字。任何人都可以请给我解释一下?

您将nr声明为char。虽然它确实可以容纳一个整数值,但如果你这样打印它,它将被打印为一个字符。将其声明为int,或者在打印时强制转换。