C++ 将char*[]传递给接受char**作为参数的函数

C++ 将char*[]传递给接受char**作为参数的函数,c++,command-line-arguments,C++,Command Line Arguments,我已经编写了一个程序,对命令行参数进行排序。但是,当我尝试打印输出(使用函数)时,我无法执行此操作。因为我尝试在接受char**作为参数的函数中传递char*[]。经过大量的搜索,没有什么结果,因此我在这里提出我的第一个问题 #include "iostream" #include "cstdlib" #include "cstring" using namespace std; void sortArgs(); int stringcomp (const void * x, const v

我已经编写了一个程序,对命令行参数进行排序。但是,当我尝试打印输出(使用函数)时,我无法执行此操作。因为我尝试在接受char**作为参数的函数中传递char*[]。经过大量的搜索,没有什么结果,因此我在这里提出我的第一个问题

#include "iostream"
#include "cstdlib"
#include "cstring"
using namespace std;


void sortArgs();
int stringcomp (const void * x, const void * y);
void parse(char **argv, int argc);
void printArgs();
void setArgs(char **argv, int argc);

int size;
char** argNew;

int main (int argc, char** argv) 
{

parse(argv, argc);
printArgs();

return 0;

}

int stringcomp (const void *x, const void *y) 
{
    return strcmp (*(char * const *)x, *(char * const *)y);
}

void parse(char **argv, int argc)
{
   setArgs(argv, argc);
   sortArgs();
}


void setArgs(char **argv, int argc)
{
   argNew=argv;
   size=argc;
}

void  printArgs()
{

  char *s[size-1];
  cout<<size<<endl;

  for (int i = 1; i < size; i++)
  {
      s[i-1] = argNew[i];

  }

   for (int i = 0; i < size-1; i++)
        cout<<" "<< s[i];
   cout <<endl;
}

void sortArgs()
{


    int i;
    char *strings[size-1];

    /* assign each argument to a pointer */
    for (i = 1; i < size; i++)
    {
        strings[i-1] = argNew[i];
    }

    /* sort the array of pointers alphabetically with qsort */
    qsort (strings, size - 1, sizeof *strings, stringcomp);

    for (int i = 0; i < size-1; i++)
    cout<<" "<< strings[i];  //this prints the output just fine  


    setArgs(strings, size);    // pass the *strings[] here


 }
