Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用forrange循环打印argv_C++_Argv - Fatal编程技术网

C++ 使用forrange循环打印argv

C++ 使用forrange循环打印argv,c++,argv,C++,Argv,正如所料 但是如果我试试这个, muyustan@mint:~/Desktop/C_Files/oop$ g++ main.cpp -o main && ./main Hello ABC DEF int main(int argc,const char**argv){ std::cout如果要将基于范围的for应用于argv,最好先创建一个包含以下参数的向量: muyustan@mint:~/Desktop/C_Files/oop$ g++ main.cpp -o main &

正如所料

但是如果我试试这个,

muyustan@mint:~/Desktop/C_Files/oop$ g++ main.cpp -o main && ./main
Hello
ABC
DEF
int main(int argc,const char**argv){

std::cout如果要将基于范围的
for
应用于
argv
,最好先创建一个包含以下参数的向量:

muyustan@mint:~/Desktop/C_Files/oop$ g++ main.cpp -o main && ./main
main.cpp: In function ‘int main(int, const char**)’:
main.cpp:30:26: error: ‘begin’ was not declared in this scope
     for (const char *i : argv)
                          ^~~~
main.cpp:30:26: note: suggested alternative:
In file included from /usr/include/c++/7/string:51:0,
                 from /usr/include/c++/7/bits/locale_classes.h:40,
                 from /usr/include/c++/7/bits/ios_base.h:41,
                 from /usr/include/c++/7/ios:42,
                 from /usr/include/c++/7/ostream:38,
                 from /usr/include/c++/7/iostream:39,
                 from main.cpp:1:
/usr/include/c++/7/bits/range_access.h:105:37: note:   ‘std::begin’
   template<typename _Tp> const _Tp* begin(const valarray<_Tp>&);
                                     ^~~~~
main.cpp:30:26: error: ‘end’ was not declared in this scope
     for (const char *i : argv)
                          ^~~~
main.cpp:30:26: note: suggested alternative:
In file included from /usr/include/c++/7/string:51:0,
                 from /usr/include/c++/7/bits/locale_classes.h:40,
                 from /usr/include/c++/7/bits/ios_base.h:41,
                 from /usr/include/c++/7/ios:42,
                 from /usr/include/c++/7/ostream:38,
                 from /usr/include/c++/7/iostream:39,
                 from main.cpp:1:
/usr/include/c++/7/bits/range_access.h:107:37: note:   ‘std::end’
   template<typename _Tp> const _Tp* end(const valarray<_Tp>&);

…但是,
argv
没有这样一个静态可见的定义,编译器可以从中推断其大小。在典型情况下,有一些代码在
main
之外运行,它检查命令行,并动态分配它。

表达式的范围与迭代器一起工作(指针是迭代器的一种类型),它需要一个范围开始和结束的迭代器。它通过将范围传递到
std::begin
std::end
来获得这些值

arr2d
的类型是
char[2][4]
。作为一个数组,它携带有关其大小的信息作为其类型的一部分。对于
std::begin
std::end
有模板重载,它们接受对数组的引用,并分别返回指向其第一个和最后一个元素的指针

argv
的类型是
char**
。它只是指向
char
的指针。编译器不知道这些指针中有哪一个指向数组的第一个元素,并且这些指针不携带关于它们指向的数组长度的信息。因此,
std::begin>没有重载
std::end
接受指针,因为
std::end
无法单独计算数组的结尾相对于指针开头的位置

若要使用范围为的指针,必须提供有关数组长度的信息。在这种情况下,您可以在数组上构造一个简单视图,因为您可以从
argc
了解其长度:

template <class T, size_t N>
size_t array_size(T (&array)[N]) {
    return N;
}

int foo[2][3];
std::cout << array_size(foo) << "\n";

char bar[12][13][14];
std::cout << array_size(bar) << "\n";

它们的行为不同,因为它们有不同的类型。这对于初学者来说是令人困惑的,但是:

int main(int argc, char** argv)
{
    for (std::string_view arg : std::span{argv, argc}) {
        std::cout << arg << "\n";
    }
}
是指向
char
的指针。事实上,在
argv
的情况下,它指向一个指针序列,每个指针指向一个以nul结尾的字符串(即字符序列)

迭代这些序列的问题是这些序列的大小未知。编译器无法知道
argc
与上述第一个序列相关

然而:

char **
解析为以下类型:

char arr2d[][4] = {"ABC", "DEF"};
这是一个字符数组(
char
)的数组。在本例中,大小是已知的(
2
),因此可以对其进行迭代

最后,编译器抱怨
std::begin
,因为基于范围的for循环被转换成不同的等效代码,使用
std::begin
等进行迭代

这是我被告知错误的事情,当时我在处理C时,在某个地方我读到“数组也是指针!”

关于这句话,有两个更好的观点我们必须理解

  • 在大多数上下文中,数组会衰减为指针,但数组仍然不同于指针

    char const* ptr1 = "Some text.";
    char array[] = "some text.";
    
    char const** ptr2 = &ptr1;      // OK.
    char** ptr3 = &array;           // Error. Type mismatch.
    char (*ptr4}[11] = &array;      // OK.
    
    • 当用作
      sizeof
      的参数时,以下两个选项将产生不同的答案

      char [2][4]
      
  • 二维数组可以衰减为指向一维数组的指针,但不会衰减为指向指针的指针

    char const* ptr1 = "Some text.";
    char array[] = "some text.";
    
    char const** ptr2 = &ptr1;      // OK.
    char** ptr3 = &array;           // Error. Type mismatch.
    char (*ptr4}[11] = &array;      // OK.
    

  • 如果您的编译器有span头(现在没有很多这样做),我想这是可行的

     int array1[10];
     int* ptr1 = array1;          // OK. Array decays to a pointer
    
    
     int array2[10][20];
     int (*ptr2)[20] = array2;    // OK. 2D array decays to a pointer to 1D array.
     int**  ptr3 = array2;        // Error. 2D array does not decay to a pointer to a pointer.
    
    //示例程序
    #包括
    #包括
    #包括
    int main(int argc,字符**argv)
    {
    for(std::string_视图s:std::span{argv,argc})
    {
    
    std::cout No,
    argv
    是指向
    char
    arr2d
    的指针,是
    char
    s数组的数组。数组不是指针。@MilesBudnek当时我在处理C时,在某个地方我读到“数组也是指针!”.您听说这很可能与数组在某些情况下衰减为指针有关(参见示例)那么,把它们等同起来是错误的,而代码中的许多误解和错误的来源,你会定义一系列指针吗?那么,为了使用一个循环循环来检查ARGV的内容,请检查C还不是C++。我将要问一个更解释性的答案,我现在将检查你的编辑版本。似乎你忘了添加
    #include
    @usr:这要看情况了。如果这就是你用它所做的一切,那么可能是的。但是如果你用它做的很多,把它放到向量中是完全值得的。当然,你也可以选择
    std::vector args(argv,argv+argc)的中间地带或者介于两者之间的东西,比如C++20中的(std::string\u视图s:std::span{argv,argc})
    std::vector
    ,甚至是(std::string\u视图s:std::span{argv,argc})的
    在C++20中。@Jarod42是的,刚刚更改了它。我永远无法保持范围的正确性。好吧,这个答案远远高于我现在的水平,但我大致理解如下:对于forrange循环,iterable的长度(或开始和结束)(我不知道这个词的正确名称)必须定义。因此,对于2D数组,它是已知的,但是对于
    char**
    它是未知的。这是问题的基础。我至少捕捉到了正确的轨迹吗?@muyustan是的,这是正确的轨迹。我编辑以添加更多的信息。基本上,数组的大小已知,但指针可以指向任何东西。你必须告诉数组指向的范围是指它能够使用指针的时间,你可以通过将指针封装在某种范围类中来实现。让我来解释一下我的理解。因此,你无法知道
    char**
    ,这就是问题产生的原因吗?但是对于
    char*
    的情况,它的终点是kno默认情况下为wn,因为它以null结尾(
    \0<
    
    char [2][4]
    
    char const* ptr = "Some text.";
    char array[] = "some text.";
    
    std::cout << sizeof(ptr) << std::endl;    // prints sizeof the pointer.
    std::cout << sizeof(array) << std::endl;  // prints sizeof the array.
    
    char const* ptr1 = "Some text.";
    char array[] = "some text.";
    
    char const** ptr2 = &ptr1;      // OK.
    char** ptr3 = &array;           // Error. Type mismatch.
    char (*ptr4}[11] = &array;      // OK.
    
     int array1[10];
     int* ptr1 = array1;          // OK. Array decays to a pointer
    
    
     int array2[10][20];
     int (*ptr2)[20] = array2;    // OK. 2D array decays to a pointer to 1D array.
     int**  ptr3 = array2;        // Error. 2D array does not decay to a pointer to a pointer.
    
    // Example program
    #include <iostream>
    #include <string_view>
    #include <span>
    
    int main(int argc, char **argv)
    {
      for (std::string_view s : std::span{argv, argc})
      {
          std::cout << s << std::endl;
      }
      return 0;
    }