【问题标题】:c++ formating error with cstrings when using tolowerc++ 在使用 tolower 时使用 c 字符串格式化错误
【发布时间】:2011-04-22 21:16:40
【问题描述】:

嗨,所以我尝试将 cstring 设为小写,但是当我在最后打印 cstring 时,我得到了一个奇怪的格式框,其中一些字母应该是。有人有什么想法吗?

#include <string>
#include <iostream>
#include <string.h>

using namespace std;

int main () 
{ 
    int i=0; 
    char* str="TEST"; 
    char c; 
    char* cstr = new char[strlen(str) + 1];
    while (str[i]) 
    { 
        c = str[i]; 
        c = tolower(c);
        strcat(cstr, &c); 
        i++; 
    } 

    cout << cstr << endl; 
    return 0; 
}

【问题讨论】:

  • 使用char *new 而不使用std::string 类具有讽刺意味。请参阅std::transformstd::string 转换为小写。

标签: c++ cstring


【解决方案1】:

问题是您错误地调用了strcat。第二个参数不是以 null 结尾的字符串。

您根本不需要致电strcat。直接写入输出字符串即可:

试试:

  while (str[i])
  {
    c = str[i];
    c = tolower(c);
    cstr[i] = c;
        i++;
  }
  cstr[i] = 0;

或者,等效地:

while(str[i])
{
  cstr[i] = tolower(str[i]);
  i++;
}
cstr[i] = 0;

【讨论】:

  • 我认为 strcat 似乎不合适。很好地把它放在简单易读的代码中。
  • 段错误-在 str[i] = tolower(str[i]
  • @trev9065 - 是的,这是一个不同的错误。我会把它添加到描述中。
  • -1 出现段错误,因为此代码试图修改字符串常量。修复/解决此问题后,我将撤消我的 -1。 :-)
  • @trev9065:你现在明白为什么std::string 比老式的c-strings 更可取吗?即使是有经验的人也很难在第一次就正确掌握 c 弦。 :-)
【解决方案2】:

strcat 需要一个 null-terminated char*,因此通过提供本地 char 的地址,您正在调用 undefined behavior

另外,new char[std::strlen(str) + 1] 不会将数组初始化为0s,这意味着cstr 也不会被正确地以空值终止;将() 添加到new[] 会导致数组被初始化。

试试这个:

#include <cstddef>
#include <cctype>
#include <cstring>
#include <ostream>
#include <iostream>

int main()
{
    char const* str = "TEST";
    char c[2] = { };
    char* cstr = new char[std::strlen(str) + 1]();
    std::size_t i = 0;
    while (str[i])
    {
        c[0] = static_cast<char>(std::tolower(str[i++]));
        std::strcat(cstr, c);
    }
    std::cout << cstr << std::endl;
    delete [] cstr;
}

【讨论】:

  • 这对于一个简单的解决方案来说似乎过于复杂。
  • @Tyler Ferraro :OP 的代码过于复杂,我只是修复了他们的错误。 OP 没有问有什么更好的方法,他们问为什么他们的代码不起作用。出于启蒙的目的,至少解释他们如何/为什么错误地使用strcat 与采取不同的(阅读:“更好”)方法一样有帮助,但不会告诉他们原因他们的代码被破坏了。否决 保证 imo。
【解决方案3】:

strcat 的第二个参数应该是一个以空字符结尾的字符串,而不是单个字符的地址。 strcat 不适合这种用途。

int main ()
{
    const char* str="TEST";
    char* cstr = new char[strlen(str) + 1];
    cstr[strlen(str)] = 0;
    for (int i = 0; str[i]; ++i) {
        cstr[i] = tolower(str[i]);
    }
    cout << cstr << endl;
}

【讨论】:

    【解决方案4】:
    #include <cstddef>
    #include <cctype>
    #include <cstring>
    #include <ostream>
    #include <iostream>
    
    #include <string>
    
    int main()
    {
        std::string str = "TEST";
        std::string cstr;
    
        for (std::string::const_iterator it = str.begin(); it!= str.end(); ++it)
            cstr.push_back(tolower(*it));
    
        std::cout << cstr << std::endl;
    }
    

    甚至更短:

    #include <algorithm>
    #include <iterator>
    

    ...

        std::transform(str.begin(), str.end(), std::back_inserter(cstr), tolower);
    

    【讨论】:

    • 注意到键盘无法解决转换过载问题 - 没有时间弄清楚。恢复到以前版本的答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-09
    • 2021-05-09
    • 2016-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多