V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xrr2016
V2EX  ›  程序员

既然字符串是一个 char 数组, 为什么语言还要定义 String 的方法,而不是是直接用 Array 的方法?

  •  
  •   xrr2016 ·
    xrr2016 · 2017-07-15 21:21:25 +08:00 · 4838 次点击
    这是一个创建于 2448 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题, 定义 String 的方法是否多此一举,增加了程序员的负担。

    44 条回复    2017-07-16 17:25:06 +08:00
    choury
        1
    choury  
       2017-07-15 21:26:29 +08:00 via Android
    你说的是 C 语言?然后再定义一堆,strlen strste strcmp strcap 等等函数?
    aprikyblue
        2
    aprikyblue  
       2017-07-15 21:29:25 +08:00
    可 C 语言就是拿 char[]做字符串,也没 String 啊……
    xrr2016
        3
    xrr2016  
    OP
       2017-07-15 21:35:06 +08:00
    @choury 在 javascript 里面也是, 既然 Array 有了 slice, splice 等方法,String 还要弄 substr, substring, 让我使用的时候还要纠结一下。
    Trim21
        4
    Trim21  
       2017-07-15 21:39:28 +08:00
    在一个 array 中寻找另一个 array....
    linpf
        5
    linpf  
       2017-07-15 21:47:27 +08:00
    可以把 string 理解为 array 的派生。虽然是个 array,但他是一个特殊的 array,有字符串操作方面的特性以及限制。
    wwjvtwoex
        6
    wwjvtwoex  
       2017-07-15 21:50:15 +08:00
    正则表达式
    geelaw
        7
    geelaw  
       2017-07-15 21:51:43 +08:00   ❤️ 4
    因为并不是所有的 char[] 都是有效的 string。

    譬如有的语言 / API 不允许 embedded null character。

    再比如多个 char 可能表示的是一个字符( UTF16 的 surrogate pair、UTF8 的 continuation ),数组长度并不总是和字符串长度之间有简单的等式关系。
    mooncakejs
        8
    mooncakejs  
       2017-07-15 21:57:13 +08:00
    @xrr2016 char array 没有编码
    Perry
        9
    Perry  
       2017-07-15 22:00:19 +08:00 via iPhone
    你确定是增加了负担?你想要知道一个 string 的长度没有 strlen 还不是要写一个 for loop ?
    0asis
        10
    0asis  
       2017-07-15 22:02:05 +08:00 via iPhone
    一言以蔽之,抽象。
    就好比栈和队列实质上都可以用顺序的 array 存储,为什么还要定义这两个数据结构
    xrr2016
        11
    xrr2016  
    OP
       2017-07-15 22:02:18 +08:00
    @Perry 有 length 属性啊
    Perry
        12
    Perry  
       2017-07-15 22:02:21 +08:00 via iPhone
    slice 的方法要是直接用在 String 只能得到一个 char[] 而不是 String
    firemiles
        13
    firemiles  
       2017-07-15 22:03:40 +08:00
    确认楼主没写过多少代码
    xieranmaya
        14
    xieranmaya  
       2017-07-15 22:21:26 +08:00
    为了抽象
    ETiV
        15
    ETiV  
       2017-07-15 22:25:43 +08:00 via iPhone
    既然 123 都是一二三
    <del>为什么四不写作 亖</del>

    一百不写作“一百个横”
    changwei
        16
    changwei  
       2017-07-15 22:26:56 +08:00 via Android
    因为要考虑到多字节字符的使用,所以做了一下抽象会更加方便。

    比如说汉语,日语,韩语等字符,在不同的编码规则(比如说 unicode )以及编码实现(比如说 utf-8 )下,这些字符串的一个字符其实底层是多个 char 组成的。楼主试试看 php 里面的 strlen 和 mb_strlen 的区别就知道了。php 也是 c 写的,也可以看看 php 里面相关的源码来理解。
    misaka19000
        17
    misaka19000  
       2017-07-15 22:29:58 +08:00 via Android
    哈哈 程序员的负担可比程序的负担重要多了,机器性能那都不是事
    xrr2016
        18
    xrr2016  
    OP
       2017-07-15 22:40:20 +08:00
    @changwei 所以主要是因为有多种编码规则, 那么要是以后编码规则只有 Unicode 了, 就可以去掉 String 了吧.
    changwei
        19
    changwei  
       2017-07-15 22:50:01 +08:00 via Android
    @xrr2016 嗯嗯,你就把 string 当做语法糖就好了。
    shihira
        20
    shihira  
       2017-07-15 22:51:13 +08:00   ❤️ 4
    在多数的解释型语言里,抽象的成本比较高。在 js 当中,Array 是动态类型的 Array,并没有什么 Array of Char,其中每个元素都可以有不同的类型,于是访问每一个元素,解释器底层都要对这个元素识别类型、拆箱,才能开始计算,计算量 /复杂度可谓翻了个倍。但是明确钦定是 String 的时候,数据在内存里就是连续的、裸的字符序列,直接可以开始计算了。

    所以,在动态类型语言或者多数的解释型语言里,该用 String 的时候不要用 Array,这很重要。
    changwei
        21
    changwei  
       2017-07-15 22:51:28 +08:00 via Android
    @xrr2016 也不是,utf8 这种实现一般情况下是三个字节代表一个汉字,如果用 array,做 substring 还得各种数学上的 x3,+1,-1 的计算,还是麻烦。
    hand515
        22
    hand515  
       2017-07-15 22:51:31 +08:00
    这个问题我联想到,既然有 byte 数组,为啥还要定义 int,long
    shihira
        23
    shihira  
       2017-07-15 22:54:41 +08:00   ❤️ 3
    同样,多数动态语言中 string 表现为 immutable,而 array 表现为 mutable,也是这个原因。
    xrr2016
        24
    xrr2016  
    OP
       2017-07-15 22:58:15 +08:00
    @shihira 嗯, 多谢解释
    beginor
        25
    beginor  
       2017-07-15 23:03:10 +08:00 via Android
    突然想起一个段子,计算机最终执行的不都是 0 1 么, 为啥还要整各种开发语言?
    sagaxu
        26
    sagaxu  
       2017-07-15 23:10:50 +08:00
    @xrr2016 string 有一些特有的算法,比如忽略大小写的匹配,array 如何做到?
    AckywOw
        27
    AckywOw  
       2017-07-15 23:21:49 +08:00
    因为人懒
    nbndco
        28
    nbndco  
       2017-07-15 23:25:54 +08:00 via iPhone   ❤️ 1
    String 当前的实现几乎都复杂到一定境界了……怎么可能只是几个字符串匹配函数的目的而已……
    gyorou
        29
    gyorou  
       2017-07-15 23:27:15 +08:00
    一般来说,string 可以看成是以某种编码下的 code point 的容器。这个容器可以是 list 或者是 array。
    所以感觉上来说,string 的抽象层次更高。
    这种抽象,无论是用面向对象概念的类来实现,还是通过 protocol 统一接口来实现,
    必然会有一系列名称和操作类似的方法或者函数。
    wohenyingyu02
        30
    wohenyingyu02  
       2017-07-15 23:48:51 +08:00
    为什么是负担?你不想用完全可以不用
    zhicheng
        31
    zhicheng  
       2017-07-16 00:39:08 +08:00
    C 语言教材和 C 语言标准库最大的错误就是让人觉得 C 有 “字符串” 这个类型,无论 char * 还是 char [] 都不是字符串,它们只是 “字节数组” ,C 标准甚至都没有规定 char 是 signed 还是 unsigned。同时 C 语言也没有规定一个字节是多少 bit。C 语言诞生的时候字符串没有现在这么重要,所以只是简单的 “约定” 了一下用 '\0' 结尾的字节数组作为字符串,并实现了相关函数。现在应该尽量避免用 '\0' 结尾的字节数组来模拟字符串。
    secondwtq
        32
    secondwtq  
       2017-07-16 02:03:07 +08:00
    Haskell 就是和 C 一样直接拿 [Char] 当 String,不过用起来比 C 的要舒服得多
    虽然貌似实际多数人都在用 text ...
    wwqgtxx
        33
    wwqgtxx  
       2017-07-16 02:20:44 +08:00 via iPhone
    当你学 c++11 14 17 的时候也会觉得很多东西都已经存在了,为什么 stl 还要实现一遍,最后当你能熟练运用这些库的时候你就会明白他存在的意义了
    congeec
        34
    congeec  
       2017-07-16 02:24:44 +08:00
    @wwqgtxx std::array 用起来炒鸡爽
    xupefei
        35
    xupefei  
       2017-07-16 05:26:17 +08:00
    有些字符串并不是简单的数组,例如 Windows API 常用的 UNICODE_STRING 结构体。
    msg7086
        36
    msg7086  
       2017-07-16 05:39:40 +08:00
    其实就是,既然代码都是指令,为啥还要定义各种高级语言而不直接使用机器指令呢。
    增加程序员的负担?你说反了吧。
    yulon
        37
    yulon  
       2017-07-16 06:00:56 +08:00
    C++ 的 string 都被喷成啥样了,这还有开倒车的。。。
    gnaggnoyil
        38
    gnaggnoyil  
       2017-07-16 06:18:35 +08:00
    LZ 根本的问题还是没有区分开字符串和字符存储区的概念.在这一点上 C 的简单粗暴的抽象方式难辞其咎.

    不过同样让 C 难辞其咎的还有,部分评论中的字符和编码字符的字节区分不开来的趋势……
    Quaintjade
        39
    Quaintjade  
       2017-07-16 09:23:47 +08:00 via Android
    Javascript 的 char[]形式是从 ES5 才开始规范的,所以像 IE7 之类远古浏览器不支持。
    shuson
        40
    shuson  
       2017-07-16 09:56:37 +08:00
    用 c++做解释

    String 里包装了一个 array,帮你做 malloc 和 free,用\0 管理长度,并提供一系列方便的方法。
    cwek
        41
    cwek  
       2017-07-16 10:52:30 +08:00
    C 的话忘记加\0 就字符串未结束了
    封装就是减轻开发负担,让程序帮你管理部分数据,封装的话可以用 length 来记录字符串长度,不用你管理。
    holy_sin
        42
    holy_sin  
       2017-07-16 11:38:25 +08:00
    为了好用吧,所有的对象都是 bit,为什么还要定义数据结构呢,是这个道理吧
    hyyou2010
        43
    hyyou2010  
       2017-07-16 17:02:42 +08:00
    字符串是人类语言层面的一句话,但这句话在不同计算机不同语言编码下会存储为各种不同的二进制 char 数组。我们往往需要在人类语言层面做操作,所以需要字符串这个比较高的表现层。
    yidinghe
        44
    yidinghe  
       2017-07-16 17:25:06 +08:00 via Android
    封装起来好。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1531 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 17:07 · PVG 01:07 · LAX 10:07 · JFK 13:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.