You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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后出错,是因为后续找峰值的逻辑也写错了,没有同步修正所有错误下标。

代码改进方案

核心修正点:

  1. 所有数组读写统一用循环变量i作为下标,彻底避免越界。
  2. 找最大值时同步记录对应电压,不再读取越界元素。
  3. 重复逻辑封装成函数,消除冗余代码。
  4. 用std::vector替代C风格数组,更安全且适配数据行数变化。
  5. 修正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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 06:47:47