朗朗空间

我知道并不是 所有鸟儿都飞翔

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  16 Posts :: 0 Stories :: 6 Comments :: 0 Trackbacks

常用链接

留言簿(1)

我参与的团队

搜索

  •  

最新随笔

最新评论

阅读排行榜

评论排行榜

(一)字符串输入函数
1.gets()函数
gets()函数从系统的标准输入设备获得一个字符串,gets()将一直读字符串直到遇到一个换行符\n,
按回车可以产生这个字符。

#include <stdio.h>
#define MAX 81
int main (void)
{
    
char name[MAX];    //分配空间
 
    
printf ("what's your name?\n");
    
gets (name);
    
printf ("Nice name, %s.\n", name);
 
    
return 0;
}

gets ()函数的构造如下:
char *gets (char *s)
{
……
return (s);
}
这个函数头说明 gets ()返回一个指向char的指针。
如果一切顺利,会如同上面的构造一样,返回读入字符串的地址。
如果出错或者如果gets ()遇到文件结尾,它就返回一个空(或0)地址。
这个空地址被称为空指针,习惯上用常量NULL表示,它定义在stdio.h头文件里面。
它可以很方便地以如下形式使用:

while (gets (name) != NULL)

注意:
不要混淆空指针和空字符。空指针是一个地址,而空字符是一个char类型的数据结构。
虽然二者都可以用0表示,但是他们的概念不同。

/*使用gets ()函数的返回值*/
#include <stdio.h>
#define MAX 81
int main (void)
{
    
char name[MAX];    //分配空间
    
char *ptr;
 
    
printf ("what's your name?\n");
    
ptr = gets (name);
    
printf ("%s? Ah! %s!.\n", name, ptr);
 
    
return 0;
}

2.fgets ()函数
gets ()函数的一个不足是它不检查预留存储区是否能够容纳实际输入的数据。
多出来的字符就简单的溢出到相邻的内存区。
fgets ()函数让您指定最大读入字符数。
fgets ()总共有3个参数
第一个参数和 gets ()函数相同
第二个参数说明最大读入字符数。
如果这个参数为n,那么gets ()就会读取最多n-1个字符或者读完一个换行符为止,由这二者中最先满足的那个来结束输入


如果fgets ()读到换行符,就会把它存到字符串里,不会像gets ()那样丢弃它。
它还需要第三个参数来说明读哪一个文件。从键盘上读数据时,可以使用stdin作为参数。这个标识符在stdio.h中定义。

#include <stdio.h>
#define MAX 81
int main (void)
{
    
char name[MAX];    //分配空间
    
char *ptr;
 
    
printf ("what's your name?\n");
    
ptr = fgets (name, MAX, stdin);
    
printf ("%s? Ah! %s!.\n", name, ptr);
 
    
return 0;
}

这个例子的结果会和gets ()有所不同,原因是fgets ()会读取换行符,这样在使用printf ()函数打印的时候会将换行符

打印出来。

3.scanf ()函数
scanf ()和上面两个函数的最大差别在于,scanf ()基于获取单词(get word)而不是获取字符串(get string);
scanf ()读取会以遇到的一个非空白字符开始。
如果使用%s格式,字符串读到(但不包括)下一个空白字符(比如空格、制表符或换行符)。
如果指定了字段的宽度,比如%10s,scanf ()就会读入10个字符或者一直遇到第一个空白字符,由二者中最先满足的那一个

终止输入。
scanf ()函数返回一个整数值,如果成功,返回成功读取的项目数;当遇到文件结束时返回EOF;

#include <stdio.h>
int main (void)
{
    
char name1[11], name2[11];
    
int count;
 
    
printf ("Please enter 2 names.\n");
    
count = scanf ("%5s %10s", name1, name2);
    
printf ("I read the %d names %s and %s.\n", count , name1, name2);
 
    
return 0;
}

根据以上特点,如果单纯读取字符串,使用gets ()最好,但为安全性考虑,可以改用fgets (),scanf ()主要用于混合输

入。

(二)字符串输出函数
puts (), fputs() 和printf ()
1.puts ()

#include <stdio.h>
#define DEF "I am a #deinfed string."
int main (void)
{
    
char str1[80] = "An array was initialized to me.";
    
const char *str2 = "A pointer was initialized to me.";
 
    
puts ("I' am an argument to puts ().");
    
puts (DEF);
    
puts (str1);
    
puts (str2);
    
puts (&str1[5]);
    
puts (str2 + 4);
 
    
return 0;
}

