C++ 中的局部变量问题

local variable issue in c++

本文关键字:问题 局部变量 C++      更新时间:2023-10-16

我刚开始学习 c++ 的基础知识,我有 vb.net 和 c# 的经验

现在我认为要了解一些欧拉项目的基础知识将是一个很好的练习。我在尝试解决问题 4 时遇到了一个非常奇怪的问题,可能是因为对 c++ 缺乏了解。

我有 2 个场景,一个在工作,一个不工作(>当执行 sprintf 命令时,a 变量只是从 999 跳到 768,如下所示(,现在我的问题是:为什么在解决方案 1 中会发生这种情况?唯一的区别是循环变量 a 和 b 是在循环之前声明的,因为在解决方案 2 中,它们是用循环声明的。

解决方案 1(不起作用(:

int a =999;
int b =999;
int lb = 100;
int c = 0;
char strNumber[6];
int result = 0;
int ra = 0;
int rb = 0;
for (a=999; a>=100; a--){
    for (b = a; b>=lb; b--){
        c = a * b;
        sprintf(strNumber, "%d", c);
        if (isPalindrome(strNumber)){
            if (c > result){
                result = c;
                lb = b;
                rb = b;
                ra = a;
            }
            b = 0;
        }
    }
}

解决方案 2(工作(:

int lb = 100;
int c = 0;
char strNumber[6];
int result = 0;
int ra = 0;
int rb = 0;
for (int a=999; a>=100; a--){
    for (int b = a; b>=lb; b--){
        c = a * b;
        sprintf(strNumber, "%d", c);
        if (isPalindrome(strNumber)){
            if (c > result){
                result = c;
                lb = b;
                rb = b;
                ra = a;
            }
            b = 0;
        }
    }
}

实际上两者都有相同的问题,即未定义的行为。问题源于这里:

char strNumber[6];

此变量无法容纳字符串表示中的 999 x 999 值,因为末尾还有一个空字符''。因此,当您调用 sprintf 将整数转换为其字符串表示形式时,就在函数内部,当它尝试将字符''放在索引 6 处时,它会调用未定义的行为,因为05 的索引已经被六位数字占用998001这是 999 x 999 的乘积。

您应该至少定义它的大小7

char strNumber[7]; //one char for null-character.

至于为什么你的第二个代码有效是因为你很幸运(相当不幸(。这就是未定义的行为的含义:任何事情都可能发生。它可以运行,也可能不运行。语言规范和编译器都不保证行为,因此未定义的行为。

正如@James Kanze在评论中指出的那样,真正的解决方案是忘记sprintf,并更好地使用std::ostringstreamstd::string作为:

#include <sstream> //for std::ostringstream 
#include <string>  //for std::string 
std::ostringstream ss;
ss << number;
std::string s = ss.str(); //get the string representation of the number
第一次

通过循环时,c将是一个 6 位数字 (999²(。
因此,sprintf(strNumber, "%d", c);将写入 7 个字符到strNumber:六位数字和著名的空终止符。由于您只为strNumber保留了六个字符,因此最后一次写入会破坏某些内容。

在你的第二种情况下,它碰巧没有出现一些重要的事情,但这只是"运气",你的代码的行为在这两种情况下都是未定义的。

strNumber中保留一个额外的字符,据我所知,两个版本应该工作相同。