C 程序在CIN之后突然结束

C++ Program abruptly ends after cin

本文关键字:突然 结束 之后 CIN 程序      更新时间:2023-10-16

我正在编写代码以获取非常大的斐波那契数字的最后一位数字,例如fib(239)等。开始然后将它们转换为int,而不是将值存储回另一个字符串。我无法测试我写的内容,因为我的程序在std::cin >> n;行之后不断关闭。这是我到目前为止所拥有的。

#include <iostream>
#include <string>
using std::cin;
using std::cout;
using namespace std; 
char get_fibonacci_last_digit_naive(int n) {
cout << "in func";
if (n <= 1)
    return (char)n;
string previous= "0";
string current= "1";
for (int i = 0; i < n - 1; ++i) {
    //long long tmp_previous = previous;
    string tmp_previous= previous; 
    previous = current;
    //current = tmp_previous + current; // could also use previous instead of current
    // for with the current length of the longest of the two strings
    //iterates from the end of the string to the front
    for (int j=current.length(); j>=0; --j) {
        // grab consectutive positions in the strings & convert them to integers
        int t;
        if (tmp_previous.at(j) == '') 
            // tmp_previous is empty use 0 instead
            t=0;  
        else
            t = stoi((string&)(tmp_previous.at(j))); 
        int c = stoi((string&)(current.at(j)));
        // add the integers together
        int valueAtJ= t+c;
        // store the value into the equivalent position in current
        current.at(j) = (char)(valueAtJ); 
    }
    cout << current << ":current value"; 
}
return current[current.length()-1];
}
int main() {
int n;
std::cin >> n;
//char& c = get_fibonacci_last_digit_naive(n);  // reference to a local variable returned WARNING
// http://stackoverflow.com/questions/4643713/c-returning-reference-to-local-variable
cout << "before call";
char c = get_fibonacci_last_digit_naive(n);
std::cout << c << 'n';
return 0;
}

输出始终相同。无论我输入什么,输出始终相同。这是我用来运行代码及其输出的行。

$ g++ -pipe -O2 -std=c++14 fibonacci_last_digit.cpp -lm
$ ./a.exe
10

10之后有一个newline,而10是我输入的n。感谢任何帮助。和节日快乐!

我正在发布此信息,因为您对问题的理解似乎正在倒退到您试图部署的解决方案的选择。这是一个XY问题的一个示例,一个问题,解决方案方法的选择方法以及其实现的问题或障碍,使您要解决的实际问题混淆了。

您正在尝试计算fibonacci编号的最终数字,其中n可能是群体。斐波那契序列的基本理解告诉您

fib(0) = 0 
fib(1) = 1 
fib(n) = fib(n-1) + fib(n-2), for all n larger than 1.

求解其 value fib(N)的迭代解决方案是:

unsigned fib(unsigned n)
{
    if (n <= 1)
        return n;
    unsigned previous = 0;
    unsigned current = 1;
    for (int i=1; i<n; ++i)
    {
        unsigned value = previous + current;
        previous = current;
        current = value;
    }
    return current;
}

一切都很好,但是一旦N导致我们选择的数据类型的存储功能溢出(在上述情况下,大多数32位平台上的unsigned将在仅47个迭代后溢出)。

,但我们不需要每次迭代的实际fib。我们只需要每个迭代的最后一位数字。好吧,Base-10 Last Digit非常容易从任何未签名的值中获得。对于我们的示例,只需替换以下内容:

current = value;

与此:

current = value % 10;

给我们一种几乎相同的算法,但只能"记住"每个迭代的最后一个数字:

unsigned fib_last_digit(unsigned n)
{
    if (n <= 1)
        return n;
    unsigned previous = 0;
    unsigned current = 1;
    for (int i=1; i<n; ++i)
    {
        unsigned value = previous + current;
        previous = current;
        current = value % 10; // HERE
    }
    return current;
}

现在current始终拥有先前总和的最后一位数字,无论是否超过10款,实际上与我们无关。一旦我们有下一个迭代可以使用它来计算两个单个正数的总和不得超过18个,而再次,我们只需要从那的最后一个数字 next 迭代等。这一直持续到我们迭代多次要求,完成后,最终答案将出现。

