如何遍历所有ASCII字符?

时间:2019-09-15 18:10:16

标签: c++

我正在尝试编写一个程序,该程序循环遍历所有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 ++还是陌生的,有人可以指出我的错误(可能很多)吗?

3 个答案:

答案 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)。