A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

1、字符串:位于双引号中的字符序列,以”\0”结束,所占字节比实际多一个。

2、字符常量可以赋给字符变量,字符串常量不可以赋给字符串变量。C语言中用字符数组来存放字符串。

3、字符数组:memset(a,’\0’,10);用来给数组清0的。需要加头文件#include<string.h>。

注意:定义数组时,应确保数组长度比字符串长度至少多1,未被使用的元素自动初始化为0。

4、’\0’代表ASCII码为0的字符(NUL)。为“空操作符”,用它作为字符串结束标志不会产生附加的操
作或增加有效字符,只起一个供辨别的标志。

5、字符数组的输入输出的两种方法:
(1)逐个字符输入输出(%c);(输出字符不包含‘\0’)

(2)整个字符串一次输入输出(%s)。(输出的是字符数组名)

6、scanf()格式化输入:接收字符串,不接收空格。输入字符串时,数组名前不加&。

7、gets()可以接收空格,以回车结束输入;getchar()输入回显;getch()不回显,而且可以接收‘\r’
,需要#include <conio.h>

8、puts()输出字符串函数程序开头用#include <string.h>;输出字符函数putchar()。

9、字符数组的一些方法

(1)统计字符串长度:strlen();(遇到‘\0’结束)。

(2)内存赋值函数:memset(字符数组名,要替换的内容,要替换的个数),根据要替换的个数,用膏药替换的内容,替换字符串数组的内容(清0)。

(3)字符串拷贝:strcpy(字符数组1,字符数组2);strcpy(字符数组名,字符常量)。

(4)字符串拷贝:strncpy(目标数组,原数组,个数);将指定个数的字符串拷贝到指定的数组中。注
意:strncpy不检查目标字符串的大小,当目标字符串内存不足,会导致崩溃。

(5)字符串比较:strcmp(字符串1,字符串2)。(规则:讲两个字符串自左至右逐个字符比较,直到遇到
相同的字符或’\0’结束)。

比较的结果由函数值带回:
1>如果字符串1=字符串2,则函数值为0;
2>如果字符串1>字符串2,则函数值为一个正整数
3>如果字符串1<字符串2,则函数值为一个负整数

(6)字符串连接函数:strcat(字符数组1,字符数组2)。

(7)字符串转小写:strlwr(字符串)。

(8)字符串转大写:strupr(字符串)。

10、C语言函数:C语言是通过函数来实现模块化程序设计的。每个模块都有特定的功能,称为子程序。函
数式C语言程序的基本单位。

11、主函数可以调用其他函数,其他函数也可以互相调用,其它函数不可以调用主函数。

12、程序使用函数的优点:
1)使用函数可以控制任务的规模
2)使用函数可以控制变量的作用范围
3)使用函数,程序的开发可以由多人分工协作
4)使用函数,可以重新利用已有的、调试好的、成熟的程序模块
5)函数模块相对独立,功能单一,可混合编写也可独立编写调试

12、函数的定义形式

(1)无参函数 :函数类型 函数名(){可执行语句部分}

(2)有参函数 : 函数类型 函数名(形参列表){可执行语句部分}

(3)空函数 :函数类型 函数名(){   }

13、命名规范
(1)首字母必须大写.
(2)函数名用大小写字母组合
(3)最好用下划线进行间隔

14、自定义头文件(*.h)。

头文件中一般放一些重复使用的代码,例如函数声明,变量声明,常数定义,宏的定义等等。

15、函数声明:又称为函数原型。

格式为:函数类型 函数名(参数类型1,参数类型2,...,参数类型n)。

返回值:return语句,函数中能出现多个return语句,但是每次只能有一个return执行,只有一个返回
值。
16、变量的两种存储方式:静态存储方式(系统固定分配存储空间)和动态存储方式(根据需要进行动态
分配存储空间)。

17、内存区域分配:

代码段:可执行代码、字符串常量
数据段:已初始化全局变量、已初始化全局静态变量、局部静态变量、常量数据
BSS:未初始化全局变量,为初始化全局静态变量
栈:局部变量、函数参数
堆:动态内存分配

18、栈和堆的区别:
(1)申请空间方式不同:栈是系统自动分配;堆是程序员自己申请的。
(2)堆是手动释放内存空间,栈是自动释放内存空间。

19、函数之外的是全局变量,函数之内的变量叫做局部变量。

20、静态变量随函数的定义而定义,如果已经存在就延用,但并不随函数的结束而消亡。若未赋以初值
,则由系统自动赋以0值。静态全局变量:静态存储方式。