#包括“iostream”
#包括“cstdlib”
#包括“cstring”
使用名称空间std;
void sortArgs();
int stringcomp(常数无效*x,常数无效*y);
无效解析(字符**argv,int argc);
void printArgs();
void setArgs(字符**argv,整数argc);
整数大小;
新字符;
int main(int argc,字符**argv)
{
解析(argv,argc);
printArgs();
返回0;
}
int stringcomp(常数无效*x,常数无效*y)
{
返回strcmp(*(字符*常量*)x,*(字符*常量*)y);
}
无效解析(字符**argv,int argc)
{
设置args(argv,argc);
sortArgs();
}
void setArgs(字符**argv,整数argc)
{
argNew=argv;
尺寸=argc;
}
void printArgs()
{
字符*s[size-1];
库特
这是个错误

strings
是一个本地数组。当函数返回时,它会被删除。因此,
argNew
在函数返回时将是一个悬空指针。尝试打印
argNew
的内容是未定义的行为

通过将
字符串的元素复制到
argNew
来替换该行

for (i = 1; i < size; i++)
{
   argNew[i] = strings[i-1];
}
for(i=1;i
您通过
sortArgs
中的
setArgs
赋值将自动变量
字符串的基址存储到全局中。一旦
sortArgs
退出并将控制权返回到
parse
,该数组就不再存在。其中的任何计算或取消引用都会调用未定义的行为

您可以解决这个问题(松散使用的术语,请参阅下一节了解原因)只需将
argv
argc
设置到全局变量中,并对它们进行排序,而不是将一些参数传递给某些函数。或者,您可以像现在这样将指针复制到指针床上,然后对它们进行排序,然后将它们复制回
argvNew

for (i = 1; i < size; i++)
{
   argNew[i] = strings[i-1];
}
或者,您可以完全消除全局变量,并在这个过程中抛弃
set
思想,只需在
parse
中直接对
argv
中的指针进行排序,您可以对其进行重新排序,但仍然可以在已定义的行为领域中发言

但<强>为什么?这是后面的,C++ + < /P>

<强>跳入C++池>/P> <>我不打算把这个糖涂写。代码很可怕。它是拼命地在C++的C++中使用C++的标准库提供的,除了基本的IO。C是一种很好的语言,并且有一个很好的标准库,但是如果你想潜入C++,那就不要害怕它;拥抱它。< /P> <>在C++中,使用一些基本的C++标准库提供。一个可以做得相当不同的事情。例如:

  • argv
    argc
  • 做任何你想做的事情,包括分类
  • 该代码比您想象的要简单得多:

    #include <iostream>
    #include <vector>
    #include <string>
    
    std::vector<std::string> parseArgs(char **argv, int argc)
    {
        std::vector<std::string> args(argv+1, argv+argc);
        std::sort(args.begin(), args.end());
        return args;
    }
    
    int main (int argc, char** argv)
    {
        auto args = parseArgs(argv, argc);
    
        // move to your own function.
        for (auto const& s : args)
            std::cout << s << '\n';
    
        return 0;
    }
    
    #包括
    #包括
    #包括
    std::vector parseArgs(字符**argv,int argc)
    {
    标准::向量args(argv+1,argv+argc);
    排序(args.begin(),args.end());
    返回args;
    }
    int main(int argc,字符**argv)
    {
    自动args=parseArgs(argv,argc);
    //转到您自己的功能。
    用于(自动常量和参数:args)
    
    std::cout有很多很好的搜索,比如StackOverflow或Google上的“双指针c”。例如和

    也就是说,我建议的第一件事是,您可以像打印数字一样打印指针的值。要执行此操作,请编写:

    printf("Pointer is %p.\n", ptr);
    
    或:

    请注意,
    字符串
    数组的位置对于
    f1
    f2
    是相同的(这不是保证的,这里正好是这种情况。但是这通常是正确的,并且有助于理解您看到的SEGV错误)。请注意字符串文字“foo”、“bar”和“baz”get pooled——也就是说,即使它们被多次使用,也只有一个副本。字符串指针值的顺序与链接器在内存中的排列顺序一致


    请注意,
    &global\u array
    的值与
    global\u array
    的值相同,但
    global\u ptr
    的情况并非如此。char*strings[]类型的参数被调整为char**.:
    char*s[size-1];
    char*strings[size-1]“/CODE”是可变长度数组,它们在C++中是不标准的。FYI,您将自动对象的基地址保存在代码> > AgNeX< /COD>中。一旦代码< > Soaltgs<代码>结束,char指针的序列就消失了,因此,定义的行为。@ VladfromMoscow,如果您在我的SoTalgS.()中看到的话函数,我尝试将其传递给setArgs()函数。但是,当我尝试在打印函数中迭代它时,我无法,相反,它给了我seg fault。@WhozCraig的注释可能正确地解释了SEGV。这个问题是非常有问题的,因为代码太糟糕了。如果你问的是C/C++中的参数传递,为什么你要将值存储在全局值而不是全局值中传递它们?如果你想探索参数传递,你可以从最简单的程序开始,该程序在main中对argv进行排序和打印,然后递增地将排序和打印分为单独的函数。向前的decls是不必要的,等等。谢谢。你能给我引用一个ref来了解**指针的更多信息吗?我正在尝试ng想了解一下。@sidchawla,我没有任何关于理解指针的具体建议。你可能想看看。我理解你的观点,非常感谢你在这方面的见解。
    
    std::cout << "Pointer is " << (void *)ptr << ".\n";
    
    #include <iostream>
    
    // Sometimes it's char *, sometimes const char *
    template <typename T>
    void print_argv_style_array(const char *label, int argc, T **argv) {
        int i = 0;
        std::cout << label << ": Printing argv array of size " << argc << " at " << (void *)argv << ":\n";
        for (int i = 0; i < argc; i++) {
        std::cout << "    " << i << ": " << (void *)argv[i] << " -- " << argv[i] << "\n";
        }
    }
    
    void f1() {
        const char *strings[] = { "foo", "bar" , "baz" };
        print_argv_style_array("f1", sizeof(strings) / sizeof(strings[0]), strings);
    }
    
    void f2() {
        const char *strings[] = { "foo", "bar" , "quux" };
        print_argv_style_array("f2", sizeof(strings) / sizeof(strings[0]), strings);
    }
    
    const char *global_array[] = { "foo", "bar", "baz" };
    const char **global_ptr = global_array;
    
    int main(int argc, char **argv) {
        std::cout << "main: argv is at " << &argv << "\n";
        print_argv_style_array("main", argc, argv);
        f1();
        f2();
        std::cout << "global_array is at: " << (void *)global_array << "\n";
        print_argv_style_array("global_array", sizeof(global_array)/sizeof(global_array[0]), global_array);
        std::cout << "global_ptr is at: " << (void *)&global_ptr << "\n";
        print_argv_style_array("global_ptr", sizeof(global_array)/sizeof(global_array[0]), global_ptr);
    }
    
    main: argv is at 0x7fff5a8c38f0
    main: Printing argv array of size 1 at 0x7fff5a8c3928:
        0: 0x7fff5a8c3ab8 -- ./pointer_help
    f1: Printing argv array of size 3 at 0x7fff5a8c38a0:
        0: 0x10533dedc -- foo
        1: 0x10533dee0 -- bar
        2: 0x10533dee4 -- baz
    f2: Printing argv array of size 3 at 0x7fff5a8c38a0:
        0: 0x10533dedc -- foo
        1: 0x10533dee0 -- bar
        2: 0x10533deeb -- quux
    global_array is at: 0x10533e140
    global_array: Printing argv array of size 3 at 0x10533e140:
        0: 0x10533dedc -- foo
        1: 0x10533dee0 -- bar
        2: 0x10533dee4 -- baz
    global_ptr is at: 0x10533e158
    global_ptr: Printing argv array of size 3 at 0x10533e140:
        0: 0x10533dedc -- foo
        1: 0x10533dee0 -- bar
        2: 0x10533dee4 -- baz