strlen 默认为“40”?

strlen defaulting to '40'?

新程序员从基础开始。 我需要编写一个代码来检查字符串(行)的长度并对其进行处理。在开始下一部分任务之前,我正在努力使长度正确。

当我 运行 下面的代码是 strlen(string1) 时发生了什么,无论我输入什么,它似乎都默认为“40”?

我不确定出了什么问题! 任何帮助将不胜感激。

#include <iostream>
#include <string.h>
#include <string>
using namespace std;

char line, just, jline;
void prompt();

int main() {
  cout << "Enter a line of text: " << endl;
  char string1[line];
  cin >> line;

  char string2[] = "1234567890123456789012345678901234567890";

  line = strlen(string1);
  just = strlen(string2);

  cout << "Length of string is: " << strlen(string1) << endl;

  if ((strlen(string1)) > (strlen(string2))) {
    cout << "Error, your line must be less than 40 characters" << endl;
  }
}

您的代码存在 2 个问题,如下所述:

问题 1

在标准 C++ 中,数组的大小必须是编译时间常数。这意味着您的程序中的以下内容不正确:

char string1[line]; //not standard C++ because line is not a constant expression

问题 2

请注意,这还有另一个问题。由于 line 是一个全局变量,它将被静态初始化为 0。因此 char string1[line]; 实际上等同于 char string1[0];.

`但是来自 array declarators documentation:

If the expression is a constant expression, it shall have a value greater than zero.

因此,char string1[line];也因此无效。

解决方案

更好的做法是 std::string,如下所示:

#include <iostream>
#include <string>

int main() {
    std::cout << "Enter a line of text: " << std::endl;
    std::string inputLine;
    std::getline(std::cin, inputLine);//take input from user and put it into inputLine
    
    std::string var = "1234567890123456789012345678901234567890";
    
//----------------------------------------------------vvvvv----------->use size member function of std::string
    std::cout << "Length of string is: " << inputLine.size() << std::endl;
    
    if (inputLine.size() > var.size()) {
        std::cout << "Error, your line must be less than 40 characters" << std::endl;
    }
    else 
    {
        std::cout<<"valid input"<<std::endl;
    }
}

Demo.

在上面的代码片段中,我们使用 std::string::size 知道 std::string 的 size/length。


此外,应尽可能避免使用全局变量。参考Are global variables bad?.

截至目前,您的 line 变量是 char 类型。这意味着它包含一个字符。如果要存储字符串,可以使用固定大小的字符数组(c-style 字符串)或字符串对象。在 C++ 中,字符串对象应该是首选,因为它们提供了比 c-style 字符串更广泛的优势,包括更高的安全性和更好的易用性。

如果你想获取用户输入的字符串对象的长度,你可以这样写

#include <iostream>
#include <string>

// if you don’t want to use std:: put using namespace std; after the includes
int main(){
    std::string str;
    int strLength

    std::cout << “Enter a Single Word: “;
    std::cin >> str;

    strLength = str.lenght();

    std::cout << “The length of the word is “ << strLength << std::endl;

    return 0;
}

如果您想获得整行文本,您可以替换

std::cout << “Enter a Single Word: “;
std::cin >> str;

std::cout << “Enter a Line of text: “;
std::getline(cin, str);

您也可以使用 c-style 字符串和 strlen() 但是,安全地执行此操作要困难得多,并且通过编写比使用的固定大小数组的大小可能会导致问题,因为额外的数据可以写入不应该写入的区域,所以如果你刚开始,你应该使用字符串对象。

如果您想了解有关 std::string 的更多信息,请访问 https://en.cppreference.com/w/cpp/string/basic_string

关于 strlen 返回 40 的原因。strlen() 的工作方式是它采用一个称为指针的变量,该变量指向字符数组的开头,并遍历从指针开始的字符数组并查找一个称为空字符 '\0' 的特殊字符和 returns 数组中此空字符之前的字符数。如果 c-style 字符串不以空字符结尾,这可能会导致问题。

对于您提供的代码,string2 包含“”内的所有 40 个字符加上末尾的空字符,因此当使用 string2 调用 strlen() 时,它会计算空字符之前的 40 个字符字符.

在 string1 的情况下,当它被创建时,它的大小等于未初始化变量行中包含的值,在本例中显示为 0。这导致 string1 被创建为大小为 0(根据语言标准,这是未定义的行为,但在某些情况下它可能仍然“有效”)。因为 string2 后来在内存中直接在 string1 之后的位置创建,当 string1 被传递到 strlen 时创建的指向 string1 开头的指针指向 string2 的开头,导致 strlen 在调用 string1 时有效地测量 string2 的长度。

最后,作为一个提示。尽量避免将变量放在全局范围内(在函数或其他封装实体之外,如 类)。这些全局变量有被函数以可能导致代码问题的方式无意更改的风险。通常最好将这些变量放在 main 中并将它们传递给您要在其中使用它们的函数。如果您想让函数影响这些变量,您可以将它们作为引用传递给函数。为此,您可以在变量将作为传入函数的参数类型后面放置一个 &,如下所示。

void function(std::string &str);

//… some other code

//… somewhere in main or another function

function(alteredString);

// some other code …