21、函数嵌套的调用:即调用一个函数的过程中,又可以调用另一个函数。

22、函数递归调用:在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调
用。
每个子问题必须比原来问题的规模更小,如果能够迅速减小更好必须有一个明确的结束递归的条件。

23、const修饰函数参数:表示函数内部不能对函数的参数进行修改。

24、数组名作为函数参数:向形参传递的是数组首元素的地址。

用数组元素做实参时向形参变量传递的是数组元素的值。

评分

参与人数 1技术分 +1 收起 理由
星河鹭起 + 1

查看全部评分

1 个回复

倒序浏览

C语言字符串数组注意点

字符串并不是C语言中默认存在的类型,但是由于字符串的实用性,在谭浩强C语言中有对字符串的一些描述,但是不是特别的详细。有时候写代码时都不会注意到一些小细节,本文就结合实验分析一下字符串与字符数组之间的差别。
    字符串与字符数组的区别在过去我一直是处于一知半解的状态,字符串是通常被认为是常量,是保存在一段固定的内存中的,这段内存是以'\0'为结束符,这段内存通常只能通过一个指针来找到。字符数组其实和其他数组没什么区别,只是保存的数据类型是字符类型(char),它没有强制要求最后的元素是否是'\0'。字符数组的数组名是指向第0个字符的指针,而不是指向这个字符串的。这与我前期博客中对数组的分析结论是相同的,数组名并不像指针存在一个地址来保存指针名,数组名可以看做是汇编程序中的一个标号,并没有专门的地址来保存数组名。
    但是字符串和字符数组又有很多相似的地方,特别是当我们结合指针操作字符数组时候,就会导致错误的产生,我觉得只有搞清楚一些概念就能较好的避免这种错误的产生。这个概念就是指针就是指针,数组就是数组,两个搞混只是因为某些巧合使我们误以为指针和数组是等值的。两者实质上是不相同的。
    字符数组和字符串的定义如下:
点击(此处)折叠或打开
1.                             //字符串
2.                             char *str = "string is a constant";
3.                             //字符数组
4.                             char strarray[] = {'s','t','r','i','n','g',' ','i','s',' ','a',' ','c','o','n','s','t','a','n','t','\0'};
5.                             //或者
6.                             char strarray[] = "string is a constant";
7.                             char strarray[] = {"string is a constant"};
    其中从上面的定义可以知道字符串实质上一块内存,其中保存的值是常量,常量其实就是不能采用程序对内存中的值进行修改,当然只是程序不能,我认为就像嵌入式C语言中的const类型一样,虽然我们通常认为这个变量是常量,但实质上是只读性变量,只是不能通过程序修改,还可以通过其他的方式修改。这时候str指向的内存空间中保存的数据是不能被程序修改的,也只能通过str指针对这段内存进行访问。
如果字符数组定义成单个的字符,我们也许还能较好的分别,但如果是如第二种定义、第三种形式定义,我们可能就会产生很大的不理解,这与字符串的类型基本上没有什么差别,只是多了一个数组符号[ ],但是这个数组符号就意味着数据类型的改变,我们可以知道数组中的值是可以改变的,不是常量,说明strarray是一个数组变量,而str却是一个字符串常量指针。Strarray是一个标号,存储器中并没有专门分配内存空间存储strarray的值。但是指针和数组名很多时候的一些相似性使得我们在处理的时候很难去判断,比如下面这段代码:
点击(此处)折叠或打开
char * str = "Constant String";
char strarray[] = "Constant String";

int str_len,size_str,array_len,size_array;

