C++ 在argv主参数中传递常量字符

C++ 在argv主参数中传递常量字符,c++,string,char,C++,String,Char,我有以下资料: int main(int argc, char *argv[]) { char *INPUTFILE_DATABASE = ""; strcpy(INPUTFILE_DATABASE, argv[1]); if(INPUTFILE_DATABASE[0]=='\0') { cout << "No input file given" << endl; INPUTFILE_DATA

我有以下资料:

int main(int argc, char *argv[])
{    
    char *INPUTFILE_DATABASE = "";
    strcpy(INPUTFILE_DATABASE, argv[1]);    
    if(INPUTFILE_DATABASE[0]=='\0')
    {
        cout << "No input file given" << endl;
        INPUTFILE_DATABASE="File_name.csv";
    }
    cout << "Input file: " << INPUTFILE_DATABASE << endl;

    return 0;
当我将
char*INPUTFILE\u数据库
设置为
const char*INPUTFILE\u数据库
时,我不能再更改它了,当然不能。 我做错了什么?或者我的动机一般来说是不可行的


最后,我只想允许更改输入文件名,但如果没有提供文件名,则应使用标准文件名。

是的,您不应该这样做。与此相反:

char *INPUTFILE_DATABASE = "";
你应该做一些事情,比如

char INPUTFILE_DATABASE[32]; // or another size that is sufficent
如果执行
char*INPUTFILE_DATABASE=“”是指您的
char*
将指向一个位置,该位置被设置为仅容纳
(因此可能只是程序二进制文件中某个位置的一个值为
0
的字节)。你不能给那里写信

也,因为这是C++,我建议:

std::string INPUTFILE_DATABASE = argv[1];

您可以使用
if(!INPUTFILE\u DATABASE.size())代替
if(INPUTFILE\u DATABASE[0]='\0')
来管理内部
char
缓冲区。例如,

#include <string>

std::string INPUTFILE_DATABASE;

if (argc == 1)
   INPUTFILE_DATABASE = "File_name.csv";
else
   INPUTFILE_DATABASE = argv[1];
#包括
std::字符串输入文件\u数据库;
如果(argc==1)
INPUTFILE\u DATABASE=“File\u name.csv”;
其他的
INPUTFILE_DATABASE=argv[1];

你永远无法改变它。只是,由于旧的C规则,看起来你可以。规则中的更改(C++98中的弃用;实际上这是非法的,因为C++11不会编译)是为了更好地提醒您这一点

要更改字符串,最好使用
std::string
,将其复制到您自己的东西上,尤其是因为您对C字符串的掌握似乎不是很强(您有一个零长度的字符串,您正试图在其上复制一个潜在的非零长度字符串!)

事实上,我不会复制任何内容,而是重新安排您的逻辑,使用仍然是原始常量字符串的内容有条件地初始化
INPUTFILE\u数据库
,如下所示:

// Use argv[1] if given and non-empty, otherwise a default path
const char* INPUTFILE_DATABASE = (
   argc > 1 && argv[1][0] != '\0'
   ? argv[1]
   : "File_name.csv"
);

那就不会再复杂了:

char const* INPUTFILE_DATABASE = argc > 1 ? argv[1] : "File_name.csv";

您不应该以任何方式修改此字符串,使其成为
char const*
可以防止您产生错误

首先:不要这样做,只需使用
std::string
。If在减少C风格字符串中出现的愚蠢错误方面帮助很大

回到您的问题:

auto i = std::make_unique<char[]>(512); // or more? (Could be calculated at runtime)
std::strcpy(i.get(), argv[1]);
if (i[0]=='\0')
    {
        cout << "No input file given" << endl;
        std::strcpy(i.get(), "filename.csv");
    }
cout << "Input file: " << i.get() << std::endl;
对于这种特殊情况,
std::string_view
也应该起作用


请注意,
Lightness Races in Orbit
发布了另一个变体,它不要求您仅使用
char const*

为这种特定情况分配内存,使用std:string代替char*字符串常量,无论您是否将其标记为常量,正如您所看到的,您应该始终使用
const
。除此之外,您还试图
strcpy
到一个只分配了一个空字节的位置,因此您不仅试图写入只读内存,而且还出现了溢出。为什么所有的否决票都被否决?这个问题问得很好。如果您搜索,可能是重复的,尽管我没有看到任何人链接到原始文件。但当我这样做时,我得到:错误:将“const char[27]”分配给“char[200]”INPUTFILE\u DATABASE=“file\u name.csv”时,类型不兼容;如果要使用c风格的字符串,仍然必须使用strcpy。所有其他答案都没有帮助,也不完整(const char*不是char*)。@MatthieuBrucher除非在这里使用
string
,否则会有过多的杀伤力,根本没有必要。”“不是0字节,它仍然包含'\0'指针,在这里就足够了,不需要分配内存和复制字符串。没错,虽然我不认为这会成为性能瓶颈。
argc>1&&argv[1][0]!='\0'
(或使用
strlen
以清晰显示),但可以
auto i = std::make_unique<char[]>(512); // or more? (Could be calculated at runtime)
std::strcpy(i.get(), argv[1]);
if (i[0]=='\0')
    {
        cout << "No input file given" << endl;
        std::strcpy(i.get(), "filename.csv");
    }
cout << "Input file: " << i.get() << std::endl;
auto i = std::string(argc[1]);
if (i.empty())
    {
        cout << "No input file given" << endl;
        i = "filename.csv";
    }
cout << "Input file: " << i << std::endl;