验证

我们知道前20个左右的斐波那契数字看起来像这样,通过 fib

0:0
1:1
2:1
3:2
4:3
5:5
6:8
7:13
8:21
9:34
10:55
11:89
12:144
13:233
14:377
15:610
16:987
17:1597
18:2584
19:4181
20:6765

这是我们通过fib_last_digit运行算法时得到的:

0:0
1:1
2:1
3:2
4:3
5:5
6:8
7:3
8:1
9:4
10:5
11:9
12:4
13:3
14:7
15:0
16:7
17:7
18:4
19:1
20:5

应该给您带来萌芽的信心感,这可能是您寻求的算法,您可以完全放弃字符串操作。

在Mac上运行此代码:

libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: basic_string before callin funcAbort trap: 6


代码本身最明显的问题是以下行:

for (int j=current.length(); j>=0; --j) {

原因:

  1. 如果您正在执行诸如current.at(j)之类的事情,这将立即崩溃。例如,字符串" blah"具有长度4,但位置4。
  2. tmp_p_previous的长度可能与当前不同。例如,当您从8到13时,呼叫tmp_previous.at(j)将崩溃。

另外,正如其他人所指出的那样,如果您唯一感兴趣的是最后一位数字,那么您就不需要遇到循环浏览每个数字的每个数字的麻烦。这里的诀窍是只记住上一个和当前的最后一位数字,因此大量的数字绝不是问题,您不必做诸如Stoi之类的事情。

作为先前答案的替代方案是字符串添加。我用斐波那契数的100000进行了测试,并且在短短几秒钟内就可以正常工作。仅与最后一位数字一起工作可以解决您的问题,从而确定更大的数字。对于所有需要斐波那契号的人,这里是一个算法:

std::string str_add(std::string a, std::string b)
{
    // http://ideone.com/o7wLTt
    size_t n = max(a.size(), b.size());
    if (n > a.size()) {
        a = string(n-a.size(), '0') + a;
    }
    if (n > b.size()) {
        b = string(n-b.size(), '0') + b;
    }
    string result(n + 1, '0');
    char carry = 0;
    std::transform(a.rbegin(), a.rend(), b.rbegin(), result.rbegin(), [&carry](char x,  char y)
    {
        char z = (x - '0') + (y - '0') + carry;
        if (z > 9) {
            carry = 1;
            z -= 10;
        } else {
            carry = 0;
        }
        return z + '0';
    });
    result[0] = carry + '0';
    n = result.find_first_not_of("0");
    if (n != string::npos) {
        result = result.substr(n);
    }
    return result;
}
std::string str_fib(size_t i)
{
    std::string n1 = "0";
    std::string n2 = "1";
    for (size_t idx = 0; idx < i; ++idx) {
        const std::string f = str_add(n1, n2);
        n1 = n2;
        n2 = f;
    }
    return n1;
}
int main() {
    const size_t i = 100000;
    const std::string f = str_fib(i);
    if (!f.empty()) {
        std::cout << "fibonacci of " << i << " = " << f << " | last digit: " << f[f.size() - 1] << std::endl;
    }
    std::cin.sync(); std::cin.get();
    return 0;
}

首先计算fibonacci编号,然后使用std::to_string()int转换为std::string。在下面,您可以在最后一个索引上使用[]操作员提取最后一个数字。

int fib(int i)
{
    int number = 1;
    if (i > 2) {
        number = fib(i - 1) + fib(i - 2);
    }
    return number;
}
int main() {
    const int i = 10;
    const int f = fib(i);
    const std::string s = std::to_string(f);
    if (!s.empty()) {
        std::cout << "fibonacci of " << i << " = " << f << " | last digit: " << s[s.size() - 1] << std::endl;
    }
    std::cin.sync(); std::cin.get();
    return 0;
}

避免使用关键字using的重复。

还考虑在数字变大时从int切换到longlong long。由于斐波那契数为正,也使用unsigned