注意,结果的每一个字符串都会被puts ()函数自动在气候添加一个换行符。
所以每一个字符串都会单行显示。
这个例子说明双引号中的字符是字符串常量,并被看作地址。
同样,字符数组字符串的名字也被看作是地址。
表达式&str1[5]是数组str1的第6个元素地址。这个元素包含字符’r',它也是puts ()输出字符穿的起点.
同样,str2 + 4指向包含’i'的那个内存单元。

puts ()如何知道何时停止?
遇到空字符时它就会停下来,所以应该确保空字符存在。

不要模仿下面的程序

#include <stdio.h>
int main (void)
{
    
char side_a[] = 'SIDE A';
    
char dont[] = {'W', 'O', 'W', '!'};
    
char side_b[] = 'SIDE B';
 
    
puts (dont);
    
    
return 0;
}

dont是一个缺少表示结束的字符串,这样puts ()就不知道应该到哪里停止。
它只是一直输出内存中dont后面的字符,直到发现一个空字符。
为了使这个空字符不太遥远,程序把dont存储在两个真正的字符串之间。
这里希望你的编译器会将side_b存放在dont之后。但有的编译器做法不同。

2.fputs ()
fputs ()需要第二个参数来说明要写的文件。
可以使用stdout(standard output)作为参数来进行输出显示,stdout在stdio.h中定义。
注意:gets ()丢弃换行符,但puts ()为输出添加换行符。
fgets ()存储换行符,但fputs ()不对输出添加任何东西。

假定写一个循环,读取下一行并把它回显在下一行,可以这么写

char line[81];
while (gets(line))
{
    
puts (line);
}

也可以这么写

char line[81];
while (fgets (line, 81, stdin))
{
    
fputs (line, stdout);
}

从这里可以看出,这两对函数是配套设计的。

3.printf ()函数
printf ()需要自己添加换行符,但是更通用。
printf (”%s\n”, string);

4.自定义字符串输入/输出函数
我们可以在getchar ()和putchar ()的基础上定义自己的函数。
如:不添加换行符打印一个字符串

#incldue <stdio.h>
void put1 (const char *string)//不改变字符串
{
    
while (*string != '\0')
    
{
        
putchar (*string++);
    
}
}

char 指针指向被调用参数的第一个元素,由于这个函数不改变该字符串,所以使用const修饰符。
++的优先级比*高,意味着putchar (*string++)输出string指向的值,然后再增加string的值。
你可以看成是*(string++)。
最后,每一个字符串都会用空字符标识其结束,所以不必向函数传递字符串的大小。
相反,函数依次处理每个字符直到遇到空字符。
很错c程序员会在while循环中使用下面的判断条件:

while (*string)

说明:
为什么程序中使用const char *string 而不用 const char string[]作为形式参数?
技术上二者等价,但方括号提醒用户函数要处理的是一个数组。
而const char *string提醒你实际的参数不一定是一个数组。

打印一个字符串,并统计其中字符的个数。

#include <stdio.h>
int put2 (const char * string)
{
    
int count = 0;
    
while (*string)
    
{
        
putchar (*string++);
        
count++;
    
}
    
putchar ('\n');
    
    
return (count);
}

测试:

int main (void)
{
    
put1 ("If I'd as much money");
    
put1 ("as I could spned, \n");
    
printf ("I count %d characters.\n",
        
put2 ("I never would cry old chairs to mend. "));
    
    
return 0;
}

这里使用了嵌套函数调用。
我们使用printf ()输出put2 ()的值,但是在计算put2 ()值的过程中,计算机必须先执行这个函数。

(3)字符串处理函数
1.strlen ()
strlen ()函数得到字符串的长度。
下面这个程序缩短字符串的长度

void fit (char * string, unsigned int size)
{
    
if (strlen (string) > size)
    
{
        *
(string + size) = '\0';
    
}
}

这个函数需要改变字符串,因此在函数头的声明时不使用const修饰符。
2.strcat ()函数
strcat ()接受两个字符串参数。它将第二个字符串的一份拷贝添加到第一个字符串的结尾,从而使第一个字符串成为一个

新的组合字符串,但第二个字符串并没有改变。
strcat ()是char *类型,这个函数返回它的第一个参数的值。

