C++char类型和输入输出优化

目录
  • 1、char类型
  • 2、getchar、putchar、cin.get、cout.put
  • 3、输入输出中文

1、char类型

char的全称是character,也就是字符的意思。顾名思义,char类型是专门为了存储字符而设计的。

计算机存储数字非常方便,只需要将其转化成二进制即可。但存储字符就有点麻烦了,一般都是通过对字符进行数字化编码。这也就是为什么char类型本质上是另外一种整数,因为它存储的其实是字符的数字编码。

char一共有8个二进制位,即一个字节,理论上能够存储256个字符。基本上足够涵盖计算机当中所有的字母、标点符号以及数字,即ASCII码。

ASCII的全称是美国信息交换标准代码,它是一套电脑编码系统,包含了所有英文字母以及标点符号和一些特殊字符。全表一共有128个字符,刚好可以用一个char(有符号)来存储。

大家可以参考一下下表,Dec表示编号,Char表示字符。

其中数字0的编号是48,字母a的编号是97,大写字母A的标号是65。

当我们把一个字符赋值给char型变量的时候,它会去查ASCII表,找到字符对应的编号。同样,当我们使用%c输出一个字符的时候,它也会去寻找char中存储的编码对应的符号进行输出。

既然字符在C++当中都是以数字的形式存储的,那么我们就可以对它来进行加减运算。

比如:

char c = 'a';
cout << ++c << endl;

得到的结果是'b',有加自然也有减,我们也可以对它做减法操作。

char c = 'b';
cout << --b << endl;

得到的结果就是'a'。

另外,我们还可以对于两个char类型的变量进行减法操作。比如用得比较多的就是将字符型的数字转成int型。

char c = '1';
int num = c - '0';

这样我们得到的num就是数字型的1。

再比如,我们还可以通过大于小于符号来判断char类型的范围:

char c = '1';
if (c >= '0' && c <= '9') {
    cout << "c is a number" << endl;
}

2、getchar、putchar、cin.get、cout.put

getcharputchar都是C语言当中专门面向字符IO的函数,也就是读入和输出字符的函数。

因为确定了处理的数据类型是字符,不需要额外的格式说明,因此getcharputchar的效率要比scanf和printf更高。

所以在算法竞赛领域,有人为了提升程序的性能,丧心病狂地使用getchar代替scanf来读入数据。

我这里贴一段使用getchar来读入int型的代码,给大家做一个参考。这个属于标准的奇淫技巧,不推荐使用。

void read(int &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') {
        if (s == '-') {
            f = -1;
            s = getchar();
        }
    }
    while (s >= '0' && s <= '9') {
        x = x * 10 + s - '0';
        s = getchar();
    }
    x *= f;
}

cin.getcout.putgetcharputchar的用法类似,只不过是C++当中的特性。大家可以参考一下下面这个例子,就不过多赘述了。

char c;
cin.get(c);
cout.put(c);

3、输入输出中文

关于这一段我犹豫了很久要不要加,因为实在是没有相关经验,毕竟之前只刷题了。纠结了很久还是决定写上,因为这个问题对于不少同学应该挺重要的,尤其是想要做C++工程的同学。本人水平有限,勉强整理了一下各方资料,如有错误,欢迎指出~

其实直接在C++当中是可以直接输出中文的,这并不会有什么问题。

比如下列代码,是可以完美运行的:

string str;
cin >> str;
cout << str << endl;
cout << str.length() << endl;

只是为什么最后输出的长度是6?因为我是在Mac上跑的这段代码。在Mac当中默认使用utf-8编码,一个汉字的长度是3个字节。C++当中的字符串计算长度的时候统计的是字节的数量,所以两个汉字的长度是6。

如果我们是在源代码当中写入了中文,比如:

string str = "中文";
cout << str << endl;

这就可能一些问题,最常见的问题就是代码存储环境和运行环境的默认编码不同,比如IDE当中默认是utf-8编码,但是终端默认是gbk编码(windows系统常见)。这就会导致输出的结果是乱码。

解决方案是我们可以使用wchar_t,wchar_tchar的宽类型版本,它占据两个字节。可以用来存储unicode编码的字符:

const wchar_t* str = L"中文";

我们在中文两个字之前加上了L修饰符,它告诉编译器,这是一个宽字符,我们需要编译器根据locale来进行翻译。

locale是指根据计算机用户使用的语言、所在的国家或地区以及文化传统而定义的软件运行时的语言环境。可以将locale理解为一系列环境变量。locale环境变量值的格式为language_area.charset。languag表示语言,例如英语或中文;area表示使用该语言的地区,例如美国或者中国大陆;charset表示字符集编码,例如UTF-8或者GBK

这些环境变量会对日期格式,数字格式,货币格式,字符处理等多个方面产生影响。在Linux系统下打开Terminal,输入locale命令,就可查看当前系统使用的语言环境。

