自定义 strtoi 函数编译时问题
Custom strtoi function compile time issue
我正在尝试实现一个非常简单的 strtoi
功能。当动态创建传递的参数时它工作正常(下面的案例 2)。但是,如果 char 是由在编译时分配的 char[]
创建的,我会在 len
上得到一个常量值,因为 std::strlen(ch)
打乱了我的逻辑,我找不到一个解决方案。
int strtoi(char* ch)
{
int sum {0};
int len = static_cast<int>(std::strlen(ch));
int skipLast = static_cast<int>(static_cast<int>(ch[0]) == 45);
//Integer Method
for(int i = len - 1; i >= 0 + skipLast; i--)
{
if(static_cast<int>(ch[i]) < 48 || static_cast<int>(ch[i]) > 57)
return 0;
sum += (ch[i]-48) * std::pow(10,i-skipLast);
}
sum = skipLast == 1 ? -sum : sum;
return sum;
}
int main()
{
char pos[3] {'1','2','3'};
std::cout << strtoi(pos) << std::endl;
char neg[4] {'-','1','2','3'};
std::cout << strtoi(neg) << std::endl;
return 0;
}
Returns:0
和 -123
。我的函数中的 len
变量没有获得第一次调用的预期值,我认为这是因为 neg[4]
分配的内存比 pos[3]
多。然而,对于第二种情况:
int main()
{
char* pos;
pos = new char[3] {'1','2','3'};
std::cout << strtoi(pos) << std::endl;
char* neg;
neg = new char[4] {'-','1','2','3'};
std::cout << strtoi(neg) << std::endl;
return 0;
}
Returns123
,-123
。预期的结果。
我猜这是因为在第一种情况下,编译器根据 char[4]
数组为函数及其参数分配内存。这个对吗?
第二种情况如何工作,编译器如何为动态变量的函数分配内存?
使该功能适用于这两种情况的可能解决方案是什么?
在此先感谢您的帮助。
strlen
要求字符串以 null 结尾,像这样:
char* pos = new char[4] {'1','2','3','[=10=]'};
std::cout << strlen(pos) << "\n"; // Shows "3"
添加这个空终止符有一个简写方式:
const char[] pos = "123";
std::cout << strlen(pos) << "\n"; // Shows "3"
std::cout << sizeof(pot) << "\n"; // Shows "4"
我为pos使用了数组类型只是为了说明它真的是4个字符;您可以改用 const char*
(实际上这很典型),但是 sizeof
行将不起作用。
请注意,如果你像这样分配一个字符串文字,那么你以后不能在它上面使用 delete
,而你可以(并且应该)使用 delete
如果你使用 new
,或 delete[]
数组。
你遇到的问题是你忘记了 char
字符串在 C++ 中真的叫做 null-terminated 字节字符串 .
null-terminator 是所有标准字符串函数(如 std::strlen
)将寻找的字符串结束位置。
您的字符串 不是 空终止的,因此将它们传递给例如std::strlen
将导致 undefined behavior,因为它们超出数组或分配的内存范围,寻找这个不存在的空终止符。
要解决该问题,您需要确保所有字符串都以 null 结尾:
// will create pos as an array of *four* characters, the last being the null-terminator
char pos[] = "123";
我修改了你的代码如下:
int strtoi(char* ch, int len)
{
int sum{ 0 };
//int len = (std::strlen(ch));
int skipLast = static_cast<int>(static_cast<int>(ch[0]) == 45);
//Integer Method
for (int i = len - 1; i >= 0 + skipLast; i--)
{
if (static_cast<int>(ch[i]) < 48 || static_cast<int>(ch[i]) > 57)
return 0;
sum += (ch[i] - 48) * std::pow(10, i - skipLast);
}
sum = skipLast == 1 ? -sum : sum;
return sum;
}
int main()
{
char pos[3]{ '1','2','3' };
std::cout << strtoi(pos, 3) << std::endl;
char neg[4]{ '-','1','2','3' };
std::cout << strtoi(neg, 4) << std::endl;
return 0;
}
strtoi
无法计算函数内的数组长度。你必须用数组指针传递它,因为没有 '\0' 字符。
这就是为什么当您将数组传递给函数时,您还必须传递数组大小或长度。
上述修改代码的输出:
321
-321
我正在尝试实现一个非常简单的 strtoi
功能。当动态创建传递的参数时它工作正常(下面的案例 2)。但是,如果 char 是由在编译时分配的 char[]
创建的,我会在 len
上得到一个常量值,因为 std::strlen(ch)
打乱了我的逻辑,我找不到一个解决方案。
int strtoi(char* ch)
{
int sum {0};
int len = static_cast<int>(std::strlen(ch));
int skipLast = static_cast<int>(static_cast<int>(ch[0]) == 45);
//Integer Method
for(int i = len - 1; i >= 0 + skipLast; i--)
{
if(static_cast<int>(ch[i]) < 48 || static_cast<int>(ch[i]) > 57)
return 0;
sum += (ch[i]-48) * std::pow(10,i-skipLast);
}
sum = skipLast == 1 ? -sum : sum;
return sum;
}
int main()
{
char pos[3] {'1','2','3'};
std::cout << strtoi(pos) << std::endl;
char neg[4] {'-','1','2','3'};
std::cout << strtoi(neg) << std::endl;
return 0;
}
Returns:0
和 -123
。我的函数中的 len
变量没有获得第一次调用的预期值,我认为这是因为 neg[4]
分配的内存比 pos[3]
多。然而,对于第二种情况:
int main()
{
char* pos;
pos = new char[3] {'1','2','3'};
std::cout << strtoi(pos) << std::endl;
char* neg;
neg = new char[4] {'-','1','2','3'};
std::cout << strtoi(neg) << std::endl;
return 0;
}
Returns123
,-123
。预期的结果。
我猜这是因为在第一种情况下,编译器根据 char[4]
数组为函数及其参数分配内存。这个对吗?
第二种情况如何工作,编译器如何为动态变量的函数分配内存?
使该功能适用于这两种情况的可能解决方案是什么?
在此先感谢您的帮助。
strlen
要求字符串以 null 结尾,像这样:
char* pos = new char[4] {'1','2','3','[=10=]'};
std::cout << strlen(pos) << "\n"; // Shows "3"
添加这个空终止符有一个简写方式:
const char[] pos = "123";
std::cout << strlen(pos) << "\n"; // Shows "3"
std::cout << sizeof(pot) << "\n"; // Shows "4"
我为pos使用了数组类型只是为了说明它真的是4个字符;您可以改用 const char*
(实际上这很典型),但是 sizeof
行将不起作用。
请注意,如果你像这样分配一个字符串文字,那么你以后不能在它上面使用 delete
,而你可以(并且应该)使用 delete
如果你使用 new
,或 delete[]
数组。
你遇到的问题是你忘记了 char
字符串在 C++ 中真的叫做 null-terminated 字节字符串 .
null-terminator 是所有标准字符串函数(如 std::strlen
)将寻找的字符串结束位置。
您的字符串 不是 空终止的,因此将它们传递给例如std::strlen
将导致 undefined behavior,因为它们超出数组或分配的内存范围,寻找这个不存在的空终止符。
要解决该问题,您需要确保所有字符串都以 null 结尾:
// will create pos as an array of *four* characters, the last being the null-terminator
char pos[] = "123";
我修改了你的代码如下:
int strtoi(char* ch, int len)
{
int sum{ 0 };
//int len = (std::strlen(ch));
int skipLast = static_cast<int>(static_cast<int>(ch[0]) == 45);
//Integer Method
for (int i = len - 1; i >= 0 + skipLast; i--)
{
if (static_cast<int>(ch[i]) < 48 || static_cast<int>(ch[i]) > 57)
return 0;
sum += (ch[i] - 48) * std::pow(10, i - skipLast);
}
sum = skipLast == 1 ? -sum : sum;
return sum;
}
int main()
{
char pos[3]{ '1','2','3' };
std::cout << strtoi(pos, 3) << std::endl;
char neg[4]{ '-','1','2','3' };
std::cout << strtoi(neg, 4) << std::endl;
return 0;
}
strtoi
无法计算函数内的数组长度。你必须用数组指针传递它,因为没有 '\0' 字符。
这就是为什么当您将数组传递给函数时,您还必须传递数组大小或长度。
上述修改代码的输出:
321
-321