#include <stdio.h>
#include <string.h>
#define SIZE 80
int main (void)
{
    
char flower[SIZE];
    
char addon[] = "s smell like old shoes.";
 
    
puts ("What is your favorite flower?");
    
gets (flower);
    
strcat (flower, addon);
    
puts (flower);
    
puts (addon);
 
    
return 0;
}

3.strncat ()函数
strcat ()函数并不检查第一个数组是否能够容纳第二个字符串。
如果没有为第一个数组分配足够大的空间,多出来的字符就会溢出到相邻的存储单元。
strncat ()函数允许你用另一个参数来指明最多允许添加的字符的数目。
如:
strncat (bugs, addon, 13)函数把addon字符串中的内容添加到bugs上,直到加到13个字符或遇到空字符为止,由二者中

现符合的那一个来终止添加过程。

#include <stdio.h>
#include <string.h>
#define SIZE 30
#define BUGSIZE 13
int main (void)
{
    
char flower[SIZE];
    
char addon[] = "s smell like old shoes.";
    
char bug[BUGSIZE];
    
int available;
 
    
puts ("What is your favorite flower?");
    
gets (flower);
    
if ((strlen (addon) + strlen (flower) +1) <= SIZE )
    
{
        
strcat (flower, addon);
    
}   
    
puts (flower);
    
    
puts ("What is your favorite bug?");
    
gets (bug);
    
avilable = BUGSIZE - strlen (bug) - 1;
    
strncat (bug, addon, available);
    
puts (bug);
 
    
return 0;
}

4.strcmp ()函数
假定您希望把用户的响应和一个已有的字符串进行比较。

//这个程序能满足要求吗?
#include <stdio.h>
#define ANSWER "Grant"
int main (void)
{
    
char try[40];
    
    
puts ("Who is buried in Grant's tomb?");
    
gets (try);
    
while (try != ANSWER)
    
{
        
puts ("No, that's WRONG, TRY AGAIN.");
        
gets (try);
    
}
    
puts ("That's right");
    
    
return 0;
}

尽管这个程序看上去不错,但不能正确工作。
ANSWER和try实际上是指针,所以比较式try != ANSWER并不检查这两个字符串是否一样,而是检查这两个字符串的地址是

否一样。由于ANSWER和try被存放在不同的位置,所以这两个地址永远都不会一样,用户永远会被告知”WRONG”。

strcmp ()函数用来比较两个字符串是否相同,特别的,如果两个字符串相同,它就返回0。

//这个程序可以满足要求
#include <stdio.h>
#define ANSWER "Grant"
int main (void)
{
    
char try[40];
    
    
puts ("Who is buried in Grant's tomb?");
    
gets (try);
    
while (strcmp (try, ANSWER) != 0)
    
{
        
puts ("No, that's WRONG, TRY AGAIN.");
        
gets (try);
    
}
    
puts ("That's right");
    
    
return 0;
}

说明:
由于任何非零值都为真,所以很多C程序员会把while语句简单地写为:

while (strcmp (try, ANSWER))
    
{
    
    
}

strcmp ()函数的一个优点是它比较的是字符串,而不是数组。尽管数组try占用40个内存单元,但是函数在比较时只看try

的第一个空字符之前的部分。
如果用于回答”GRANT”或”grant”会怎么样呢?
这些可都是正确答案,但程序没会返回WRONG。
我们可以使用#define把答案定义为”GRANT”,然后编写一个函数,把所有的输入转换成大写字母。

strcmp ()比较所有的字符,而不仅仅是字母,strcmp ()是按机器编码顺序进行比较的,如果两个字符串中的初始字符相

同,那么strcmp ()函数一直往后查找,直到找到一对不一致的字符,或者两个相同的空字符。然后就返回
负数,如果第一个字符串的机器编码比第二个字符串的机器编码小;
正数,如果第一个字符串的机器编码比第二个字符串的机器编码小;
0,两个字符串相等。

strcmp("A", "A") is 0
strcmp("A", "B") is -1
strcmp("B", "A") is 1
strcmp("Z", "a") is -7 注意a的机器码比Z

字符比较和字符串比较

if (strcmp (word, "quit") == 0)
    
{
        
puts ("Bye!");
    
}
    
if (ch == 'q')
    
{
        
puts ("Bye!");
    
}
posted on 2008-05-05 16:58 聂元朗 阅读(1100) 评论(0)  编辑 收藏 引用 所属分类: C语言学习笔记

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理