[英]For loop crashes program while trying to read array c++
练习:给定向量 A[1 to N] 和一个值 s。 构建将每组 s 元素反向写入的程序。 如果 s 除以 N 有余数,则余数应保持不变。 如果 s 大于 N(向量的元素的 nr 个),则不会有任何修改。
假设 s = 4 和 A = (1, 2, 3, 4, 5, 6, 7, 8),那么执行后的值将是 A = (4, 3, 2, 1, 8, 7, 6, 5 )
我的老师需要这种向量: int n, A[n] 其中 n 是用户给定的值。 我认为这是导致我的程序在读取最终值时崩溃的原因。 如果不是,问题出在哪里?
#include <iomanip>
using namespace std;
int ordering(int s, int n, int A[]);
int main()
{
int n, A[n];
int s;
cout << "Vlera e s: ";
cin >> s;
if (s <= 0)
{
return 1;
}
cout << "\nN: ";
cin >> n;
if (n <= 0)
{
return 1;
}
cout << "\nVector:";
for (int i = 0; i < n; i++)
{
A[i] = i + 1;
cout << " " << A[i] << " ";
}
if (s > n)
{
cout << "\nNo change\n";
return 0;
}
else
{
ordering(s, n, A);
}
cout << "\nNew vector:";
for (int i = 0; i < n; i++)
{
cout << " " << A[i] << " ";
}
return 0;
}
int ordering(int s, int n, int A[])
{
int counter = 0;
for (int i = 0, divider = n / s; i < divider; i++)
{
int decrease = 0;
for (int j = counter, a = counter + s; j < a; j++)
{
A[j] = a - decrease;
decrease++;
}
counter += s;
}
return 0;
}
该程序使用编译器扩展来允许myArray[variableSize]
形式的可变大小 arrays 。 虽然不是标准的,但它确实适用于某些编译器。
您在此处使用此功能:
int n, A[n];
但是,此时n
未初始化。 即使在支持这种可变大小 arrays 的编译器上,这也是未定义的行为。 未定义行为的一种可能(但不是唯一)结果是您的程序崩溃。
未定义的行为在理论上可以做任何事情,但在现实中可以做的事情的现实集合更小。 此处未定义行为的一些可能含义:
n
中有一些巨大的数字,无论最后使用的是 memory 的那个位。 因此, A
很大。n
是 0。你不能有一个 0 大小的数组。 如果编译器没有注意到这一点,您最终可能会丢弃 memory。n
未初始化,因此编译器的优化器(它们通常会进行一些优化,即使在 -O0 上也是如此)假定不会发生未定义的行为,这在此处被违反,导致奇怪的行为。n
是一个合理的值,只是运气好,但是因为它后来被更新,它不再匹配数组的大小,你最终会从数组的末尾读取/写入 memory,从而破坏 memory。还有其他可能性,但这给出了由于这种未定义行为的特定实例而可能发生的事情的一种想法。 如果您有兴趣了解更多信息,使用调试器在汇编中逐步执行代码(您只需了解一点即可了解 output,它看起来比实际需要的更可怕)将向您展示实际发生的情况。
可变长度 arrays 不是标准 C++ 功能。
int n, A[n];
此外,在上述声明中,变量 n 未初始化。 所以在任何情况下,程序都有未定义的行为。
您可以使用标准 class 模板std::vector
代替数组。
该程序看起来更简单、更安全是使用标准算法,例如std::reverse
。
这是一个演示程序。
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <numeric>
void reorder( std::vector<int> &v, size_t s )
{
if ( not ( s < 2 ) )
{
for ( auto last = std::end( v );
not (std::distance( std::begin( v ), last ) < s ); )
{
auto first = std::prev( last, s );
std::reverse( first, last );
last = first;
}
}
}
int main()
{
std::cout << "Vlera e s: ";
size_t s = 0;
std::cin >> s;
std::cout << "N: ";
size_t n = 0;
std::cin >> n;
std::vector<int> v( n );
std::iota( std::begin( v ), std::end( v ), 1 );
putchar( '\n' );
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
reorder( v, s );
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
return 0;
}
程序 output 可能看起来像
Vlera e s: 4
N: 10
1 2 3 4 5 6 7 8 9 10
1 2 6 5 4 3 10 9 8 7
但似乎您需要使用循环自己编写相应的代码。 在这种情况下,程序可能看起来像
#include <iostream>
#include <vector>
void reorder( std::vector<int> &v, size_t s )
{
if ( not ( s < 2 ) )
{
for ( auto n = v.size(); !( n < s ); n -= s )
{
for ( size_t i = 0; i < s / 2; i++ )
{
int value = v[n - s + i];
v[n - s + i] = v[n - i - 1];
v[n - i - 1] = value;
}
}
}
}
int main()
{
std::cout << "Vlera e s: ";
size_t s = 0;
std::cin >> s;
std::cout << "N: ";
size_t n = 0;
std::cin >> n;
std::vector<int> v( n );
int value = 1;
for ( auto &item : v ) item = value++;
putchar( '\n' );
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
reorder( v, s );
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
return 0;
}
程序 output 可能看起来如上所示
Vlera e s: 4
N: 10
1 2 3 4 5 6 7 8 9 10
1 2 6 5 4 3 10 9 8 7
将变量作为数组大小传递是无效的,您需要使用常量const int n
或创建动态数组int* arr = new int[n];
,该数组将在运行时创建,您可以传递变量作为它的大小。 不要忘记删除该数组,因为它超出了 scope delete[] arr;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.