综述:在C语言中字符串或字符数组最后都会有一个额外的字符‘\0’来表示结束,而在java语言中没有结束符这一概念。具体见下面分析。

1. C 语言

  在C语言中字符串和字符数组基本上没有区别,都需要结束符;如:char s[4]={'a','b','c','d'};此字符数组的定义编译可以通过,但却没有关闭数组,若其后需要申请内存,那么以后的数据均会放入其中,尽管它的长度不够,但若为 char s[5]={'a','b','c','d'};则系统会自动在字符串的最后存放一个结束符,并关闭数组,说明字符数组是有结束符的;
    而字符串定义的长度必须大于字符序列的长度,如:char s1[4]={"abcd"};编译不能通过,而应写成char s1[5]={"abcd"};并且系统会自动在字符串的最后存放一个结束符,说明字符串有结束符;
在C语言中使用strlen()函数可以测数组的长度,strlen(()函数计算的时候不包含结束符'\0'。
char s[5]={'a','b','c','d'};
char s1[5]={"abcd"};
int a=strlen(s);
int b=strlen(s1);
结果是a,b均为4;
注:printf函数跟strlen一样,打印输出字符串/数组时都以'\0'作为结束符,即:打印输出到'\0'为止(不包括'\0')。

2.Java语言
  字符串和字符串数组都是不需要结束符的;
  如:char[] value={'j','a','v','a','语','言'};
        String s1=new String(value);
        String s2="java语言";  
   int a=value.length;
        int b=s1.length();
        int c=s2.length();

  运行得到的结果a,b,c都是6,说明字符串和字符串数组都不需要结束符。但注意此处value.length和s1.length(),在数组中有属性length可以记录数组对象的长度,而length()方法是File类中的一个实例方法,用于返回文件的大小,当然也可以返回字符串的大小。

3.java中无需结束符的原因

Java里面一切都是对象,是对象的话,字符串肯定就有长度,即然有长度,编译器就可以确定要输出的字符个数,当然也就没有必要去浪费那1字节的空间用以标明字符串的结束了。比如,数组对象里有一个属性length,就是数组的长度,String类里面有方法length()可以确定字符串的长度,因此对于输出函数来说,有直接的大小可以判断字符串的边界,编译器就没必要再去浪费一个空间标识字符串的结束。

4.java字符串末尾空字符的处理

java和c通信的时候,由于c中的char中有结束符的,所以当java收到C发来的字符串时,后面往往会有若干空字符,如果不做处理的话,java会对其一并输出,为了将空字符处理掉不输出,可以采用如下两种方法:

方法一:

调用java字符串的trim()方法,该方法会将字符串前后的空字符读去掉。

方法二:自己实现去掉尾部空字符的方法:

  1. /**
  2. * 截取掉C中之前的字符串。即只截取前的字符
  3. *
  4. * @param s:尾部带有空字符的java字符串
  5. * @return
  6. *
  7. */
  8. public static String deletTailChar0(String s){
  9. if(s == null){
  10. return null;
  11. }
  12. char[] chars = s.toCharArray();
  13. StringBuffer sb = new StringBuffer();
  14. for(char c : chars){
  15. Character ch = c;
  16. if(0 == ch.hashCode()){ //如果到了字符串结束,则跳出循环
  17. break;
  18. }else{
  19. sb.append(c);
  20. }
  21. }
  22. return sb.toString();
  23. }

附:

1.Java 数组初始化的两种方法:

静态初始化: 程序员在初始化数组时为数组每个元素赋值;

动态初始化: 数组初始化时,程序员只指定数组的长度,由系统为每个元素赋初值。

  1. public class ArrayInit {
  2. public static void main(String[] args) {
  3. //静态初始化数组:方法一
  4. String cats[] = new String[] {
  5. "Tom","Sam","Mimi"
  6. };
  7. //静态初始化数组:方法二
  8. String dogs[] = {"Jimmy","Gougou","Doggy"};
  9. //动态初始化数据
  10. String books[] = new String[2];
  11. books[0] = "Thinking in Java";
  12. books[1] = "Effective Java";
  13. System.out.println(cats.length);
  14. System.out.println(dogs.length);
  15. System.out.println(books.length);
  16. }
  17. }

注意,声明一个数组不需分配任何存储空间,它仅仅是代表你试图创建一个数组。跟C/C++声明一个数组的明显区别就是空间的大小没有被特别标识。因此,下面的声明将会引起一个编译期错误。

int num[5];
即:上面代码Demo中静态初始化中的方法二,如果改为String dogs[3] = {"Jimmy","Gougou","Doggy"};  则在编译时报错。
一个数组的大小将在数组使用new关键字真正创建时被给定,例如:
int num[];
num = new int[5];
 
 
迭代器(Iterator)是按照一定的顺序对一个或多个容器中的元素从前往后遍历的一种机制,比如for循环就是一种最简单的迭代器,对一个数组的遍历也是一种的迭代遍历的过程。GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。

迭代器其实就是维护一个当前的指针,这个指针可以指向当前的元素,可以返回当前所指向的元素,可以移到下一个元素的位置,通过这个指针可以遍历容器的所有元素。迭代器一般至少会有以下几种方法:

First(); //将指针移至第一个位置或获得第一个元素

GetCurrent(); //获得当前所指向的元素

MoveNext(); //移至下一个元素

2.1 C++中的迭代器:

  1. void TestIterator()
  2. {
  3. vector<int> vec;          // 定义一容器
  4. for(int i = 0; i < 5; i++)
  5. {
  6. vec.push_back(i*2);     //添加元素
  7. }
  8. //用迭代器访问容器中的每个元素
  9. cout << "iterator vector:" << endl;
  10. for(vector<int>::iterator itr = vec.begin(); itr != vec.end(); itr ++)
  11. {
  12. cout << *itr << "   ";  //itr是一个指针,指向当前的元素, 所以要解引用获得元素值
  13. }
  14. cout << endl;
  15. map<int, string> student; //创建一个map,对应学号-姓名的键值对
  16. //添加元素
  17. student.insert(pair<int, string>(1, "张三"));
  18. student.insert(pair<int, string>(3, "王五"));
  19. student.insert(pair<int, string>(2, "李四"));
  20. //遍历容器中的元素
  21. cout << "iterator map:" << endl;
  22. for (map<int, string>::iterator itr = student.begin(); itr != student.end(); itr ++)
  23. {
  24. cout << itr->first << "-->" << itr->second << endl;
  25. }
  26. }

c++中的容器(如vector、map、list、set等)一般会提供四个迭代器:

iterator:正向迭代,从前往后遍历,可修改元素的值

const_iterator:正向常量迭代,但不能修改元素的值,因为指向的是const的引用

reverse_iterator:反向迭代,从后往前遍历,可修改元素的值

const_reverse_iterator:反向常量迭代,但不能修改元素的值,因为指向的是const的引用

每一种迭代器都提供一对首尾位置的标志begin和end。

2.2 Java中的迭代器:

  1. public static void testIterator() {
  2. //创建一个列表
  3. List<Integer> list = new ArrayList<Integer>();
  4. list.add(4);    //添加元素
  5. list.add(3);
  6. list.add(7);
  7. //返回一个迭代器,并遍历列表中的元素
  8. Iterator<Integer> iterator = list.iterator();
  9. while (iterator.hasNext()) {
  10. Integer value = iterator.next();
  11. System.out.print(value + "    ");
  12. }
  13. System.out.println();
  14. //返回ListIterator迭代器并从后往前遍历列表的元素
  15. ListIterator<Integer> listIterator = list.listIterator(list.size());
  16. System.out.println("ListIterator:");
  17. while (listIterator.hasPrevious()) {
  18. Integer value = listIterator.previous();
  19. System.out.print(value + "    ");
  20. }
  21. System.out.println();
  22. }

Java中的List接口及其实现类可以通过iterator()返回Iterator,或通过listIterator()和listIterator(int index) 返回ListIterator。

Iterator和ListIterator都是迭代器,ListIterator继承自Iterator。Iterator只能对列表进行遍历,且只能从前往后遍历,ListIterator可以修改列表,且可以选择往前或往后遍历。

java中map容器的遍历(可分别利用keySet或entrySet):

  1. 方法一:keySet遍历key+value:
  2. Iterator<String> iter = map.keySet().iterator();
  3. while (iter.hasNext()) {
  4. key = iter.next();
  5. value = map.get(key);
  6. }
  7. 方法二:entrySet遍历key+value:
  8. Iterator<Entry<String, String>> iter = map.entrySet().iterator();
  9. Entry<String, String> entry;
  10. while (iter.hasNext()) {
  11. entry = iter.next();
  12. key = entry.getKey();
  13. value = entry.getValue();
  14. }

迭代器小结:C++中通过容器对象的begin或end方法来获取到迭代器,其迭代器的含义是一个指针,指向容器中的元素;而java中的迭代器是一个对象,通过容器的iterator()方法得到容器的迭代器,之后通过迭代器对象的方法hasNext()来获取到容器的指向。

3.C语言常用字符串函数

函数名: strrchr

功  能: 在串中查找指定字符的最后一个出现 
用  法: char *strrchr(char *str, char c);

举例:

  1. char fullname="./lib/lib1.so";
  2. char *ptr;
  3. ptr = strrchr(fullname,'/');
  4. printf("filename is %s",++ptr);
  5. //运行结果:filename is lib1.so

函数名: strchr 
功  能: 在串中查找指定字符的第一个出现 
用  法: char *strchr(char *str, char c);

举例:

  1. char fullname="./lib/lib1.so";
  2. char *ptr;
  3. ptr = strrchr(fullname,'.');
  4. printf("after strchr() is %s",++ptr);
  5. //运行结果:after strchr() is  /lib/lib1.so

函数名: strtok 
功  能: 在串中查找指定字符的第一个出现 
用  法: char *strtok(char *s, char *delim);

说明:

1.strtok函数的实质上的处理是,strtok在s中查找包含在delim中的字符并用NULL(’\0′)来替换,直到找遍整个字符串。这句话有两层含义:(1)每次调用strtok函数只能获得一个分割单位。(2)要获得所有的分割单元必须反复调用strtok函数。

2.strtok函数以后的调用时的需用NULL来替换s.

3.形参s(要分割的字符串)对应的变量应用char s[]=”….”形式,而不能用char *s=”….”形式。

举例:

  1. void  main()
  2. {
  3. char buf[]=”Golden Global View”;
  4. char* token = strtok( buf, ” “);
  5. while( token != NULL )
  6. {
  7. printf( ”%s “, token );
  8. token = strtok( NULL, ” “);
  9. }
  10. return 0;
  11. }
  12. /*其结果为:
  13. Golden
  14. Global
  15. View
  16. */

strcspn() 用来计算字符串 str 中连续有几个字符都不属于字符串 accept,其原型为:
    int strcspn(char *str, char *accept);
【参数说明】str、accept为要进行查找的两个字符串。
strcspn() 从字符串 str 的开头计算连续的字符,而这些字符都完全不在字符串 accept 中。简单地说,若 strcspn() 返回的数值为 n,则代表字符串 str 开头连续有 n 个字符都不含字符串 accept 中的字符。
【返回值】返回字符串 str 开头连续不含字符串 accept 内的字符数目。
注意:如果 str 中的字符都没有在 accept 中出现,那么将返回 atr 的长度;检索的字符是区分大小写的。
提示:函数 strspn() 的含义与 strcspn() 相反,可以对比学习。
【示例】返回s1、s2包含的相同字符串的位置。

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. #include<string.h>
  4. int main()
  5. {
  6. char* s1 = "http://c.biancheng.net/cpp/u/biaozhunku/";
  7. char* s2 = "c is good";
  8. int n = strcspn(s1,s2);
  9. printf("The first char both in s1 and s2 is :%c\n",s1[n]);
  10. printf("The position in s1 is: %d\n",n);
  11. system("pause");
  12. return 0;
  13. }运行结果:
  14. The first char both in s1 and s2 is :c
  15. The position in s1 is: 7

再看一个例子,判断两个字符串的字符是否有重复的。

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. #include<string.h>
  4. int main()
  5. {
  6. char* s1 = "http://c.biancheng.net/cpp/xitong/";
  7. char* s2 = "z -+*";
  8. if(strlen(s1) == strcspn(s1,s2)){
  9. printf("s1 is diffrent from s2!\n");
  10. }else{
  11. printf("There is at least one same character in s1 and s2!\n");
  12. }
  13. system("pause");
  14. return 0;
  15. }
  16. 运行结果:
  17. s1 is diffrent from s2!

strpbrk()函数检索两个字符串中首个相同字符的位置,其原型为:
    char *strpbrk( char *s1, char *s2);
【参数说明】s1、s2要检索的两个字符串。
strpbrk()从s1的第一个字符向后检索,直到'\0',如果当前字符存在于s2中,那么返回当前字符的地址,并停止检索。
【返回值】如果s1、s2含有相同的字符,那么返回指向s1中第一个相同字符的指针,否则返回NULL。
注意:strpbrk()不会对结束符'\0'进行检索。
【函数示例】输出第一个相同字符之后的内容。

    1. #include<stdio.h>
    2. #include<string.h>
    3. int main(void){
    4. char* s1 = "http://see.xidian.edu.cn/cpp/u/xitong/";
    5. char* s2 = "see";
    6. char* p = strpbrk(s1,s2);
    7. if(p){
    8. printf("The result is: %s\n",p);
    9. }else{
    10. printf("Sorry!\n");
    11. }
    12. return 0;
    13. }
    14. 输出结果:
    15. The result is: see.xidian.edu.cn/cpp/u/xitong/

java与C语言在字符串结束符上的区别的更多相关文章

  1. C++入门经典-例6.3-字符串之未使用字符串结束符“\0”和使用字符串结束符“\0”的区别

    1:为字符串数组赋值的方式有两种,即数组元素逐一赋值和使用聚合方式赋值. 为数组元素逐一赋值.例如: pWord[0]='H'; 使用聚合方式赋值如: char pWord[]={'H','E','L ...

  2. C语言中字符串结束符'\0'

    转自:http://www.cnblogs.com/kaituorensheng/archive/2013/12/09/3464462.html 本质 '\0'就是8位的00000000,因为字符类型 ...

  3. C++与C语言在结构体上的区别

    用Nios 实现逻辑上很清楚,只是C++用switch语句后,写的很麻烦,主要是Switch语句很长吧. 另外要记录下:struct在C++中,在a文件中定义在b文件中定义变量是可以的,但在C语言中, ...

  4. JAVA基础2---深度解析A++和++A的区别

    我们都知道JAVA中A++和++A在用法上的区别,都是自增,A++是先取值再自增,++A是先自增再取值,那么为什么会是这样的呢? 1.关于A++和++A的区别,下面的来看个例子: public cla ...

  5. 【转载】Java与C++语言在作用域上的差异浅析

    http://developer.51cto.com/art/200906/126199.htm 差异一:变量作用域的不同 如下面这段程序代码是符合C++语言的语法要求的.其可以在C语言下正常运行.但 ...

  6. atitit.java解析sql语言解析器解释器的实现

    atitit.java解析sql语言解析器解释器的实现 1. 解析sql的本质:实现一个4gl dsl编程语言的编译器 1 2. 解析sql的主要的流程,词法分析,而后进行语法分析,语义分析,构建sq ...

  7. C语言里字符串的解析

      根据给定的字符串,按照一定规则解析字符串,卡住好几次,这次做个笔记,以供参考 函数名称:   strtok 函数原型:   char *strtok(char *s1, const char *s ...

  8. JAVA和C语言的区别

    java语言和c语言的区别:                                      1 un 公司推出的Java 是面向对象程序设计语言,其适用于Internet 应用的开发,称为 ...

  9. 分享:写了一个 java 调用 C语言 开发的动态库的范例

    分享:写了一个 java 调用 C语言 开发的动态库的范例 cfunction.h   代码#pragma once#ifdef __cplusplusextern "C" {#e ...

随机推荐

  1. 很棒的bootstrap学习网站

    http://www.w3cschool.cc/bootstrap/bootstrap-tutorial.html

  2. 6w4:第六周程序填空题1

    描述 下面程序的输出结果是: A::Fun C::Do 请填空: #include <iostream> using namespace std; class A { private: i ...

  3. dubbo源码分析--dubbo spi解析

    1. 什么叫SPI? 简单总结就是一种使用类名字符串来动态实例化java类的方式,也就是反射. 2. java SPI与Dubbo SPI有什么区别 (此图来自网上,我没有刻意去截图) 然后在这个文件 ...

  4. 解决tomcat启动 startup.bat的时候一闪而过(就是java环境变量的配置)

    系统变量配置:(解决tomcat启动 startup.bat的时候一闪而过) JAVA_HOME C:\Program Files (x86)\Java\jdk1.7.0_25 =========== ...

  5. php 写入csv时 双引号,逗号及特殊字符

    1.双引号 <?php function new_csv($string) { $filename = date('Ymd').'.csv'; //设置文件名 header("Cont ...

  6. R语言常用包汇总

    转载于:https://blog.csdn.net/sinat_26917383/article/details/50651464?locationNum=2&fps=1 一.一些函数包大汇总 ...

  7. enumerate函数

    enumerate(list):返回元组,带有索引值,常用用法: for i in enemerate(list): print(i)

  8. LeetCode记录之26——Remove Duplicates from Sorted Array

    国外的表达思维跟咱们有很大差别,做这道题的时候很明显.简单说本题就是让你把有序数组中的重复项给换成正常有序的.比如 1 2 2 3换成 1 2 3 3,根本不需要考虑重复的怎么办,怎么删除重复项等等. ...

  9. let 和 var 的区别笔记

    参考文章:阮一峰   ECMAScript 6 入门 ES6中新增加了 let  声明,它跟 var  的区别如下: 1.作用域不同,let  只在代码块中有效 { var a = '123'; le ...

  10. 洛谷 P2147 [SDOI2008]洞穴勘测 (线段树分治)

    题目链接 题解 早就想写线段树分治的题了. 对于每条边,它存在于一段时间 我们按时间来搞 我们可把一条边看做一条线段 我们可以模拟线段树操作,不断分治下去 把覆盖\(l-r\)这段时间的线段筛选出来, ...