我的 C++ 项目中遇到未知错误?无法弄清楚出了什么问题

问题描述 投票:0回答:1

我的目标是用 c++ 制作一个 计算器。我正在使用 Visual Studio Code计算器将包括计算顺序(首先是括号,然后是 * 和 /,然后是 + 和 -)。在终端中编写一个方程,例如:3 * (4 - 1)。该程序的工作原理是我有一个包含方程作为字符串类型的vector。然后我有2d向量,其中包含作为数字(双精度)的方程和数字的'层'layer 是我用来确定每个数字的计算顺序的东西,由之前的开/闭括号的数量决定。我还没有开始计算数字,但是我面临一个问题,我不知道如何解决。

问题是,每当我在终端中写入内容时,特别是当我输入空格时,代码会在 return 0; at main() 之后停止。然后,我的选项卡中会打开一个名为 'new_allocater.h' 的新文件。此外,根本没有出现任何错误消息,代码停在 'new_allocater.h' 内,就像有一个断点一样。

到目前为止,问题似乎并没有真正阻碍我的代码运行,因为问题出现在main()处的return 0;之后。但它以后肯定会回来咬我的。

这是我的计算器项目的代码:

#include <iostream>
#include <cmath>
#include <vector>
#include <string.h>
#include <bits/stdc++.h>
#include <algorithm>

using namespace std;

vector<string> split(string s, const char f) { // s = string, f = delimiter
    // Function for turning strings into vectors using a delimiter

    vector<string> v; // List of substrings to be returned
    int startPoint = 0; // Startpos of substring
    const int stringLength = s.length();

    for (int i = 0; i < stringLength; i++)
    {
        if (s[i] == f) {
            s.erase(i, 1); // Remove delimiter character from the string
            v.push_back(s.substr(startPoint, i-startPoint));
            startPoint = i;
        }
    }
    v.push_back(s.substr(startPoint, s.back()));
    
    return v;
}

bool isDigit(const string &s) {
    // Return true or false value whether a string is a digit or not
    return s.find_first_not_of("0123456789.") == string::npos;
}

double convertMainToAlt(string s) {
    const int stringLength = s.length();
    for (int i = 0; i < stringLength; i++)
    {
        if (s[i] == '(' || s[i] == ')' || s[i] == 'V') {
            s.erase(i, 1);
            i--;
        }
    }

    if (isDigit(s)) {
        return stod(s);
    }

    else {
        return 0;
    }
}

int main()
{
    // Main variables / vectors / arrays used for the program

    string mainEquation; // String of equation
    vector<string> mainEquationList; // {"(5", "+", "10)", "-", "4.2"}

    getline(cin, mainEquation); // Get user input for the equation
    mainEquationList = split(mainEquation, ' ');

    vector<vector<double>> altEquationList = {{0}, {0}}; /*
    {{equation numbers}, {layer numbers}}*/

    for (int i = 0; i < mainEquationList.size(); i++)
    {
        altEquationList[0][i] = convertMainToAlt(mainEquationList[i]);
    }

    for (int i = 0; i < mainEquationList.size(); i++)
    {
        cout << altEquationList[0][i] << endl;
    }

    cout << "===========================" << endl;
    
    // Layer Number
    /*
    Assign layer number to each element by counting the number of open/closed parantheses before.
    +1 to layer number for every open parantheses that appears before or is on the same element.
    -1 to layer number for every closed paranhteses that appears before the element.*/

    int layerIncOrDec = 0;

    for (int i = 0; i < mainEquationList.size(); i++)
    {
        if (mainEquationList[i].find("(") != string::npos) {
            layerIncOrDec++;
            altEquationList[1][i] = layerIncOrDec;
        } else if (mainEquationList[i].find(")") != string::npos) {
            altEquationList[1][i] = layerIncOrDec;
            layerIncOrDec--;
        } else {
            altEquationList[1][i] = layerIncOrDec;
        }
    }

    int highestLayer = 0;
    for (int i = 0; i < mainEquationList.size(); i++)
    {
        if (altEquationList[1][i] > highestLayer) {
            highestLayer = altEquationList[1][i];
        }
    }

    // Print information

    for (int i = 0; i < mainEquationList.size(); i++)
    {
        cout << altEquationList[0][i] << " - " << altEquationList[1][i] << endl;
    }

    return 0;
}

