c++ 在使用 tolower 时使用 c 字符串格式化错误

Posted

技术标签:

【中文标题】c++ 在使用 tolower 时使用 c 字符串格式化错误【英文标题】:c++ formating error with cstrings when using tolower 【发布时间】: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 转换为小写。 【参考方案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);

【讨论】:

注意到键盘无法解决转换过载问题 - 没有时间弄清楚。恢复到以前版本的答案

以上是关于c++ 在使用 tolower 时使用 c 字符串格式化错误的主要内容,如果未能解决你的问题,请参考以下文章

C函数tolower,与toupper

tolower字符串转换函数应用实例

C++ 字符串到布尔值

为啥 putchar、toupper、tolow 等采用 int 而不是 char?

使用 tm_map(..., tolower) 将文本转换为小写时出错

ccf 201409-3 字符串匹配(toupper,tolower)