str_len = strlen(str);
array_len = strlen(strarray);
size_str = sizeof(str);
size_array = sizeof(strarray);
size_str = sizeof(*str);
    如果知道其中的一些数组与指针的一些区别可以较好的得到这些值,首先strlen(str)是指求解字符串的长度,但是不包含'\0',因此str_len就是字符串的长度,也就是str_len = 15,array_len也是求解字符串长度的值,我们前面已经指出数组和字符串存在差别,但为什么还可以这样做呢。我们暂且认为包含'\0'的字符数组可以看做是字符串或者伪字符串,两者非常的相似,都是存在一段内存,保存一段数据,格式也非常的相似,所以strlen认为两者是相同的,但实质上还是存在差别的,但是采用strlen求解字符串长度时,array_len和str_len 是相同的。
    size_str 和size_array这两个变量的值是我写这篇文章的初衷,因为我之前根本没有起分析其中的一些差别,理所当然的认为两者是相同的,但细细比较发现两者确实存在问题。size_str = sizeof(str)的值是多少?sizeof是指对变量或者类型求解存储空间,是C语言中不被重视的关键字,被大多数人认为是一个函数,实质上是一个关键字。这样我们就能比较快速的确定后面三个变量的值啦,size_str = sizeof(str)是指对str的存储器长度进行计算,str是一个字符型指针,我们知道,指针类型的变量实质上就是一个地址,在32机中,地址通常需要4个字节的内存空间来存储,因此,size_str = 4;知道了sizeof的意义,size_array就比较简单了,strarray是一个数组变量,是一段内存空间的标示,sizeof(strarray)是指上就是求解数组的内存大小,这时候的内存大小包含'\0',因此size_array的值应该是15+1=16。而接下来的size_str = sizeof(*str)就更加简单了,因为我们知道对于字符串指针而言,指向的只是字符串的第0个元素,而不是整个字符串,这时候又会和数组的数组名有一定的交叉,数组的数组名我们通常被认为是一个常量指针(左值右值的差别),也就是指向的起始地址是不变的,但是通常被认为是指向数组首个元素的常指针,不能进行++,--操作。接着说明sizeof(*str),*str是指指向字符串的第0个元素的指针的值,也就是说*str是指上就是字符串的第0个元素,也就是一个字符类型,字符类型的大小也就是1字节了,因此这时候的size_str = 1。
    上面的分析说明了在字符串和数组的相关操作中使用strlen的安全性总是比sizeof好,特别是不清楚sizeof的一些意义的情况下。
    通过上面的分析我们应该字符串和字符数组还是存在很多差别的,但是只是理论上的分析,接下来采用程序进行测试。这个程序主要检测字符串是否为常量,而字符数组是可以修改的。
点击(此处)折叠或打开
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define BUFS 20

int main()
{
        char s[] = {"This is just a test!!"};
        char d[] = {"Hello String strncpy!!"};

        char *str = "String constant!";
        char *str1 = "Testing!!";

        /*不能采用定义指针的情况下就进行字符串的操作,
         *需要分配一定长度的空间,
         *因为没有内存空间不能操作
         */
        char *p = malloc(BUFS * sizeof(char));

        /*修改字符数组*/
        strncpy(p,s,strlen(s));
        printf("p = %s\n",p);
        printf("d = %s\n",d);
        strncpy(d,s,strlen(s));
        printf("d = %s\n",d);
        strncpy(d,s,strlen(d));
        printf("d = %s\n",d);

        /*修改字符串*/
        printf("Test the string constant\n");
        printf("Constant String str = %s\n",str);

        strncpy(str,d,strlen(str));
        printf("p = %s\n",p);
        printf("d = %s\n",d);
        strncpy(d,s,strlen(s));
        printf("d = %s\n",d);
        strncpy(d,s,strlen(d));
        printf("d = %s\n",d);

        /*修改字符串*/
        printf("Test the string constant\n");
        printf("Constant String str = %s\n",str);

        strncpy(str,d,strlen(str));
        printf("Constant String str = %s\n",str);

        return 0;
}
编译以后出现的效果如下:
点击(此处)折叠或打开
[gong@Gong-Computer c_languange]$ gcc -g strncpytest.c -o strncpytest
[gong@Gong-Computer c_languange]$ ./strncpytest
p = This is just a
d = Hello String
d = This is just a
d = This is just a
Test the string constant
Constant String str = String
Segmentation fault (core dumped)
结合上面的代码可以知道关于字符数组的操作都顺利的完成了,但是字符串的修改却没有正常的完成,出现了
异常(Segmentation fault (core dumped)),实质上就是因为字符串是不能修改的,导致了问题的抛出。据说在ANSI C中规定对字符串的操作会导致不确定的结果,这也说明了字符串是不能进行修改的。

通过上面的分析,数组和指针还是存在非常大的差别的,在字符串的操作过程中这种差别更加的明显,因此在实际写代码的过程中要时时注意这些小的差别,只有铭记一些概念才能真正的写好代码。

总结:
字符串是一个常量,不应该被修改,修改会出现错误,字符数组可以进行修改,因为数组中的值并不是不变的。在关于字符串的操作中,最好是采用首先将字符串赋值给字符数组,然后通过指针的方式访问进行修改等相关操作,而不能直接对字符串指针进行修改操作。
数组是一段内存的标示,指针只是保存了一个地址值。

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马