第4章 字符串和格式化输入

函数:strlen()

关键字:const

字符串

如何创建、存储字符串

如何使用strlen()获取字符串的长度

用C预处理指令#define和ANSIC的const修修饰符创建符号常量

 

目录

4.1 前导程序

4.2 字符串简介

4.2.1 char类型数组和null字符

4.2.2 使用字符串

4.2.3 strlen()函数

4.3 常量和C预处理器

4.3.1 const限定符

4.3.2 明示常量

4.4 printf()和scanf()

4.4.1 print()函数

4.4.2 使用print()

4.4.3 printf()的转换说明修饰符

4.4.4 转换说明

4.4.5 使用scanf()

4.4.6 printf()和scanf()的修饰符

4.4.7 printf()的用法提示

4.5 关键概念

4.5 本章小结


4.1 前导程序

// talkback.c -- nosy, informative program
#include <stdio.h>
#include <string.h>      // for strlen() prototype
#define DENSITY 62.4     // human density in lbs per cu ft
int main()
{
    float weight, volume;
    int size, letters;
    char name[40];        // name is an array of 40 chars
    
    printf("Hi! What's your first name?\n");
    scanf("%s", name);
    printf("%s, what's your weight in pounds?\n", name);
    scanf("%f", &weight);
    size = sizeof name;
    letters = strlen(name);
    volume = weight / DENSITY;
    printf("Well, %s, your volume is %2.2f cubic feet.\n",
           name, volume);
    printf("Also, your first name has %d letters,\n",
           letters);
    printf("and we have %d bytes to store it.\n", size);
    
    return 0;
}
Hi! What's your first name?
lalalala
lalalala, what's your weight in pounds?
1111
Well, lalalala, your volume is 17.80 cubic feet.
Also, your first name has 8 letters,
and we have 40 bytes to store it.

4.2 字符串简介

字符串(character string)是一个或多个字符的序列。

“Zing wet the strings of my heart! ”双引号告知编译器扩起来的是字符串,正如单引号标识单个字符一样。

4.2.1 char类型数组和null字符

把字符串中的字符逐个放入数组,计算机处理在末尾加\0的细节。scnf()在读输入的时候也完成这项工作的细节,包括define预定义的时候,总之,你不用亲自把空字符放在字符串末尾。

4.2.2 使用字符串

/* praise1.c -- uses an assortment of strings */
#include <stdio.h>
#define PRAISE "You are an extraordinary being."
int main(void)
{
    char name[40];
    
    printf("What's your name? ");
    scanf("%s", name);
    printf("Hello, %s. %s\n", name, PRAISE);
    
    return 0;
}

 

What's your name? angela lalala
Hello, angela. You are an extraordinary being.

注意:scanf()只会读取字符串的第一个单词,它在遇到第1个空白(空格、制表符、换行符)时就不再读取输入了。后面的fgets()函数用于读取一般字符串

4.2.3 strlen()函数

/* praise2.c */
// try the %u or %lu specifiers if your implementation
// does not recognize the %zd specifier
#include <stdio.h>
#include <string.h>      /* provides strlen() prototype */
#define PRAISE "You are an extraordinary being."
int main(void)
{
    char name[40];
    
    printf("What's your name? ");
    scanf("%s", name);
    printf("Hello, %s. %s\n", name, PRAISE);
    printf("Your name of %zd letters occupies %zd memory cells.\n",
           strlen(name), sizeof name);
    printf("The phrase of praise has %zd letters ",
           strlen(PRAISE));
    printf("and occupies %zd memory cells.\n", sizeof PRAISE);
    
    return 0;
}

What's your name? Serendiapity Chance
Hello, Serendiapity. You are an extraordinary being.
Your name of 12 letters occupies 40 memory cells.
The phrase of praise has 31 letters and occupies 32 memory cells.

string.h头文件包含多个与字符串相关的函数原型。一般而言,C把函数库中相关的函数归为一类,并为每类函数提供一个头文件。

截止到现在接触到两个头文件,stdio.h与string.h

注意,name数组明确告知有40个存储单元,故第12个单元存储空字符,strlen()并未将其计入。但是对于PRAISE,sizeof,把字符串末尾不课件的空字符也计算在内,因为它为明确告知计算机要给字符串预留多少空间,所以必须计算双引号的字符数。

sizeof和strlen返回的类型,C99和C11标准专门做了%zd的转换说明

4.3 常量和C预处理器

#define TAXRATE 0.0012

编译时替换(complie-time substitution),在运行程序时,所有的替换均已完成,这样定义的常量称为明示常量(manifest constant)

4.3.1 const限定符

const int MONTHS = 12;

const限定变量为只读变量

4.3.2 明示常量

