如何将 cstring 作为函数传递 parameter/argument
How to pass a cstring as a function parameter/argument
我有一个小程序可以打印出单词中每个字母的大写形式,但是当我编译它时出现错误 signed/unsigned mismatch 因为我将 cstring 作为正常传递 string
在这个程序中。如何正确传递它以便我仍然可以使用 text.length()
?这是我得到的错误“Tester.cpp(22,23):警告 C4018:'<':signed/unsigned 不匹配”。在 for (int i = 0; i < text.length(); i++)
#include <iostream>
using namespace std;
string capitalizeFirstLetter(string text);
int main() {
char sentence[100];
for ( ; ; )
{
cin.getline(sentence, 100);
if (sentence != "0")
capitalizeFirstLetter(sentence);
}
return 0;
}
string capitalizeFirstLetter(string text) {
for (int i = 0; i < text.length(); i++)
{
if (i == 0)
{
text[i] = toupper(text[i]);
}
if (text[i] == ' ')
{
++i;
text[i] = toupper(text[i]);
}
}
cout << text;
return text;
}
由于您将 cstring 作为正常 string
传递给函数,因此未生成错误,但这是因为您正在尝试使用 !=
运算符比较 c 样式字符串在声明中
if (sentence != "0")
capitalizeFirstLetter(sentence);
为此尝试使用 strcmp()
您的代码有问题:
if (sentence != "0")
:非法比较。如果您想中断获取 0
作为输入,请尝试使用 strcmp
(包括 <cstring>
)作为 if (strcmp(sentence, "0")
。 (请注意,当两个字符串 相等 时,strcmp
returns 0
。)或者简单地执行 if (!(sentence[0] == '0' and sentence[1] == 0))
。此外,此条件应伴随 else break;
以防止 for 循环永远 运行。
for (int i = 0; i < text.length(); i++)
:由于有符号和无符号类型之间的比较而生成警告。将 i
的 data-type 更改为 string::size_type
以防止警告。
<string>
(对于std::string
)和<cctype>
(对于std::toupper
)不包括在内。
感谢 @john 指出这一点。如果字符串的最后一个字符是 space,则您的代码具有未定义的行为。在使用 text[i]
.
之前添加检查 i
是否仍然小于 text.length()
另一种错误情况是 space 在 0
之后。将 getline
移动到 for 的条件来解决这个问题。现在不需要输入 0 来终止程序。此外,我建议为此使用 while
循环而不是 for
.
您可能还需要打印换行符来分隔句子。此外,我更喜欢使用 capitalizeFirstLetter
.
返回的字符串在 main()
函数中打印修改后的句子
代码短(beginner-level)没关系,但要避免养成每写代码都把using namespace std;
放在最前面的习惯。 Refer this.
固定码:
#include <cctype>
#include <cstring>
#include <iostream>
#include <string>
using namespace std;
string capitalizeFirstLetter(string text);
int main() {
char sentence[100];
while (cin.getline(sentence, 100))
cout << capitalizeFirstLetter(sentence) << '\n';
}
string capitalizeFirstLetter(string text) {
for (string::size_type i = 0; i < text.length(); i++) {
if (i == 0)
text[i] = toupper(text[i]);
if (text[i] == ' ')
if (++i < text.length())
text[i] = toupper(text[i]);
}
return text;
}
输入:
hello world
foo bar
输出:
Hello World
Foo Bar
我的版本(需要 C++20):
#include <cctype>
#include <iostream>
#include <string>
auto capitalizeFirstLetter(std::string text) {
for (bool newWord = true; auto &&i : text) {
i = newWord ? std::toupper(i) : i;
newWord = std::isspace(i);
}
return text;
}
int main() {
std::string sentence;
while (std::getline(std::cin, sentence))
std::cout << capitalizeFirstLetter(sentence) << std::endl;
}
这里有几件事困扰着我。
首先,不要使用using namespace std
,在这种情况下它是“好的”,但不要习惯它,它会引起相当大的麻烦。
参见 Why is “using namespace std;” considered bad practice?
下一步是,这里只使用 std::string
而不是 cstrings,它更容易编写和读取,并且不会产生任何可测量的性能损失或其他问题。而且这样更难产生错误。
所以只需使用
std::string sentence;
和
getline(std::cin, sentence);
为什么要在转换字符串的函数中处理输出?只需让 main 打印转换后的字符串即可。
所以您的主要内容可能如下所示:
int main() {
std::string sentence;
while(true)
{
getline(std::cin, sentence);
auto capitalized = capitalizeFirstLetter(sentence);
std::cout << capitalized;
}
return 0;
}
PS:您得到的 'error' 是一个警告,因为您将 int i
与 text.length()
进行比较,后者属于 size_t
类型 [=18] =] 或 unsigned long int
.
处理将 sentence
作为字符串传递的最简单方法是将其包含在花括号集中,以便为参数 std::string text
提供 直接初始化 例如..
for ( ; ; )
{
std::cin.getline(sentence, 100);
if (*sentence)
capitalizeFirstLetter({sentence});
}
这允许字符串 sentence
用作 Direct initialization 以在您的 capitalizeFirstLetter()
函数中初始化 std::string text
:
std::string capitalizeFirstLetter (std::string text) {
for (size_t i = 0; i < text.length(); i++)
{
if (i == 0)
{
text[i] = toupper(text[i]);
}
if (text[i] == ' ')
{
++i;
text[i] = toupper(text[i]);
}
}
std::cout << text;
return text;
}
阅读 Why is “using namespace std;” considered bad practice? 后,您的完整代码将是:
#include <iostream>
std::string capitalizeFirstLetter (std::string text) {
for (size_t i = 0; i < text.length(); i++)
{
if (i == 0)
{
text[i] = toupper(text[i]);
}
if (text[i] == ' ')
{
++i;
text[i] = toupper(text[i]);
}
}
std::cout << text;
return text;
}
int main (void) {
char sentence[100];
for ( ; ; )
{
std::cin.getline(sentence, 100);
if (*sentence)
capitalizeFirstLetter({sentence});
}
return 0;
}
(注意: 取消引用 sentence
提供第一个字符,然后确认为 nul-terminating[=46 以外的字符=] 字符 (ASCII 0))
更好的 CapitalizeFirstLetter()
一种更简单的大写方法是包含 <cctype>
和一个 int
来保存最后读取的字符。然后逻辑简单地遍历每个字符,如果第一个字符是 alpha-character,则将其大写,否则仅当当前字符是 alpha-character 且最后一个字符是空格时才将字母大写,例如
std::string capitalizeFirstLetter (std::string text)
{
int last = 0
for (auto& c : text)
{
if (isalpha(c))
{
if (!i || isspace (last))
c = toupper(c);
}
last = c;
}
std::cout << text;
return text;
}
(注:上面使用了一个range-basedfor
循环)
两种方法都行。
我有一个小程序可以打印出单词中每个字母的大写形式,但是当我编译它时出现错误 signed/unsigned mismatch 因为我将 cstring 作为正常传递 string
在这个程序中。如何正确传递它以便我仍然可以使用 text.length()
?这是我得到的错误“Tester.cpp(22,23):警告 C4018:'<':signed/unsigned 不匹配”。在 for (int i = 0; i < text.length(); i++)
#include <iostream>
using namespace std;
string capitalizeFirstLetter(string text);
int main() {
char sentence[100];
for ( ; ; )
{
cin.getline(sentence, 100);
if (sentence != "0")
capitalizeFirstLetter(sentence);
}
return 0;
}
string capitalizeFirstLetter(string text) {
for (int i = 0; i < text.length(); i++)
{
if (i == 0)
{
text[i] = toupper(text[i]);
}
if (text[i] == ' ')
{
++i;
text[i] = toupper(text[i]);
}
}
cout << text;
return text;
}
由于您将 cstring 作为正常 string
传递给函数,因此未生成错误,但这是因为您正在尝试使用 !=
运算符比较 c 样式字符串在声明中
if (sentence != "0")
capitalizeFirstLetter(sentence);
为此尝试使用 strcmp()
您的代码有问题:
if (sentence != "0")
:非法比较。如果您想中断获取0
作为输入,请尝试使用strcmp
(包括<cstring>
)作为if (strcmp(sentence, "0")
。 (请注意,当两个字符串 相等 时,strcmp
returns0
。)或者简单地执行if (!(sentence[0] == '0' and sentence[1] == 0))
。此外,此条件应伴随else break;
以防止 for 循环永远 运行。for (int i = 0; i < text.length(); i++)
:由于有符号和无符号类型之间的比较而生成警告。将i
的 data-type 更改为string::size_type
以防止警告。<string>
(对于std::string
)和<cctype>
(对于std::toupper
)不包括在内。感谢 @john 指出这一点。如果字符串的最后一个字符是 space,则您的代码具有未定义的行为。在使用
之前添加检查text[i]
.i
是否仍然小于text.length()
另一种错误情况是 space 在
0
之后。将getline
移动到 for 的条件来解决这个问题。现在不需要输入 0 来终止程序。此外,我建议为此使用while
循环而不是for
.您可能还需要打印换行符来分隔句子。此外,我更喜欢使用
返回的字符串在capitalizeFirstLetter
.main()
函数中打印修改后的句子代码短(beginner-level)没关系,但要避免养成每写代码都把
using namespace std;
放在最前面的习惯。 Refer this.
固定码:
#include <cctype>
#include <cstring>
#include <iostream>
#include <string>
using namespace std;
string capitalizeFirstLetter(string text);
int main() {
char sentence[100];
while (cin.getline(sentence, 100))
cout << capitalizeFirstLetter(sentence) << '\n';
}
string capitalizeFirstLetter(string text) {
for (string::size_type i = 0; i < text.length(); i++) {
if (i == 0)
text[i] = toupper(text[i]);
if (text[i] == ' ')
if (++i < text.length())
text[i] = toupper(text[i]);
}
return text;
}
输入:
hello world
foo bar
输出:
Hello World
Foo Bar
我的版本(需要 C++20):
#include <cctype>
#include <iostream>
#include <string>
auto capitalizeFirstLetter(std::string text) {
for (bool newWord = true; auto &&i : text) {
i = newWord ? std::toupper(i) : i;
newWord = std::isspace(i);
}
return text;
}
int main() {
std::string sentence;
while (std::getline(std::cin, sentence))
std::cout << capitalizeFirstLetter(sentence) << std::endl;
}
这里有几件事困扰着我。
首先,不要使用using namespace std
,在这种情况下它是“好的”,但不要习惯它,它会引起相当大的麻烦。
参见 Why is “using namespace std;” considered bad practice?
下一步是,这里只使用 std::string
而不是 cstrings,它更容易编写和读取,并且不会产生任何可测量的性能损失或其他问题。而且这样更难产生错误。
所以只需使用
std::string sentence;
和
getline(std::cin, sentence);
为什么要在转换字符串的函数中处理输出?只需让 main 打印转换后的字符串即可。 所以您的主要内容可能如下所示:
int main() {
std::string sentence;
while(true)
{
getline(std::cin, sentence);
auto capitalized = capitalizeFirstLetter(sentence);
std::cout << capitalized;
}
return 0;
}
PS:您得到的 'error' 是一个警告,因为您将 int i
与 text.length()
进行比较,后者属于 size_t
类型 [=18] =] 或 unsigned long int
.
处理将 sentence
作为字符串传递的最简单方法是将其包含在花括号集中,以便为参数 std::string text
提供 直接初始化 例如..
for ( ; ; )
{
std::cin.getline(sentence, 100);
if (*sentence)
capitalizeFirstLetter({sentence});
}
这允许字符串 sentence
用作 Direct initialization 以在您的 capitalizeFirstLetter()
函数中初始化 std::string text
:
std::string capitalizeFirstLetter (std::string text) {
for (size_t i = 0; i < text.length(); i++)
{
if (i == 0)
{
text[i] = toupper(text[i]);
}
if (text[i] == ' ')
{
++i;
text[i] = toupper(text[i]);
}
}
std::cout << text;
return text;
}
阅读 Why is “using namespace std;” considered bad practice? 后,您的完整代码将是:
#include <iostream>
std::string capitalizeFirstLetter (std::string text) {
for (size_t i = 0; i < text.length(); i++)
{
if (i == 0)
{
text[i] = toupper(text[i]);
}
if (text[i] == ' ')
{
++i;
text[i] = toupper(text[i]);
}
}
std::cout << text;
return text;
}
int main (void) {
char sentence[100];
for ( ; ; )
{
std::cin.getline(sentence, 100);
if (*sentence)
capitalizeFirstLetter({sentence});
}
return 0;
}
(注意: 取消引用 sentence
提供第一个字符,然后确认为 nul-terminating[=46 以外的字符=] 字符 (ASCII 0))
更好的 CapitalizeFirstLetter()
一种更简单的大写方法是包含 <cctype>
和一个 int
来保存最后读取的字符。然后逻辑简单地遍历每个字符,如果第一个字符是 alpha-character,则将其大写,否则仅当当前字符是 alpha-character 且最后一个字符是空格时才将字母大写,例如
std::string capitalizeFirstLetter (std::string text)
{
int last = 0
for (auto& c : text)
{
if (isalpha(c))
{
if (!i || isspace (last))
c = toupper(c);
}
last = c;
}
std::cout << text;
return text;
}
(注:上面使用了一个range-basedfor
循环)
两种方法都行。