这是“new_allocater.h”文件的代码: 错误发生在第168行:

// Allocator that wraps operator new -*- C++ -*-

// Copyright (C) 2001-2023 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file bits/new_allocator.h
 *  This is an internal header file, included by other library headers.
 *  Do not attempt to use it directly. @headername{memory}
 */

#ifndef _STD_NEW_ALLOCATOR_H
#define _STD_NEW_ALLOCATOR_H 1

#include <bits/c++config.h>
#include <new>
#include <bits/functexcept.h>
#include <bits/move.h>
#if __cplusplus >= 201103L
#include <type_traits>
#endif

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  /**
   * @brief  An allocator that uses global `new`, as per C++03 [20.4.1].
   * @ingroup allocators
   *
   * This is precisely the allocator defined in the C++ Standard.
   *   - all allocation calls `operator new`
   *   - all deallocation calls `operator delete`
   *
   * This is the default base-class implementation of `std::allocator`,
   * and is also the base-class of the `__gnu_cxx::new_allocator` extension.
   * You should use either `std::allocator` or `__gnu_cxx::new_allocator`
   * instead of using this directly.
   *
   * @tparam  _Tp  Type of allocated object.
   *
   * @headerfile memory
   */
  template<typename _Tp>
    class __new_allocator
    {
    public:
      typedef _Tp        value_type;
      typedef std::size_t     size_type;
      typedef std::ptrdiff_t  difference_type;
#if __cplusplus <= 201703L
      typedef _Tp*       pointer;
      typedef const _Tp* const_pointer;
      typedef _Tp&       reference;
      typedef const _Tp& const_reference;

      template<typename _Tp1>
    struct rebind
    { typedef __new_allocator<_Tp1> other; };
#endif

#if __cplusplus >= 201103L
      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 2103. propagate_on_container_move_assignment
      typedef std::true_type propagate_on_container_move_assignment;
#endif

      __attribute__((__always_inline__))
      _GLIBCXX20_CONSTEXPR
      __new_allocator() _GLIBCXX_USE_NOEXCEPT { }

      __attribute__((__always_inline__))
      _GLIBCXX20_CONSTEXPR
      __new_allocator(const __new_allocator&) _GLIBCXX_USE_NOEXCEPT { }

      template<typename _Tp1>
    __attribute__((__always_inline__))
    _GLIBCXX20_CONSTEXPR
    __new_allocator(const __new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { }

#if __cplusplus <= 201703L
      ~__new_allocator() _GLIBCXX_USE_NOEXCEPT { }

      pointer
      address(reference __x) const _GLIBCXX_NOEXCEPT
      { return std::__addressof(__x); }

      const_pointer
      address(const_reference __x) const _GLIBCXX_NOEXCEPT
      { return std::__addressof(__x); }
#endif

#if __has_builtin(__builtin_operator_new) >= 201802L
# define _GLIBCXX_OPERATOR_NEW __builtin_operator_new
# define _GLIBCXX_OPERATOR_DELETE __builtin_operator_delete
#else
# define _GLIBCXX_OPERATOR_NEW ::operator new
# define _GLIBCXX_OPERATOR_DELETE ::operator delete
#endif

      // NB: __n is permitted to be 0.  The C++ standard says nothing
      // about what the return value is when __n == 0.
      _GLIBCXX_NODISCARD _Tp*
      allocate(size_type __n, const void* = static_cast<const void*>(0))
      {
#if __cplusplus >= 201103L
    // _GLIBCXX_RESOLVE_LIB_DEFECTS
    // 3308. std::allocator<void>().allocate(n)
    static_assert(sizeof(_Tp) != 0, "cannot allocate incomplete types");
#endif

    if (__builtin_expect(__n > this->_M_max_size(), false))
      {
        // _GLIBCXX_RESOLVE_LIB_DEFECTS
        // 3190. allocator::allocate sometimes returns too little storage
        if (__n > (std::size_t(-1) / sizeof(_Tp)))
          std::__throw_bad_array_new_length();
        std::__throw_bad_alloc();
      }

#if __cpp_aligned_new
    if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
      {
        std::align_val_t __al = std::align_val_t(alignof(_Tp));
        return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp),
                               __al));
      }