// defines.c -- uses defined constants from limit.h and float.
#include <stdio.h>
#include <limits.h>    // integer limits
#include <float.h>     // floating-point limits
int main(void)
{
    printf("Some number limits for this system:\n");
    printf("Biggest int: %d\n", INT_MAX);
    printf("Smallest long long: %lld\n", LLONG_MIN);
    printf("One byte = %d bits on this system.\n", CHAR_BIT);
    printf("Largest double: %e\n", DBL_MAX);
    printf("Smallest normal float: %e\n", FLT_MIN);
    printf("float precision = %d digits\n", FLT_DIG);
    printf("float epsilon = %e\n", FLT_EPSILON);
    
    return 0;
}
Biggest int: 2147483647
Smallest long long: -9223372036854775808
One byte = 8 bits on this system.
Largest double: 1.797693e+308
Smallest normal float: 1.175494e-38
float precision = 6 digits
float epsilon = 1.192093e-07

4.4 printf()和scanf()

输入/输出函数 = I/O函数。函数打印数据的指令要与待打印数据的的类型匹配,需要用到转换说明(conversion specification)

4.4.1 print()函数

4.4.2 使用print()

4.4.3 printf()的转换说明修饰符

/* width.c -- field widths */
#include <stdio.h>
#define PAGES 959
int main(void)
{
    printf("*%d*\n", PAGES);
    printf("*%2d*\n", PAGES);
    printf("*%10d*\n", PAGES);
    printf("*%-10d*\n", PAGES);
    
    return 0;
}
*959*
*959*  //字段宽度自动扩大以符合整数的长度
*       959*  //7个空格和3位数字,并且数字位于字段右侧
*959       *  //
// floats.c -- some floating-point combinations
#include <stdio.h>

int main(void)
{
    const double RENT = 3852.99;  // const-style constant
    
    printf("*%f*\n", RENT);//系统默认值,小数点后6位
    printf("*%e*\n", RENT);//小数点左侧1个数字,右侧计数法
    printf("*%4.2f*\n", RENT);
    printf("*%3.1f*\n", RENT);
    printf("*%10.3f*\n", RENT);//控制小数点右侧显示位数
    printf("*%10.3E*\n", RENT);
    printf("*%+4.2f*\n", RENT);//前面显示+号
    printf("*%010.2f*\n", RENT);//0标记使得打印的值前面以0填充以满足字段要求
    
    return 0;
}
*3852.990000*

*3.852990e+03*
*3852.99*
*3853.0*
*  3852.990*
* 3.853E+03*
*+3852.99*
*0003852.99*
/* flags.c -- illustrates some formatting flags */
#include <stdio.h>
int main(void)
{
    printf("%x %X %#x\n", 31, 31, 31); //十六进制数
    printf("**%d**% d**% d**\n", 42, 42, -42);//在转换说明中用空格在输出的正值前面生成前导空格,负值前面不产生前导空格
    printf("**%5d**%5.3d**%05d**%05.3d**\n", 6, 6, 6, 6);//使用精度生成足够的前导0以满足最小位数的要求
    
    return 0;
}
1f 1F 0x1f
**42** 42**-42**
**    6**  006**00006**  006**
/* stringf.c -- string formatting */
#include <stdio.h>
#define BLURB "Authentic imitation!"
int main(void)
{
    printf("[%2s]\n", BLURB);//字段扩大为可容纳字符串中的所有字符
    printf("[%24s]\n", BLURB);//精度限制了待打印字符的个数
    printf("[%24.5s]\n", BLURB);
    printf("[%-24.5s]\n", BLURB);//-标记似的文本左对齐输出
    return 0;
}
[Authentic imitation!]
[    Authentic imitation!]
[                   Authe]
[Authe                   ]

4.4.4 转换说明

转换其实是翻译说明,把给定的值翻译成十进制整数文本并打印出来

 

/* intconv.c -- some mismatched integer conversions */
#include <stdio.h>
#define PAGES 336
#define WORDS 65618
int main(void)
{
    short num = PAGES;
    short mnum = -PAGES;
    
    printf("num as short and unsigned short:  %hd %hu\n", num,
           num);//336 336
    printf("-num as short and unsigned short: %hd %hu\n", mnum,
           mnum); //-336 65200
    printf("num as int and char: %d %c\n", num, num);// 336 p
    printf("WORDS as int, short, and char: %d %hd %c\n",
           WORDS, WORDS, WORDS);//65618 82 R
    return 0;
}
printf("-num as short and unsigned short: %hd %hu\n", mnum, mnum);

short int的大小为2字节,其次系统采用二进制补码来表示有符号整数,0~32767为本身,32768~65535为负数,65535为-1,655334为-2,65200为-336

short int是2字节,而char是1字节,所以%c打印336的时候,会进行截断相当于一个整数除以256,只保留其余数。在这中情况下余数是80,对应的ASCII值是字符P。即该数字被解释成“以256为模”(modulo 256),即该数字除以256后取其余数。

65518存储为4字节的int类型值,用%hd转换说明打印时,printf()只使用最后2个字节,相当于65618除以65536的余数,即余数是82.