locale的结果包含12类,我在网上也找到了表格:

LANG指的是未设置的默认值,大部分程序应用LANGUAGE指定的语言作为界面语言。LC_ALL同时设置所有的内容,并且其优先级比每个内容单独设置的优先级都高,而LANG的优先级最低。

cincout可以看成是针对char的流,所以不适合应用在wchar_t类型的处理上。与之对应我们应该使用wcin和wcout。而wcout默认采用的是C local,并不认识中文,所以我们要先对wcoutlocal进行设置。将其设置成和运行环境的local一致。

大约有以下几种设置方法:

#include <codecvt>
const wchar_t* str = L"中文";

// 使用默认local
locale loc("");
wcout.imbue(loc);

// 使用local命令显示的结果
locale loc("en_US.UTF-8");
wcout.imbue(loc);

// 使用标准facet
locale utf8(locale(), new codecvt_utf8_utf16<wchar_t> );
wcout.imbue(utf8);

// 使用系统local
locale sys_loc("");
wcout.imbue(sys_loc);

wcout << str << endl;
cout << wcslen(str) << endl;

我们可以使用wcslen来计算宽字节字符串的长度,它输出的结果是2,而不是6。

C++当中的编码设置是一个很大的问题,因为在刷题当中几乎不会遇到,我们这里也只是做一个浅尝辄止的讨论。大家如果有需要,可自行深入研究。

