我正在尝试编写一个程序,该程序循环遍历所有ASCII字符,选择字母,然后将其附加到字符串中,然后输出该字符串。我已经编写了以下代码:
#include <iostream>
#include <string>
#include "ctype.h"
using namespace std;
int main()
{
string str;
for (char k = 0; k <= 255; k++)
if (isalpha(k) != 0) {
str += k;
}
cout << str << '\n';
}
但是,当我运行这段代码时,我收到一个“ bad_alloc”错误,据我所知,这意味着我内存不足。因此,我一定在我的代码中做了非常错误的事情。一般来说,我对C ++还是陌生的,有人可以指出我的错误(可能很多)吗?
答案 0 :(得分:4)
在编译代码(-Wall -Wextra
)时应启用所有警告。这样做将导致编译器出现以下消息:
c声:
常数255与'char'类型表达式的比较结果始终为真[-Wtautologic-constant-out-of-range-compare]
gcc:
警告:由于数据类型[-Wtype-limits]的范围有限,比较总是正确的
根据编译器和目标平台的不同,char的签名可能有所不同。 ARM和PowerPC的默认值通常是无符号的,x86和x64的默认值通常是有符号的。
char
的范围(如果签名)为-128到127,要与平台无关,则需要确保使用unsinged char
,但是即使那样,您仍然会遇到{ {1}}会产生相同的<=255
错误,因为bad_alloc
的最大值是unsigned char
,因此您必须使用`k <255;':
255
答案 1 :(得分:1)
将#include <utility>
template<typename... Args>
void f(Args... args) {
// does something with args
}
template<typename... Args> struct
get_f
{
static constexpr auto & get() { return f<Args...>; }
};
template<template<typename...> typename T, typename... Args>
void g(int i, Args&&... args) {
if (i != 0) T<int, Args...>::get()(i, std::forward<Args>(args)...);
else T<Args...>::get()(std::forward<Args>(args)...);
}
int main() {
g<get_f>(0, 0);
return 0;
}
更改为for (char k = 0; k <= 255; k++)
,就可以了。
原因:
系统上的字符是带符号的字符,因此它的范围是for (int k = 0; k <= 255; k++)
到2^n - 1
,其中 n 是 8 (您可以通过打印宏{ {1}}。
因此,当 k 的循环达到 127 并获取下一个值时,该值将变为 -128 ,然后该值环绕&它变成了无限循环。
您可以通过以下方式进行验证:
-(2^n) - 1
输出: -128
答案 2 :(得分:1)
在许多平台上,char
已签名。这意味着它会上升到127,然后出现“溢出”。
溢出具有不确定的行为,但有时看起来像是“包装”为负值。结果是k
将始终小于255
,因此循环将永远不会结束,并且您将一直尝试向字符串中永久添加字符,或者直到耗尽内存为止(繁荣)。
实际上,即使您使用unsigned char
,也永远不会超越255
。
改为使用int
。
由于类似原因,您对isalpha
的呼叫也具有未定义的行为(请参阅the documentation for functions that you use)。