getcharputchar缓冲区

有下面的语句段:

while ((s = getchar()) != '\n'){
putchar(s);
putchar("\n");
}

这个while循环是怎么工作的呢?

首先getchar在数据缓冲区里读数据进来,这个读取数据是一个个读的,循环依次判断读进来的字符是不是为换行符,是的话就跳出循环,不是就打印出该字符。其实在getchar读取字符之前,通过键盘输入的字符已经通过stdin流全部存入了缓冲区中,getchar只在用户输入了换行符时才会去读取缓冲区里的数据。

C字符串数组与指针

在C中字符串实质上是最后一个元素为空字符的char数组,而我们知道数组与指针是有关联的。声明一个字符串有以下两种方式:

char *string1 = "foo";
//通过指针声明,string1其实是指向"foo"这个字符串第一个char字符'f'的地址
char string2[4] = "foo";
//通过char数组生明字符串,string2是一个数组

这两种声明方式有一点不同,就是数组名string2是个常量,而指针名string1是一个量。数组形式的string[4]是计算机内存中分配的用于存储四个字符'f','o','o','o','\0'string2既是数组名,也是首个字符string[0]的地址,string2的值不能更改,可以通过string2+1来访问第二个字符'o',但不能这样用:++string2,C中规定++自增符号只能用于变量,string2这里显然是个常量,它的值是该数组首个元素的地址。对于string1形式,C Primer Plus中这样说:

指针形式(也就是我们这里的string1)会在静态存储区为字符串预留4个元素的空间(最后一个存储空间用来放'\0')。一旦程序开始执行,还要为指针变量string1另外预留一个存储位置,以在该指针变量中存储字符串地址。这个变量初始时指向字符串的第一个字符,但是它的值是可以改变的。因此,可以对它使用增量运算符(例++string1将指向第二个字符'o')。总之数组形式的字符串初始化是从静态存储区把一个字符串赋值给数组,而指针初始化只是复制字符串的地址。

这里我们就很清楚了两种形式的不同。一般推荐用数组来定义字符串,因为用指针形式定义字符串时,若是修改了指针指向的字符串某个字符可能会导致所有使用该地址字符的值发生变化,这和编译器的实现方式有关。

在访问字符串,例如puts时,不管是数组形式还是指针形式,会一直打印字符知道碰到空字符才结束。

字符串数组

考虑到一下形式定义:

char (*list)[2] ={"a","b"};//1
const char *multiple_strings[3] = {//2
"I love you",
"You are beautiful",
"You makes me happy"};

你会发现1处会报警告:Incompatible pointer types initializing 'char (*)[2]' with an expression of type 'char [2]'; take the address with &因为此处声明的list是一个指向由两个字符构成的元素的元素的地址,而"a"是一个字符串,并不是个字符,因此我们得把"a"改成'a'。其实这样也是错误的,我们声明list是个指针,指向一个二维数组的第一个元素,那么就不要用一整个二维数组类型去初始化它,最好这样:

char (*list)[2] = {'a','b'};
char test[2][2] = {{'a','b'},{'b','c'}};
list = test;

这样不会有任何警告。

再看注释2处什么意思呢?这其实定义了一个字符串数组,但是这是一个一位数组,而不是二维数组(我们知道二维数组指针形式声明并不是这样的),数组里面的每个元素都是一个char类型元素的地址,每个元素都是对应字符串第一个字符的地址,也就有下列关系成立:

*multiple_strings[0] == 'I'; *multiple_strings == 'Y'。对指针进行数组式操作在这里也是成立的:

multiple_strings[1][2]就对应的就是第二个字符串You中的'u'

关于这部分的详细知识可以参见C Primer Plus的第十一章关于字符串数组的部分。

总结:

声明一个数组将为数据分配存储空间;而生明一个指针只为一个地址分配存储空间。