到此这篇关于C++char类型和输入输出优化的文章就介绍到这了,更多相关C++char类型和输入输出优化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++中const char*、char const*、char * const三者的区别

    目录 一.const char *ptr; 二.char const *ptr; 三.char * const ptr; C/C++ 中关于以下三种定义: const char *ptr; char const *ptr; char * const ptr; 整理三者之间的区别与联系. 一.const char *ptr; 定义一个指向字符常量的指针,这里,ptr是一个指向 char* 类型的常量,所以不能用ptr来修改所指向的内容,换句话说,*ptr的值为const,不能修改.但是ptr的声明

  • C++char类型和输入输出优化

    目录 1.char类型 2.getchar.putchar.cin.get.cout.put 3.输入输出中文 1.char类型 char的全称是character,也就是字符的意思.顾名思义,char类型是专门为了存储字符而设计的. 计算机存储数字非常方便,只需要将其转化成二进制即可.但存储字符就有点麻烦了,一般都是通过对字符进行数字化编码.这也就是为什么char类型本质上是另外一种整数,因为它存储的其实是字符的数字编码. char一共有8个二进制位,即一个字节,理论上能够存储256个字符.基

  • C++ WideCharToMultiByte()函数案例详解

    函数WideCharToMultiByte() 详解 函数原型: int WideCharToMultiByte( UINT CodePage, DWORD dwFlags, LPWSTR lpWideCharStr, int cchWideChar, LPCSTR lpMultiByteStr, int cchMultiByte, LPCSTR lpDefaultChar, PBOOL pfUsedDefaultChar ); 函数功能: 此函数把宽字符串转换成指定的新的字符串,如ANSI,U

  • C++中putchar与getchar函数的细节及运用

    在C语言中,输入和输出除了用printf和scanf外,另外还有用于输入字符的函数为getchar()函数,用于输出字符的函数为putchar()函数. 功能解释如下: 下面用例子来说明函数的用法 #include <stdio.h> int main() { int ch = 0; while ((ch = getchar()) != EOF) putchar(ch); return 0; } 结果: 可以看出,当按下键盘上的回车键时,getchar函数会读取到屏幕中输入的字符和回车字符'\

  • C++编程之CString、string与、char数组的转换

    C++编程之CString.string与.char数组的转换 虽然网上关于CString,string,char数组的转换的文章一大堆,但是感觉很乱很杂,而且许多并不能真正达到目的,在此,我把自己调试通过的转换方法贴到这里,做个笔记. 编译环境:vs2008, Use Unicode Character Set //----------------ANSI字符串转换为UNICODE字符串----------------------// // 待转换的数组 char szDCBparam[50]

  • C++中string转换为char*类型返回后乱码问题解决

    问题来源: 在写二叉树序列化与反序列化时发现序列化函数为char* Serialize1(TreeNode *root)  其函数返回类型为char*,但是我在实现的过程中为了更方便的操作添加字符串使用的是C++中string类型的变量,这就导致我最后得到的结果res是string类型,若是要返回需要转化为char *类型.而等我将string类型转为char*后返回在主函数中就成了乱码. 先直接说最后的解决办法: 第一种:定义一个char数组,数组长度为stringlength+1,将stri

  • C++中char[]能修改char*却不行

    少扯淡没用的,直接上代码 int main(int argc, char *argv[]) { char p[74] = "abcefghijkmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm"; char *a = "abcefghijkmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm"; printf(&qu

  • C++程序中main(int argc, char *argv[])函数的参数意义

    在vs中编写C++程序时,可以往主函数里传递两个参数:main(int argc,char *argv[]).主函数不能被其它函数调用,在window操作系统下调用者是. 测试程序如下所示: #include "stdafx.h" #include "iostream" using namespace std; int main(int argc,char *argv[]) { int i; for (i = 0; i < argc; i++) { cout

  • C++ 将字符串值赋给CHAR数组的实现

    我就废话不多说啦,大家还是直接看代码吧~ CHAR name[50]; strcpy(name, "tagname"); 补充:将char* 赋值给std::string的一些陷阱 这段时间,总是要使用char或者char* 赋值给std::string,踩了不少坑.于是写了个测试代码,如果你不想看我的代码,可以跳到下面直接看总结: #include <string> #include <iostream> using namespace std; int ma

  • 浅谈char*类型返回值和字符串常量

    看这样一段简单的程序: #include <stdio.h> char* fun() { return "fun"; } int main() { printf("%s", fun()); return 0; } 这段程序可以正常run,但是最好不要这么做. 因为  直观上你返回了一个局部的东西出去.  你可以再外面定义这个常量,然后返回. 另外,字符串常量不可修改,而char*意味着要修改,故此最好加上const. 以上就是小编为大家带来的浅谈char

  • mysql修改自增长主键int类型为char类型示例

    原来有一个表中的主键是int自增长类型, 因为业务变化需要把int改成char类型的主键.同时因为原来的表中已经存在了数据,不能删除表重建,只能修改表结构. 首先去掉自增长属性: alter table table_name  change indexid indexid int; 然后去掉主键: ALTER TABLE table_name   DROP   primary key; 修改表结构为char类型: alter table table_name change indexid ind

  • String类型传递是值传递,char[]类型传递是引用传递的实现

    如下所示: package com.lstc.test; public class TestDemo3 { String str = new String("hello"); char[] ch = { 'a', 'b' }; public static void main(String[] args) { TestDemo3 t = new TestDemo3(); t.change(t.str, t.ch);//String是封装类,是值传递,char数组是引用传递 System.

  • C# char类型字符转换大小写的实现代码

    C# char类型有自带的大小写转换方法:ToUpper和ToLowerchar str1 = 'a';char str2 = 'A';Char.ToUpper(str1); Char.ToLower(str2);

  • 解决mybatis使用char类型字段查询oracle数据库时结果返回null问题

    同事在学mybatis时,遇到了一个问题就是,使用char类型字段作为查询条件时一直都查不出数据,其他类型的则可以. 使用的数据库是oracle,查询条件字段类型是char(50),java代码对应的是String类型. 后来经过排查,是由于在oracle中,char类型字段,如果内容长度不够,会自动以空格方式补足长度.如字段 name char(5),若值为sgl,那么oracle会自动用空格补足长度,最终值为sgl. 一.解决方法: 方法1:先用trim()函数把值去掉两边空格再作为条件查询

  • Django ORM 自定义 char 类型字段解析

    用 CharField 定义的字段在数据库中存放为 verchar 类型 自定义 char 类型字段需要下面的代码: class FixedCharField(models.Field): """ 自定义的 char 类型的字段类 """ def __init__(self, max_length, *args, **kwargs): self.max_length = max_length super(FixedCharField, self)

  • Java数据类型之细讲char类型与编码关系

    一.开头 Java是一种强类型的语言,这意味着必须为每一个变量声明一种类型 Java中一共有8种基本数据类型(整形有4种,浮点型有2种,字符型1种,还有一种布尔类型) 由于Java程序必须保证在所有机器上都能得到相同的运行结果,所以各种数据类型的取值范围必须是固定的 二.整形 整形共有4种 byte:一个字节 short:2个字节 int:4个字节(刚好超过二十亿) long int:8个字节 这里要注意的一些地方是 长整形数值有一个后缀L或者l 十六进制数值有一个前缀0x或者0X 八进制有一个

  • MySQL中varchar和char类型的区别

    目录 前述 VARCHAR类型 VARCHAR适用情况 CHAR类型 测试 VARCHAR(5)与VARCHAR(200)的区别 总结 前述 VARCHAR和CHAR是两种最主要的字符串类型.不幸的是,很难精确地解释这些值是怎么存储在磁盘和内存中的,因为这跟存储引擎的具体实现有关.下面的描述假设使用的存储引擎是InnoDB和/或者MyISAM.如果使用的不是这两种存储引擎,请参考所使用的存储引擎的文档. 先看看VARCHAR和CHAR值通常在磁盘上怎么存储.请注意,存储引擎存储CHAR或者VAR

随机推荐