#endif
    return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp)));
      }

      // __p is not permitted to be a null pointer.
      void
      deallocate(_Tp* __p, size_type __n __attribute__ ((__unused__)))
      {
#if __cpp_sized_deallocation
# define _GLIBCXX_SIZED_DEALLOC(p, n) (p), (n) * sizeof(_Tp)
#else
# define _GLIBCXX_SIZED_DEALLOC(p, n) (p)
#endif

#if __cpp_aligned_new
    if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
      {
        _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n),
                     std::align_val_t(alignof(_Tp)));
        return;
      }
#endif
    _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n)); // Line 168, the error occurs here
      }

#undef _GLIBCXX_SIZED_DEALLOC
#undef _GLIBCXX_OPERATOR_DELETE
#undef _GLIBCXX_OPERATOR_NEW

#if __cplusplus <= 201703L
      __attribute__((__always_inline__))
      size_type
      max_size() const _GLIBCXX_USE_NOEXCEPT
      { return _M_max_size(); }

#if __cplusplus >= 201103L
      template<typename _Up, typename... _Args>
    __attribute__((__always_inline__))
    void
    construct(_Up* __p, _Args&&... __args)
    noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
    { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }

      template<typename _Up>
    __attribute__((__always_inline__))
    void
    destroy(_Up* __p)
    noexcept(std::is_nothrow_destructible<_Up>::value)
    { __p->~_Up(); }
#else
      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 402. wrong new expression in [some_] allocator::construct
      __attribute__((__always_inline__))
      void
      construct(pointer __p, const _Tp& __val)
      { ::new((void *)__p) _Tp(__val); }

      __attribute__((__always_inline__))
      void
      destroy(pointer __p) { __p->~_Tp(); }
#endif
#endif // ! C++20

      template<typename _Up>
    friend __attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR bool
    operator==(const __new_allocator&, const __new_allocator<_Up>&)
    _GLIBCXX_NOTHROW
    { return true; }

#if __cpp_impl_three_way_comparison < 201907L
      template<typename _Up>
    friend __attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR bool
    operator!=(const __new_allocator&, const __new_allocator<_Up>&)
    _GLIBCXX_NOTHROW
    { return false; }
#endif

    private:
      __attribute__((__always_inline__))
      _GLIBCXX_CONSTEXPR size_type
      _M_max_size() const _GLIBCXX_USE_NOEXCEPT
      {
#if __PTRDIFF_MAX__ < __SIZE_MAX__
    return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp);
#else
    return std::size_t(-1) / sizeof(_Tp);
#endif
      }
    };

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

#endif

c++ c++11 calculator
1个回答
0
投票

我想说问题是这个循环

for (int i = 0; i < stringLength; i++)
{
    if (s[i] == f) {
        s.erase(i, 1); // Remove delimiter character from the string
        v.push_back(s.substr(startPoint, i-startPoint));
        startPoint = i;
    }
}

问题是您正在缩短字符串

s.erase(i,1)
但您没有更新
stringLength
变量。因此,您可能会面临字符串访问越界的风险。

更改循环直接查询长度

for (int i = 0; i < s.length(); i++)

这种情况(迭代集合的同时从该集合中删除项目)是非常常见的错误来源。在编写类似情况时,您应该始终格外小心。

© www.soinside.com 2019 - 2024. All rights reserved.