/* floatcnv.c -- mismatched floating-point conversions */
#include <stdio.h>
int main(void)
{
    float n1 = 3.0;
    double n2 = 3.0;
    long n3 = 2000000000;
    long n4 = 1234567890;
    
    printf("%.1e %.1e %.1e %.1e\n", n1, n2, n3, n4); 
//float类型的值作为printf()参数时会被转换成double类型,即8字节
    printf("%ld %ld\n", n3, n4);
//正确的转换说明
    printf("%ld %ld %ld %ld\n", n1, n2, n3, n4);
//转换说明也会产生虚假的结果
    return 0;
}
3.0e+00 3.0e+00 3.1e+46 1.7e+266
2000000000 1234567890
0 1074266112 0 1074266112

floatcnv.c:10:45: warning: format specifies type 'double' but the argument has type 'long' [-Wformat]
    printf("%.1e %.1e %.1e %.1e\n", n1, n2, n3, n4);
                      ~~~~                  ^~
                      %.1ld
floatcnv.c:10:49: warning: format specifies type 'double' but the argument has type 'long' [-Wformat]
    printf("%.1e %.1e %.1e %.1e\n", n1, n2, n3, n4);
                           ~~~~                 ^~
                           %.1ld
floatcnv.c:12:33: warning: format specifies type 'long' but the argument has type 'float' [-Wformat]
    printf("%ld %ld %ld %ld\n", n1, n2, n3, n4);
            ~~~                 ^~
            %f
floatcnv.c:12:37: warning: format specifies type 'long' but the argument has type 'double' [-Wformat]
    printf("%ld %ld %ld %ld\n", n1, n2, n3, n4);
                ~~~                 ^~
                %f
4 warnings generated.

/* prntval.c -- finding printf()'s return value */
#include <stdio.h>
int main(void)
{
    int bph2o = 212;
    int rv;
    
    rv = printf("%d F is water's boiling point.\n", bph2o);
    printf("The printf() function printed %d characters.\n",
           rv);
    return 0;
}
212 F is water's boiling point.
The printf() function printed 32 characters.
/* longstrg.c –– printing long strings */
#include <stdio.h>
int main(void)
{
    printf("Here's one way to print a ");
    printf("long string.\n");
    printf("Here's another way to print a \
long string.\n");
    printf("Here's the newest way to print a "
           "long string.\n");      /* ANSI C */
    
    return 0;
}
//总之,不能在双括号括起来的字符串中间断行
Here's one way to print a long string.
Here's another way to print a long string.
Here's the newest way to print a long string.

4.4.5 使用scanf()

// input.c -- when to use &
#include <stdio.h>
int main(void)
{
    int age;             // variable
    float assets;        // variable
    char pet[30];        // string
    
    printf("Enter your age, assets, and favorite pet.\n");
    scanf("%d %f", &age, &assets); // use the & here
    scanf("%s", pet);              // no & for char array
//变量加&,字符数组不使用&
    printf("%d $%.2f %s\n", age, assets, pet);
    
    return 0;
}
Enter your age, assets, and favorite pet.
38
92360.88 llama
38 $92360.88 llama

Enter your age, assets, and favorite pet.
  42

      323。45
42 $323.00 。45

//scanf()函数使用空白把输入分成多个字段。在依次把转换说明和字段匹配时跳过空白。

scanf()根据一个%d转换说明读取一个整数,每次跳过所有空白字符,直至遇到第一个非空白字符才开始读取,并寻找数字字符或者符号,便保存该字符,并读取下一个字符。不断地读取和保存字符,直至遇到非数字字符,如果遇到了非数字字符,它便认为读到了整数的末尾。

scanf()能读取不同类型的数据。把更多字符识别成数字的一部分,浮点转换要求scanf()识别小数点、e计数法。

scanf("%d,%d",&n,&m)
88,121
88,
121

4.4.6 printf()和scanf()的修饰符

/* varwid.c -- uses variable-width output field */
#include <stdio.h>
int main(void)
{
    unsigned width, precision;
    int number = 256;
    double weight = 242.5;
    
    printf("Enter a field width:\n");
    scanf("%d", &width);
    printf("The number is :%*d:\n", width, number);
    printf("Now enter a width and a precision:\n");
    scanf("%d %d", &width, &precision);
    printf("Weight = %*.*f\n", width, precision, weight);
    printf("Done!\n");
    
    return 0;
}
Enter a field width:
6
The number is :   256:
Now enter a width and a precision:
8 3
Weight =  242.500
Done!
/* skiptwo.c -- skips over first two integers of input */
#include <stdio.h>
int main(void)
{
    int n;
    
    printf("Please enter three integers:\n");
    scanf("%*d %*d %d", &n);
    printf("The last integer was %d\n", n);
    
    return 0;
}
[wlsh@wlsh-MacbookPro] Ch04$ ./a.out 
Please enter three integers:
2013 2014 2015
The last integer was 2015

4.4.7 printf()的用法提示

printf("%d %d %d\n",val1,val2,val3);
12 234 1222
4 5 23
22334 2322 10001

printf("%9d %9d %9d\n",val1,val2,val3);
12    234   1222
 4      5     23

4.5 关键概念

4.5 本章小结

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值