C++代码num_voltages下标越界仍正常运行的原因及优化建议问询
问题描述
我正在计算所有文件第二列的最大值,并求解其比例效应。当前代码能输出正确结果,但num_voltages作为数组下标已经超出合法范围(数组大小为num_voltages=16,合法下标应为0至15),我对此感到困惑。我是C++新手,代码是试错写出来的,把num_voltages替换为i会得到错误结果,修改现有代码也会出错。现有6个包含2列数据的文件,恳请提供代码改进方案及越界问题的解答。
原代码
#include <fstream> #include <sstream> #include <iostream> #include <cstring> using namespace std; int main () { ifstream infile; ofstream outfile; int num_voltages; int num_concs; float peak_current; string filename; int conc; string conc_string; int i; i = 0; num_concs = 6; num_voltages = 16; peak_current = -10; float current[num_voltages]; float voltage[num_voltages]; outfile.open ("Conc_vs_peak_current.txt"); for (conc = 0; conc <= 10; conc += 2) { filename = "IK_IV_" + to_string (conc) + ".txt"; infile.open (filename.c_str ()); cout << "The System is Reading " << filename << endl; if (!infile) { cout << "File Not Found. Exiting" << endl; exit (1); } for (i = 0; i < 16; i++) { infile >> voltage[num_voltages] >> current[num_voltages]; } infile.close (); cout << "File Read" << endl; for (i = 0; i < 16; i++) { if (current[i] > peak_current) peak_current = current[num_voltages]; } cout << "Peak Value = " << peak_current << ", " << "Voltage = " << voltage[num_voltages] << endl; outfile << conc << " " << peak_current << " " << voltage[i] << endl; cout << endl << endl; } outfile.close (); /////////////////////////////// float current0[15]; float voltage0[15]; float current10[15]; float voltage10[15]; infile.open ("IK_IV_0.txt"); for (i = 0; i < 16; i++) { infile >> voltage[num_voltages] >> current[num_voltages]; } infile.close (); for (i = 0; i < 16; i++) { if (current[i] > peak_current) peak_current = current[num_voltages]; current0[15] = peak_current; } infile.open ("IK_IV_10.txt"); for (i = 0; i < 16; i++) { infile >> voltage[num_voltages] >> current[num_voltages]; } infile.close (); for (i = 0; i < 16; i++) { if (current[i] > peak_current) peak_current = current[num_voltages]; current10[15] = peak_current; } cout << endl << endl; ///////////////////////////// outfile.open ("Proportional_effect.txt"); for (conc = 0; conc <= 10; conc += 2) { filename = "IK_IV_" + to_string (conc) + ".txt"; infile.open (filename.c_str ()); cout << "The System is Reading " << filename << endl; if (!infile) { cout << "File Not Found. Exiting" << endl; exit (1); } for (i = 0; i < 16; i++) { infile >> voltage[num_voltages] >> current[num_voltages]; } infile.close (); cout << "File Read" << endl; for (i = 0; i < 16; i++) { if (current[i] > peak_current) peak_current = current[num_voltages]; } float numerator = peak_current - current0[15]; float denominator = current10[15] - current0[15]; float value = numerator / denominator; float absolute_value = abs (value); cout << "The Proportional Effect is " << absolute_value << endl; outfile << conc << " " << absolute_value << endl; cout << endl << endl; } outfile.close (); }
越界问题解答
- 你所有读写数组的操作都错误地用
num_voltages(值为16)作为下标,而数组current、voltage的合法下标范围是0到15。当前代码能输出“正确”结果是未定义行为的巧合:你每次都把数据写到数组末尾外的一块内存,后续读取时刚好读到这块区域,但这非常危险,程序随时可能崩溃或输出错误结果。 - 替换成
i后出错,是因为后续找峰值的逻辑也写错了,没有同步修正所有错误下标。
代码改进方案
核心修正点:
- 所有数组读写统一用循环变量
i作为下标,彻底避免越界。 - 找最大值时同步记录对应电压,不再读取越界元素。
- 重复逻辑封装成函数,消除冗余代码。
- 用
std::vector替代C风格数组,更安全且适配数据行数变化。 - 修正
current0、current10的越界问题(原代码定义大小为15的数组却访问下标15)。
改进后的代码:
#include <fstream> #include <iostream> #include <vector> #include <string> #include <cmath> // 读取文件数据,返回峰值电流和对应电压 std::pair<float, float> readFileAndFindPeak(const std::string& filename, std::vector<float>& voltages, std::vector<float>& currents) { std::ifstream infile(filename); if (!infile) { std::cout << "未找到文件: " << filename << std::endl; exit(1); } std::cout << "正在读取文件: " << filename << std::endl; voltages.clear(); currents.clear(); float v, c; while (infile >> v >> c) { voltages.push_back(v); currents.push_back(c); } infile.close(); std::cout << "文件读取完成" << std::endl; // 查找峰值电流及对应电压 float peak_current = -10.0f; float peak_voltage = 0.0f; for (size_t i = 0; i < currents.size(); ++i) { if (currents[i] > peak_current) { peak_current = currents[i]; peak_voltage = voltages[i]; } } return {peak_current, peak_voltage}; } int main() { std::ofstream outfile; std::vector<float> voltages, currents; // 生成浓度vs峰值电流文件 outfile.open("Conc_vs_peak_current.txt"); for (int conc = 0; conc <= 10; conc += 2) { std::string filename = "IK_IV_" + std::to_string(conc) + ".txt"; auto [peak_current, peak_voltage] = readFileAndFindPeak(filename, voltages, currents); std::cout << "峰值电流 = " << peak_current << ", 对应电压 = " << peak_voltage << "\n\n"; outfile << conc << " " << peak_current << " " << peak_voltage << "\n"; } outfile.close(); // 获取浓度0和10的峰值电流 float peak0 = readFileAndFindPeak("IK_IV_0.txt", voltages, currents).first; float peak10 = readFileAndFindPeak("IK_IV_10.txt", voltages, currents).first; // 计算比例效应并输出 outfile.open("Proportional_effect.txt"); for (int conc = 0; conc <= 10; conc += 2) { std::string filename = "IK_IV_" + std::to_string(conc) + ".txt"; auto [peak_current, _] = readFileAndFindPeak(filename, voltages, currents); float numerator = peak_current - peak0; float denominator = peak10 - peak0; float value = numerator / denominator; float absolute_value = std::abs(value); std::cout << "比例效应值 = " << absolute_value << "\n\n"; outfile << conc << " " << absolute_value << "\n"; } outfile.close(); return 0; }
关键修正说明
- 用
std::vector替代固定大小数组,自动适配文件数据行数,无需硬写16。 - 封装
readFileAndFindPeak函数,避免重复代码,提升可维护性。 - 找峰值时同步记录对应电压,确保数据完全合法。
- 所有数组访问使用合法下标,用
size_t匹配vector的长度类型,避免类型不匹配。 - 删除冗余变量,代码结构更简洁清晰。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

