繁体   English   中英

将C样式字符串char *传递给函数参数

[英]Passing C-Style string char * to function argument

我想更改用户传递的字符串中的字符,将其转换为C样式的字符串,并作为参数传递给具有char *参数的函数:

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

void functoupper(char *myString)
{
    int i=0;
    char z;
    do {
        z= myString[i];
        myString[i]=toupper(z);
        ++i;
    } while(myString[i]!=0);
}

int main() {

    std::string name;

    std::cout << "Please, enter your full name in small caps: ";
    std::getline (std::cin,name);
    const char *myString = name.c_str();
    std::cout << "Hello, " << functoupper(myString) << "!\n";

    return 0;   
}

我收到错误错误消息:在main()中调用函数functoupper(myString)时,从'const char *'到'char *'的无效转换[-fpermissive]。

std::string::c_str()方法返回一个指向const char数据的指针,但是您的函数需要一个指向非const char数据的指针。 这就是为什么您会遇到错误。

您可以使用const_cast const (但这并不明智):

char *myString = const_cast<char*>(name.c_str());
functoupper(myString);
std::cout << "Hello, " << name << "!\n";

您可以使用非常量std::string::operator[]访问字符串的基础字符数据(请注意,因为在C ++ 11之前, 不需要将字符连续存储在内存中,但是大多数 std::string实现了):

functoupper(&name[0]);
std::cout << "Hello, " << name << "!\n";

在C ++ 17和更高版本中,可以改用非const std::string::data()方法:

functoupper(name.data());
std::cout << "Hello, " << name << "!\n";

话虽如此,使用toupper()时请注意以下警告:

<cctype>所有其他函数一样,如果参数的值既不能表示为unsigned char也不等于EOF ,则std::toupper的行为是不确定的。 为了安全地将这些函数与纯char s(或带signed char )一起使用,应首先将参数转换为unsigned char ...类似地,当迭代器的值类型为charsigned char时,不应将它们直接与标准算法一起使用。 而是先将值转换为unsigned char

话虽如此,请尝试类似以下的操作:

#include <string>
#include <iostream>
#include <cctype>

void functoupper(char *myString)
{
    for (int i = 0; myString[i] != '\0'; ++i) {
        unsigned char z = static_cast<unsigned char>(myString[i]);
        myString[i] = static_cast<char>(std::toupper(z));
    }
}

int main() {

    std::string name;

    std::cout << "Please, enter your full name in small caps: ";
    std::getline(std::cin, name);
    functoupper(&name[0]); // or name.data()
    std::cout << "Hello, " << name << "!\n";

    return 0;   
}

话虽如此,您应该只按原样将整个std::string传递给函数,然后可以根据需要进行操作,例如,使用std::transform()算法:

#include <string>
#include <iostream>
#include <algorithm>
#include <cctype>

void functoupper(std::string &myString)
{
    std::transform(myString.begin(), myString.end(), myString.begin(),
      [](unsigned char ch){ return std::toupper(ch); }
    );
}

int main() {

    std::string name;

    std::cout << "Please, enter your full name in small caps: ";
    std::getline(std::cin, name);
    functoupper(name);
    std::cout << "Hello, " << name << "!\n";

    return 0;   
}

或者:

#include <string>
#include <iostream>
#include <algorithm>
#include <cctype>

std::string functoupper(std::string myString)
{
    std::transform(myString.begin(), myString.end(), myString.begin(),
      [](unsigned char ch){ return std::toupper(ch); }
    );
    return myString;
}

int main() {

    std::string name;

    std::cout << "Please, enter your full name in small caps: ";
    std::getline(std::cin, name);
    std::cout << "Hello, " << functoupper(name) << "!\n";

    return 0;   
}

正如@Someprogrammerdude和@RemyLebeau所评论的,为什么不简单地

std::transform(std::begin(name), std::end(name), std::begin(name), 
    [](const unsigned char c)
    {
        return std::toupper(c);
    });

但是,如果必须通过char* ,则需要首先复制数据,例如:

char myString* = new char[name.size() + 1];
strcpy(myString, name.c_str());

编辑:感谢@RemyLebeau的有用评论

只需将std::string转换为std::vector更好地避免上述所有内存管理问题:

std::vector<char> myVec(std::begin(name), std::end(name));
myVec.push_back(`\0`);

然后使用以下命令调用char*函数:

functoupper(myVec.data());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM