变量名

  • 变量名规则:只能用字母、数组和下划线(_)构成,且第不能以数字开头,不能使用关键字
  • 占位符:十进制整数(%d)、无符号十进制整数(%u)、八进制整数(%o)、十六进制整数(%x)、浮点型(%f)、指数方式输出(%e)、字符(%c)、字符串(%s)、地址(%p)
int main()
{
    int a=101;
    float b=0.1234;
    char c='\101',*s="asdf";
    printf("%-5d%-8.4f%-3c%-6s输出结束\n",a,b,c,s);
    printf("%-5u%-5o%-5x\n",a,a,a);//以无符号十进制、八进制、十六进制输出a=101
    printf("%.2e  %p  %p",b,&c,s);//以指数形式输出0.1234并规定系数部分显示两位小数,输出字符c、s串的地址
}
//101  0.1234  A  adsf  输出结束
//101  145  65
//1.23e-01  0x7ffc572f702f 0x400658
  • '*'、'.*'、'*.*'用于占位符中的作用(占用一位操作数)
int main()
{
    int a=0,b=0,c=0;
    scanf("%d%*d%d",&a,&b,&c);
    printf("a=%d,b=%d,c=%d\n",a,b,c);
    //'*'相当于占用了对应位置的数据,11赋值给a,12被*占用,13赋值给b,c没有赋值
    //输入:11 12 13
    //输出:a=11,b=13,c=0

    float a=10.1234;
    printf("a=%*.*f结束",-7,2,a);
    //两个*占用两个数据:所以-7替代了小数点前的*,2替代了小数点后面的*
    //所以以上语句相当于:printf("a=%-7.2f结束",a);
    //结束前有两个空格:10.12只占用了5位,左对齐右补两个空格
}
//a=10.12  结束
  • 宏定义:#define 标识符 常量
#include <stdio.h>
#define PI 3.1415926  //宏定义只是做简单机械的替换
int main()
{
    int r=2;
    printf("半径为2的圆面积为%6.2f;\n",PI*2*2);
    //%6.3f:小数点前的6表示这个数(字符串也遵循这个规则)所占的位数(浮点数包括小数点),小数点后的3表示显示这个浮点数三位小数(并会对第4位做四舍五入)
    printf("%6.3f\n%4.2f",PI,3.1415926e5);
    //3.1415926e5:表示3.1415926乘以10的5次方(当然也可以有314159.26e-5)
    //当数值位数小于输出位数时;若是正数则左起补空格(右对齐),若是负数则右末补空格(左对齐)
    //当数值位数大于输出位数时,则会全部输出数值
}
//半径为2的圆面积为 12.57;
// 3.142
//314159.26
  • 字符串:末尾系统自动加“\0”(空字符表示这个字符串结束)
#include <stdio.h>
int main()
{
    char str[]="love";
    printf("str占用字节数为:%d\n",sizeof(str));
    //str[]={'l','o','v','e','\0'};字符串的长度是不算'\0'字符的;(长度为0的字符串:""={'\0'})
}
//str占用字节数为:5

进制转换

  十进制:直接法,除留余数法转换;

  二进制、八进制、十六进制:只需要注意,3位二进制数是1位八进制数,4位二进制数是一位十六进制数

  • 二进制原码:一个二进制数由8位组成,第一位是符号位,其余位是数据位(0:表示正号;1:表示负号)
  • 二进制反码:正数反码跟原码相同;负数反码:符号位不变,数据位按位取反
  • 二进制补码:正数补码跟原码相同;负数补码:符号位不变,数据位按位取反,再在最低为加1(反码是原码与补码之间的过渡码)

数据类型

变量:

  数据类型:sizeof运算符可获取数据类型或表达式的字节数(如:sizeof(int) ; 注:不同操作系统结果不一定一样;)

    signedunsigned可限定char类型和所有整性类型符(包括short或long限定过的整型)

      signed: 表示可以带符号(表示可保存负数)
          一般 int 都可表示负数;(注:二进制形式第一位为0/1表示正/负数;所以最大可存储的数是2^31)
          计算机表示一个负数的方法:1、先取的该数绝对值的二进制;2、将这个二进制按位取反加1(补码)
      unsigned:整型使得原有整型长度不变,符号位变成了数据位,仅能表示零和正数。

int main()
{
    int a=100;
    unsigned int b=-100;
    printf("有符号输出:%d  无符号输出:%u\n",a,a);
    printf("有符号输出:%d  无符号输出:%u\n",b,b);
    //%u:用于输出无符号数; %d:用于输出有符号数
    //用有符号形式输出正数和负数都是问题的
    //用无符号形式输出负数则会错误输出为4294967196
}
//有符号输出:100  无符号输出:100
//有符号输出:100  无符号输出:4294967

  基本类型:整型(short int ; int ; long int ; long long int),浮点型(floatdoublelong double

  • 截断:将占字节数多的整形数据赋值给占字节数少的数据变量,只将低位原封不动的送给被赋值的变量
int main()
{
    int i=289;//4Byte:00000000 00000000 00000001 00100001(289)
    char c=i; //1Byte:00100001(33)
    printf("%d",c);
}
//输出:33

   字符(char),布尔(_Bool),枚举类型(enum
   指针类型
   构造类型
   空类型(void#include <stdio.h>

int main()
{
    int a=0.9,*p_a=&a;//为整数赋值浮点型,系统会自动强制转化为整形型;去掉小数部分,并不会四色五人
    float b=0,*p_b=&b;
    double c=0,*p_c=&c;//为浮点型赋值整数,系统会自动强制转化为浮点型
    char d=0,*p_d=&d;//为字符型赋值整数,系统会赋值为整形ASCII相应的字符
    printf("int:%d   int *:%d\n",sizeof(a),sizeof(p_a));
    printf("float:%d   float *:%d\n",sizeof(b),sizeof(p_b));
    printf("double:%d   double *:%d\n",sizeof(c),sizeof(p_c));
    printf("char:%d   char *:%d\n",sizeof(d),sizeof(p_d));
  //sizeof(int);sizeof(int *);也是可以正确输出的
  //这样直接输出会有%d输出"int"的警告,在sizeof(int)前进行强制转换则可以消除这种警告:(int)sizeof(int *); }
//int:4 int *:8 //float:4 float *:8 //double:8 double *:8 //char:1 char *:8

常量:

  • 每个系统分配的字节数可能是不同的;
  • 但 short int、int、long int、long long intf 分配的字节数是成2倍关系的
  • 每个字节(Byte)有8位二进制数(Bit),两个字节的int型最大可表示的数为65535
  • float类型:有效位为7位,说以最多显示到小数点后6位
  • double类型:有效位为15位(long double:19位);默认显示到小数点后6位,但可以指定小数点位数
#include <stdio.h>

int main()
{
    float f1=1.123456789f;
    //float:小数后面要跟f才是float类型,否则就是默认的double类型(相应的long int也是相似的定义方法)
    double f2=1.123456789;
    printf("float:%.14f  double:%.14f",f1,f2);
    //从输出结果可以看出来flout在小数点后6位以后是不准确的
}
//float:1.12345683574677  double:1.12345678900000
  • 字符常量有4种表示方法
//表示一个字符有4种方法:'?'的ASCII码为 63
int main()
{
    char a='?';//普通字符:'字符'
    char b='\?';//转义形式:'\字符'
    char c='\77';//八进制数转义形式:'\ooo'(其中o代表一个八进制数,当然:'\77'='\077')
    char d='\x3f';//十六进制数转义形式:'\xhhh'(其中h代表一个十六进制数)
    printf("a:%d %c  ",a,a);
    printf("b:%d %c  ",b,b);
    printf("c:%o %c  ",c,c);
    printf("d:%x %c",d,d);
    return 0;
}
//输出:a:63 ?  b:63 ?  c:77 ?  d:3f ?

  整型常量:31(十进制)、037(八进制)、0x1f(十六进制)、10(int)、10L(long)、10LL(long long)

  浮点型:10.0(double)、10.0f(float)

  字符常量:'0'-48、'A'-65、'a'-97

#include <stdio.h>
int main()
{
    int a=100;
    float f1=1.23456789;
    double d1=1.23456789;
    printf("%5d%5o%5x\n",a,a,a);
    printf("%f\n%f",f1,d1);
    //float型的有效位为7位;double型的有效位为15位;long double 19位(若超出对应精度,则显示的数可能不准确)
    //浮点数在系统中一般只计算到小数点后7位,并把第七位四色五人给小数点后的第六位
}
//  100  144   65
//1.234568
//1.234568
  • 字符串常量:用双引号包裹起来的≥0个的字符组成的序列为字符串常量;(字符串的长度是串中字符数、由于字符串以 '\0' 结束,所以所占空间为长度加一)
int main()
{
    char a[]="\"\778a\x30";
    printf("a占用空间数:%d a中字符为:%s结束",sizeof(a),a);
    //a:{'\"','?','8','a','0','\0'}
    //可以看出来其长度为5,占用空间数却是6
}
//输出:a占用空间数:6 a中字符为:"?8a0结束
  • 类型转换:强制转换(类型转换只体现在结果上,并不会改变转换变量的类型
  • 注意:强制转换时不会四舍五入,而是相0靠近;这点需要与格式输出( %.2f )区分清楚,这样的格式输出会对小数点后的第3位做四舍五入
int main()
{
    float f1=1.9f,f2=-1.9f;
    printf("f1强制转换:%d\n",(int)f1);
    printf("f2强制转换:%d",(int)f2);
    //可以看得出:浮点型强制转换整形,不会四色五人,只是向0靠近
}
//f1强制转换:1
//f2强制转换:-1
  • 自动转换:赋值时系统会自动将结果的类型转化为赋值类型;
int main()
{
    float a=1;
    int b=2.9,c=a+b;
    printf("a+b=%d",c);
    //实际上在执行时,由于是int、float型进行计算:计算机会将a,b的数据先转化为double型,再进行计算,最后将结果强制转换赋值给c(小杯+大杯=超大杯)
}
//a+b=3


运算符和优先级

  运算符:%取余(两边都必须是整性,若有浮点型时则会报错),在运算中,小数据类型会转化为大数据类型。输出时小数据类型也可以大数据类型格式输出,反之则不可。(单目运算符优先级高于双目运算符;非0即为真,就算是负数、浮点型数也为真。只有0是假

优先级 运算符
1 []  ()  . 成员选择  ->成员指针
2 -   (类型)  ++   --   *(取值指针)   &   !   ~   sizeof()计算占用内存大小
3  /  *  % (取整,乘,取余)
4  +  - (加减)
5  <<  >> (左移右移)
6 >  >=  <  <=
7 ==  !=
8 &(按位与)
9  ^(按位异或)
10  |(按位或)
11 &&(逻辑与)
12 ||(逻辑或)
13 ?:(三目)
14 = -=   *= ...(11种赋值)
15  ,(逗号运算符)
  • 第2行的单目,13行的三目运算符和14行的赋值运算为从右向左运算,其他均为从左向右(!0=1)
  • 三母运算符的优先级高于赋值
int a=5,b;
b=a>0?a: -a;//正确
//a>0?b=a:b=-a;错误,因为三目优先级高于赋值
//这里相当于(a>0?b=a:b)=-a;把一个整型常量赋值给另一个整型常量当然错误
  • 比较运算符和逻辑运算符的结果都只是0和1,在多类运算符混合在一起要区分清楚
int main()
{
    int a=3,b=4,c=5;
    printf("%d",!(a+b)+c-1&&b+c/2);
    //由于'&&'优先级低于'+-'低于'/'低于'!'
    //逆波兰:a b + ! c + 1 - b c 2 / + &&
    //所以表达式相当于:(!(a+b)+c-1)&&(b+c/2)
}
//输出:1
  • 逻辑与,逻辑或都运用短路取值
int main()
{
    //短路径取值:当可以得出结果时就不执行后面的语句
    //表达式1&&表达式2:当表达式1结果为假时,就可以判断出结果为假,不执行后面的表达式2
    //表达式1||表达式2:当表达式1结果为真时,就可以判断出结果为真,不执行后面的表达式2
    int i=0,j=0;
    i++&&++j;
    printf("i=%-3dj=%d\n",i,j);
    i=j=0;
    ++i||j++;
    printf("i=%-3dj=%d",i,j);
}
//i=1  j=0
//i=1  j=0
  • 大致优先级由强到弱分为:选择运算符,操作运算符,四则运算符,位移运算符,比较运算符,判断运算符,按位运算符,逻辑运算符,三目运算符,赋值运算符,‘,’
int main()
{
    printf("%d",5>3&&8<4-!0);
    //逆波兰表达式:5 3 > 8 4 0 ! - < &&
    //5>3——>1;1&&8<4-!0
    //!0——>1;1&&8<4-1
    //4-1——>3;1&&8<3
    //8<3——>0;1&&0
    //1&&0——>0;0 (结果)
}
//输出:0
  •  先自加(减)和后自加(减)的两种执行顺序
//i++和i--:先使用再自加(减)++和--i:先自加(减)再使用
int main()
{
    int a=7;
    printf("%3d",a++>7);a--;//'++'在'>'之前,先执行自增
    printf("%3d",7>--a);a++;//'>'后紧跟的是'++',无法比较,继续往后执行
    printf("%3d",7>a--);a++;//'>'后紧跟的是'a',马上比较
    printf("%5d",a+=a-=a+a);//'='、'-='、'+='、...等赋值符号的优先级只大于','
    printf("%5d",a++);a--;
    printf("%5d",++a);
}
//  0  1  0  -14  -14  -13
  • 指针也可以自加
int main()
{
    char a[]="abcdefg";
    char *p=a;
    while(*p!='\0')
        printf("%c ",*p++);
    //*p++:'*'解引用与'++'优先级相同,并且是后自加操作
    //先解引用*p;然后p地址自加
}
//输出:a b c d e f g
  • 常量(右值)不可以自加(减),数组名就是地址常量,所以不可以自加
  • 浮点数可以自加(减)
int main()
{
    double i=1.;
    printf("%f",++i);
}
//输出:2.000000
  • 浮点数不进行 '%' 取余操作;例如:3%1.0(错误)
int main()
{
    int i=1,b=0;
    b=(++i)+(++i)+(++i);
    printf("%d",b);
    //逆波兰表达式:i ++ i ++ + i ++ +
    //++i——>i=2:i+(++i)+(++i)
    //++i——>i=3:i+i+(++i)
    //i+i——>    6+(++i)【虽然'()'和'++'优先于'+',但系统只会判断前一个运算符的与栈顶的优先级关系】
    //++i——>i=4:6+i
    //6+i——>    10 (结果赋值给b)
}
//输出:10
  • 逻辑运算符优先级依次为:!,&&,||(非与或的优先级都低于加减)
//逗号表达式:表达式1,表达式2,表达式3(int a,b;分隔符);逗号表达式做为一个整体,他的值为最后一个表达式的值优先级是最低的
int
a=1,2,3; //这里a实际上赋了值为1(等号的优先级高于逗号,所以此表达式赋值给a的值并不为逗号表达式的值) a=(b=3,(c=b+4)+5); //过程为:1、b=3;2、c=b+4;3、a=c+5(因为加了括号之后得出的值才位逗号表达式的值)

位运算符

  位操作:在C语言中是没有规定一个字节占多少位的

  逻辑位运算符:" ~,&,^,| "【优先级从高到低,且针对二进制操作】
    ~:按位取反(单目运算符,不能和赋值号结合)
    &:按位与【a&b:a和b按位排放,对应位同为1时,结果为1 (有0则0)】
    ^:按位异或【a&b:a和b按位排放,对应位不同时,结果为1 (相同为0)】( 与1异或可实现转置:可用于针对个别位转置 )
      例如:15:00001111,15^3=00001111^00000011=00001100=12 ( 要针对转置对应位为1,其他均为0 )
    | :按位或【a&b:a和b按位排放,对应位不同为0时,结果为1 (有1则1)】
  移动运算符:"<<,>>"
    <<:左移,将左左边n位删除在右边添加n位0;
      例如:10:00001010,10<<2=00101000=40 【移动n位就相当于乘以2^n】
    >>:右移,将右左边n位删除在左边边添加n位0;
      例如:10:00001010,10>>2=00000010=2 【移动n位就相当于除以2^n】


基本逻辑语句

  • if语句嵌套中:表达式的条件可以是整形,浮点型,或者算式,else语句采取就近原则匹配if,所以建议使用‘{... }’
int main()
{
    double a=0.0;
    scanf("%lf",&a);
    if(a)
    if(0);
    else printf("Hello");
}
//输入:0    1
//输出:     Hello
//由这两次输出就可看出,else是与if(0)匹配的;
  • else if :当遇到为真的结果,则执行对应语句块,并停止对后续表达式的判断
int main()
{
    float a=0.0;
    scanf("%f",&a);
    if(a>=100)
        printf("满分");
    else if(a>=90)
        printf("优秀");
    else if(a>=60)
        printf("良好");
    else printf("不及格");
}
//输入:101      88
//输出:满分     良好
  • switch语句:传入表达式的类型一定整型(字符也是特殊的整型,不能传入字符串或浮点型),进行从上向下依次匹配case,若匹配成功,则从这个case中开始执行,之后的case不需要匹配直接按顺序执行,除非遇到break跳出循环
int main()
{
    int a;
    printf("请输入比赛名次:");
    scanf("%d",&a);
    printf("奖品:");
    switch(a){
        case 1:printf("电脑");
        case 2:printf("冰箱");
        case 3:printf("电视");
        default:printf("铅笔");
    }
}
//输入:1
//输出:奖品:电脑冰箱电视铅笔
//所以每个case中结束位置要加break;
  • case:对应常量必须互不相同,且不能是浮点型、变量、变量表达式;但对应的执行语句可以为空
int main()
{
    char c='\101';
    scanf("%c",&c);
    switch(c){
        case 'a':
        case 'A':printf("85-100\n");break;
        case 'b':
        case 'B':printf("70-85\n");break;
        case 'c':
        case 'C':printf("60-70\n");break;
        case 'd':
        case 'D':printf("0-60\n");
    }
}
  • default:default属于switch语句中的一部分当default不放在最后时:
  1. default前面的case匹配成功,后面的case(包括defualt)不需要匹配直接按顺序执行
  2. default后面的case匹配成功,后面的case不需要匹配直接按顺序执行(前面的defualt块不会执行)
  3. 全部case都匹配不成功,则从defualt开始执行,并且defualt后面的case不需要匹配直接按顺序执行
int main()
{
    int i=0;
    scanf("%d",&i);
    switch(i){
        case 1:printf("a");
        case 2:printf("b");
        case 3:printf("c");
        default:printf("#");
        case 4:printf("d");
        case 5:printf("e");
        case 6:printf("f");
    }
}
//输入:2       4       7
//输出:bc#def  def     #def
  • while语句:若为 "  do{... }while(条件) ;  " 要注意while后面要加‘;’
int main()
{
    char c;
    do{
        scanf("%c",&c);
        printf("%c",c);
    }while(c!='#');
    //首先,scanf函数是键盘输入回车后才开始从缓冲区读取数据的,并不是输入一个读取一个
    //其次,scanf函数可以读取空白字符(空格、Tab、回车)
    //最后,在这个程序中没有读取到'#'是不会停止运行的;(当输入中文也可以依样输出)
}
//输入:asdfqwer回车
//输出:asdfqwer回车(再次等待输入...)
  • for(表达式1;表达式2;表达式3):表达式都可省略,但‘ ; ’不可省略。每个表达式中若有多条语句,应该用‘,’隔开
int main()
{
    for(int a=0,b=10;;a++,b--)
        if(b>a)
            printf("%d ",a);
        else break;
}
//输出:0 1 2 3 4
  • break:跳出一层循环
  • continue:跳出本次循环,进行下一次循环
  • goto 标签;直接跳转到指定标签位置
int main()
{
    A:printf("哈哈");
    goto A;
}
//死循环输出:

 


 读取缓冲区数据

  cin:(c++语法)读取数据,以空白符作为读取结束标记;(在缓冲区读取字符时会过滤掉空白字符,如:回车、换行、制表符)

  cout:(c++语法)输出数据(不同变量和常量之间用 '<<' 隔开);(endl:是其独有的换行标志,也可不加)

    注:c++程序可以调用std名字空间来简化以上函数(using namespace std);cin>>a;

#include <iostream>
using namespace std;
int main()
{
    char a;
    int b;
    std::cin>>a;
    cin>>b;
    std::cout<<"a的值为:"<<a;
    std::cout<<"  b的值为:"<<b<<endl;
}
//输入:a12
//输出:a的值为:a  b的值为:12

  int scanf(char *fmt,...);格式化读取缓冲区,返回读取成功的个数,当读取失败或读取到文件尾时返回宏EOF;

  • scanf函数传入的赋值变量时必须传入地址(&),普通变量需要取地址,数组有两种方法(数组名偏移、数组元素取地址)不可以传入指针
int main()
{
    char str[3];
    for(int i=0;i<3;i++)
        scanf("%c",str+i);
    for(int i=0;i<3;i++)
        printf("%-3c",*(str+i));
    putchar('\n');
    for(int i=0;i<3;i++)
        scanf("%c",&str[i]);
    for(int i=0;i<3;i++)
        printf("%-3c",str[i]);
}
//输入:a1B2c#
//输出:a  1  B
//      2  c  #
  • 当输入格式不符合要求时,只能成功复制格式正确的部分;
int main()
{
    int a,b,c,z;
    z=scanf("%d%d%d",&a,&b,&c);
    printf("%3d%3d%3d__%d",a,b,c,z);
    //这里z得到返回的赋值成功的个数
    //由于此没有赋值成功,所以c的值是不一定的
}
//10 20,30
// 10 20  0__2
  • 数值和字符串这种需要区别赋值结束的变量,用空白字符标识这个变量赋值结束(如:空格、回车、制表符)
int main()
{
    char c1,c2;
    int a,b,c,z;
    z=scanf("%c%3d%3d%3d%c",&c1,&a,&b,&c,&c2);
    printf("%c %d %d %d %c %d",c1,a,b,c,c2,z);
    return 0;
}
//输入:a010020030b按位读取//或者:a 10 20 30b按位读取,前面的空格也会占位
//输出:a 10 20 30 b 5
  • scanf("%s",str);赋值字符串时,传入的参数可以是字符数组,但不可以是字符指针;
int main()
{
    int i,j,k;
    char *str1,str2[20];
    i=scanf("%s",str1);
    j=scanf("%s",str2);
    //scanf赋值字符串:对字符数组有效;对字符指针无效
    //str="asdf"形式赋值:str是字符数组时不合法(与定义连用时除外:char str[]="asdf"合法)
    //                  str是字符指针时合法
    printf("str1赋值情况%d\n",i);
    printf("str2赋值情况%d\n",j);
    for(k=0;k<20;k++)
        printf("%c",str2[k]);
}
//输入:asdf回车
//输出:str1赋值情况0
//      str2赋值情况1
//      asdf(...未知字符)

    注:连续使用该函数时,由于前一个输入以回车结束,所以回车字符会影响到当前的读取情况;需要用一个getchar()来读取掉回车,或直接清空一下缓冲区;

int main()
{
    char a,b;
    while(scanf("%c%c",&a,&b)!=EOF){
        getchar();
        printf("%c%c\n",a,b);
    }
}
//输入:ab回车cd回车
//如果去掉getchar();则ab的值依次为:ab 回车c d回车
scanf 函数中用到的格式附加字符
字符 说明
l 用于输入长整形数据(可用%ld,%lo,%lx,%lu)以及double型数据(用%lf或%le)
h 用于输入段整形数据(可用%hd,%ho,%hx)
域宽 指定输入数据所占的宽度(列宽),域宽应该为正整数
* 代表本输入项在读入后不赋给相应的变量

  int printf(char *fmt,...);格式化输出,返回输出字符的个数;

  • printf函数是可变参数,参数采用从右向左的方式压栈,从左向右的方式弹栈
int main()
{
    int a=4;
    printf("%d %d %d %d %d",a++,--a,a+=5,a--,++a);
    //++a是后使用:先执行自加,然后等待使用(a=5)
    //a--是先使用:第4位置直接输出a现在的值5,再自减(a=4)
    //a+=5是一个执行语句:先执行,然后等待使用(a=9)
    //--a是后使用:先执行自减,然后等待使用(a=8)
    //a++是先使用:第1位置直接输出a现在的值8,再自加(a=9)
    //由于可变参数已将全部压栈,所以开始弹栈
    //将a逐一弹栈:第2、3、5位置等待输出的就是a的结果9
}
//8 9 9 5 9
  • 当实际位数大于指定输出位数时会全部输出
int main()
{
    int a=123456;
    char str[20]="asfdqwer";
    printf("%5s_%2d",str,a);
}
//输出:asfdqwer_123456
  • printf函数和scanf函数都是变参数类型,后面的参数个数和前面字符串中占位数不同是不会影响程序的执行
int main()
{
    int a=1,b=2,c=4;
    printf("a=%d,b=%d,c=%d\n",a,b,c,a,b,c);
    printf("a=%d,b=%d,c=%.2f",a,b);
    //占位符没有对应的数据会错误输出
}
//a=1,b=2,c=4
//a=1,b=2,c=0.00
  • (特例):scanf函数接收 double 类型的数据时占位符应该是 %lf (因为%f是输入 float 类型是占位符);printf 函数输出%的方法:printf("%%");
int main()
{
    float a=0.0;
    double b=0.0;
    scanf("%f,%lf",&a,&b);
    printf("%-6.2f%%%.2f",a,b);
}
//输入:3.6,101
//输出:3.60  %101.00
printf 函数中用到的格式附加字符
字符 说明
l 用于长整形,可加在格式符d、o、x、u前面
m(代表一个正整数) 数据最小宽度
n(代表一个正整数) 对实数,表示输出最小n位小数;对字符串,表示截取的字符个数
输出的数字或字符在域内向左靠

  getchar();从缓冲区中读取一个字符,回车后开始读取(回车也会被读取到:10)

  putchar();输出一个字符;

int main()
{
    char a;
    a=getchar();
    putchar(a);
}
//输入:a回车
//输出:a

  gets(str);传入数组或则指向数组的指针,缓冲区读取一段字符串赋值给str;以回车符结束(与scanf读取字符串相比会读入空格、Tab),但不会读取回车符,并且会在字符串结束位置自动加 '\0'。

int main()
{
    char a[10],*p=a;
    //p如果指向字符元素或者没有指向字符数组,则不可以正常赋值
    gets(p);
    puts(a);
    gets(a);
    puts(p);
}
//输入:asdf
//输出:asdf
//输入:qwerqwer
//输出:qwerqwer

  puts(str);输出一个字符串,并且末尾自动换行

int main()
{
    char str[10];
    gets(str);
    //gets函数:以回车结束,并且会读取空格、tab这种空白字符
    puts(str);
    //puts函数:输出一个字符串,并且自带换行
    printf("str的长度为%d",strlen(str));
}
//asf   d a回车
//asd   f a
//str的长度为7

清除缓冲区
  fflush(stdin);
  flushall();

字符串处理函数<string.h>

  • strlen(str);获得字符串长度(字符串的实际长度)
  • sizeof(str);获得字符串尺寸(字符指针是规定值;字符数组是数组长度)
#include <stdio.h>

int main()
{
    char str1[10]="asdf";//注:char str[]="asdf";sizeof(str)为5;strlen(str)为4;因为系统自动在末尾加了:'\0'
    //数组长度为10,所以尺寸是10
    //但只放了4个字符,所以字符串长度为4
    char *str2="asdf";
    //指针占8个字节,所以尺寸是8
    //但字符串中只有4个字符,所以长度是4
    printf("%d___%d\n",sizeof(str1),strlen(str1));
    printf("%d___%d",sizeof(str2),strlen(str2));
}
//输出:10___4
//      8___4
  • strcat(str1,str2);将str2拼接到字符串str1上;
  • strncat(str1,str2,n);将str2拼接到字符串str1上;不同的是可以指定拷贝多少字符;(有效的防止了溢出)
#include <stdio.h>

int main()
{
    char str1[]="a";
    char *str2="asfd";
    printf("拼接前str1的长度:%d\n",strlen(str1));
    strncat(str1,str2,3);
    //strcat和strncat都可以导致溢出;当溢出不会影响程序的执行
    printf("拼接后str1的长度:%d\n",strlen(str1));
    puts(str1);
}
//拼接前str1的长度:1
//拼接后str1的长度:5
//aasf
  • strcpy(str1,str2);将str2字符串拷贝到str1上;
  • strncpy(str1,str2,n);将str2前n个字符拷贝到字符串str1上;
  • strcmp(str1,str2);比较两个字符串大小(比较返回值:相等【0】;不相等【str1[ i ]-str2[ i ]】i 为str1与str2对应字符不相同的第一个字符下标)
  • strncmp(str1,str2,n);比较两字符串前 n 个字符的大小(若传入的是字符串常量,则返回值只有:相等【0】、str1大于str2【1】、str1小于str2【-1】)
int main()
{
    char str1[]="asdf9weqr";
    char str2[]="asdf0zasdv";
    //这里str1与str2前4个字符大小相等,第5个字符,str1[4]-str2[4]=9(按照字典位置确定字符大小:'a'-'0'=49;'a'-'A'=32)
    printf("%d___%d___%d",strncmp(str1,str2,4),strcmp(str1,str2),strcmp(str2,str1));
}
//0___9___-9
  • strlwr(str);将字符串中的字母全部转化为小写字母
  • strupr(str);将字符串中的字母全部转化为大写字母
#include <stdio.h>
#include <string.h>

int main()
{
    char str[]="AaBbCcDd12";
    strlwr(str);//将字符串中的字母全部转化为小写字母
    puts(str);
    strupr(str);//将字符串中的字母全部转化为大写字母
    puts(str);
}
//aabbccdd12
//AABBCCDD12