getchar与putchar缓冲区以及字符串数组、指针的更多相关文章

  1. 如何把字符串数组从 Swift 传递给 C

    作者:Natasha The Robot,原文链接,原文日期:2016-10-27译者:BigbigChai:校对:walkingway:定稿:CMB Swift 允许我们将原生的字符串直接传递给一个 ...

  2. C++ 字符串指针与字符串数组

    在做面试100题中第21题时,发现char *astr="abcdefghijk\0";和char astr[]={"abcdefghijk"};有点区别,以前 ...

  3. C语言之数组,字符串,指针

    一. 数组的定义 1.  数组初始化 初始化方式 int a[3] = {10, 9, 6}; int a[3] = {10,9}; int a[] = {11, 7, 6}; int a[4] = ...

  4. 「C」 数组、字符串、指针

    一.数组 (一)数组 概念:用来存储一组数据的构造数据类型 特点:只能存放一种类型的数据,如全部是int型或者全部是char型,数组里的数据成为元素. (二)数组的定义 格式: 类型 数组名[元素个数 ...

  5. 数组/指针/const/字符串常量的使用传值问题

    #include<stdio.h> #include<string.h> int main() { ] = "abcd"; //常指针a指向字符串常量&qu ...

  6. C语言 字符串指针和字符串数组使用区别

    字符串指针和字符串数组使用区别 1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 ...

  7. 数组字符串与指针字符串的区别 char s[]="***" 和char *s="***"的区别

    char s[] = "wangshihui"; char *s = "wangshihui"; 皆宣告了s字符串,在C-style string的函数皆可使用 ...

  8. getchar()、putchar()、gets()、puts()、cin.get()、cin.getline()、getline()

    1.getchar: 原型为int getchar(void). 它从stdin里读取一个字符.返回值为用户输入的ASCⅡ码,出错返回-1. eg:c=getchar(). 2.putchar: 原型 ...

  9. getchar,scanf以及缓冲区

    getchar()是stdio.h中的库函数,它的作用是从stdin流中读入一个字符,也就是说,如果stdin有数据的话不用输入它就可以直接读取了.getch()和getche()是conio.h中的 ...

随机推荐

  1. oracle数据库 TIMESTAMP(6)时间戳类型

    时间戳类型,参数6指的是表示秒的数字的小数点右边可以存储6位数字,最多9位.由于时间戳的精确度很高,我们也常常用来作为版本控制. 插入时,如下方式:insert into test4 values(t ...

  2. java List分组和排序处理

    在一些应用中,需要将List中的对象按某种情况分组或者排序处理.做个小结如下: 1. 如一个List中存放了ProductDoing对象,productDoing对象有rawTypeId 现在要求将r ...

  3. Description Resource Path Location Type Unknown Unknown Unknown org.eclipse.core.internal.resources.Marker is not of a displayable type

    是访问限制报错. 方法一: 全局属性Project>preferences>java>Compiler>Errors/Warnings>把右侧的[Deprecated a ...

  4. Java并发多线程面试题 Top 50

    不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题.Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员的欢迎.大多数待遇丰厚的Java开发职位都要求开发者精通多线程 ...

  5. [MySQL]重装数据库后无法启动服务

    具体情况请查看下面网址 https://www.jianshu.com/p/8dda50ee812f 错误信息可以在CMD里输入mysqld --console查看

  6. Redis 学习-Redis 的其他功能

    一.慢查询 找到 系统中瓶颈的命令 1. 客户端请求的生命周期: ①. 慢查询通常发生在第三阶段. ②. 客户端超时不一定是慢查询,但慢查询是客户端超时的一个可能因素. 2. 相关配置 慢查询命令会存 ...

  7. 无法将文件“E:\NetWorkPace\Permission\packages\EntityFramework.6.1.1\lib\net45\EntityFramework.xml”复制到“bin\EntityFramework.xml”。对路径“bin\EntityFramework.xml”的访问被拒绝。

    无法将文件“E:\NetWorkPace\Permission\packages\EntityFramework.6.1.1\lib\net45\EntityFramework.xml”复制到“bin ...

  8. ansible之基础篇(三)

    setup ansible_all_ipv4_addresses # ipv4的所有地址 ansible_all_ipv6_addresses # ipv6的所有地址 ansible_date_tim ...

  9. Linux 进程IO杂项

    Linux 进程IO杂项 本文结合一个 pwn 例题,在分析例题的过程中穿插介绍相关知识. 例题来源:PWNABLE.KR 网站,Toddler's Bottle 小节,习题 input. 例题内容: ...

  10. Linux/Windows下安装SonarCube

    1. 下载合适的版本,尽量不要下载最新的版本,最新的版本要求Java 11+,如果没有安装最新版的Java的话,尽量用 SonarQube 7.0 以下的版本,SonarQube 7.0是可以用jdk ...