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;
}