我是靠谱客的博主 谨慎高山,最近开发中收集的这篇文章主要介绍C语言字符串的输出与输入学习笔记字符串的输入与输入,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

  • 字符串的输入与输入
    • 1.字符串初始化
      • 1⃣️:用足够的空间的数组存储字符串:
      • 2⃣️:省略数组初始化声明中的大小
    • 2.数组与指针
      • 1⃣️:指针创建字符串
      • 2⃣️:数组与指针的区别
      • 3⃣️:使用指针的优缺点
    • 3.scanf()与printf()
    • 4.gets()与puts()
    • 5.fgets()与fputs()
      • 1⃣️fgets()优缺点:
      • 2⃣️fgets()返回值:
      • 3⃣️fgets()操作实例:
      • 3⃣️fgets()操作进阶:

字符串的输入与输入

1.字符串初始化

1⃣️:用足够的空间的数组存储字符串:

const char word[15] ="Hello world ";

这里用const,表示该字符串不会被更改。

注意⚠️:在指定数组大小时,要确保数组的元素个数至少比字符长度多1,因为要容纳" "。所有未被使用的元素都被自动初始化为。
在这里插入图片描述

2⃣️:省略数组初始化声明中的大小

const char word[] ="Hello world!This is my first program! ";

让编译器计算数组大小只能用在初始化数组时,如果创建一个数组,稍后在填充,就必须在声明时指定大小。

2.数组与指针

字符数组名与其他数组名一样,是该数组首元素的地址。

char word[10] = "Hello!";

以下表达式都为真

word == &word[0]              //字符数组名为是该数组首元素的地址

*word == 'H'                  //数组首元素的地址解引用为首元素

*(word +1 ) == car[1] == 'H'  // 数组首元素的地址+1后解引用为数组第二个元素

1⃣️:指针创建字符串

const char *pt1 = " Something is poiting at me.";

2⃣️:数组与指针的区别

  • 初始化数组把静态存储区的字符串拷贝到数组中,而初始化指针只把字符串的地址拷贝给指针
  • 数组名为常量,指针名为变量

例:

char heart[] = "I love you";
const char *head = "I love you"; //为什么使用const,在下文‘使用指针的优缺点’中说明原因

数组名heart是常量,指针名head为变量

  • heart是地址常量,不能更改heart,如果更改了heart就意味着改变了数组的存储位置(地址)。可以进行类似heart+1这样的操作,标示数组的下一个元素。但不允许++heart,递增运算只用于变量前。
  • head为变量,该变量最初指向该字符串的首字符,但是他的值可以改变。可以递增运算。
  • char *head是一个指针,根本没分配内存,他指向的 “I love you” 是只读的,不能改变,在下面给他赋值肯定是错的。而char heart[]是一个数组,已经分配内存,是将 "I love you"复制到该内存里面,这个内存是可读写的 。
  • 指针是不分配内存的,它指向的是系统的只读的内存,而数组是分配内存的,就是将系统的只读的内存里面的值复制到它的内存里面,因此可读写

3⃣️:使用指针的优缺点

  • 缺点
    -双引号括起来的字符串是字符串字面量(string literal),是静态对象,因此从语义上来说,指针指向它之后字符串内容自然不可修改,推荐使用const修饰。

  • 优点const char *pt[5] , char arrays[5][8] pt数组是一个内含5个指针的数组,占用40字节。arrays是一个内含5个数组的数组,每个数组内含40个char类型值,占用200字节。所以指针效率高。

3.scanf()与printf()

#include <stdio.h>
int main(void){
    
    char word[8];
    scanf("%s",word);
    printf("%s##n",word);
    
}

定义一个char类型的长度为8的字符串,然后接收输入并打印输出,用##可以清晰的看出字符串结尾的边界

解析:
当我们输入hello world!后回车,发现控制台只有输出了hello##,这说明scanf读一个单词时到空格就结束。
在这里插入图片描述
为了再次证明整个原理,下面我们使用两次scanf读入输入的字符然后打印。

#include <stdio.h>
int main(void){
    
    char word[8];
    char word2[8];
    scanf("%s",word);
    scanf("%s",word2);
    printf("%s##%s##n",word,word2);
    
}

我们可以从下图中看出,第一次scanf发现hello后面有空格就读取完毕,并打印时添加了##。第二次scanf继续读取,发现world!后面有回车也同样读取完毕,并在打印时添加了##。
在这里插入图片描述

所以,scanf读取一个单词(到空格,tab或者回车为止),但这也意味着scanf不安全,因为不知道要读入内容的长度。

但是我们可以通过以下的方法,来控制scanf读取的长度。

#include <stdio.h>
int main(void){
    
    char word[8];
    char word2[8];
    scanf("%7s",word);
    scanf("%7s",word2);
    printf("%s##%s##n",word,word2);
    
}

我们在scanf中的%后面加入一个具体的数字,表示scanf最多读取的长度,在这里我们限制scanf最多读取7个字符。注意:这里是最多读取的长度,如果停止读取时字符串长度不满足,则直接取字符串。

如下图所示,我们第一行输入123,不满足7个字符串长度,prinf打印出来的就只有123.
第二行输入12345678超过7个,则scanf截断第8个字符串,prinf只打印出来1234567.
在这里插入图片描述
这就相当于,scanf不是以回车,空格或tab来读取,而是以你所需要的字符串长度来读取,从而实现了安全输入。

4.gets()与puts()

  • gets()函数简单易用,它读取整行输入,直到遇到换行符,然后丢弃换行符,储存其他字符,并在这些字符末尾添加一个空字符使其成为一个C字符串。
  • puts()函数,只需把字符串的地址作为参数传递给他即可,注意puts函数会在字符串后面加上换行符。

但是gets()无法检查数组是否能装得下输入行,gets函数并不知道数组中有多少元素,如果输入的字符串过长,会导致缓冲区溢出。

因此gets函数也是不安全的,不建议使用gets()。

5.fgets()与fputs()

  • fgets()函数的第二个参数指明了读入字符的最大数量。如果该参数为n,那么fgets函数将读入n-1个字符。如果fgets()函数读到一个换行符,会把它储存在字符串中。这点与gets不同,gets会丢弃换行符。fgets()函数的第三个参数指明要读入的文件。如果读入从键盘输入的数据,则以stdin作为参数。
  • fputs()函数的第二个参数指明他要写入的文件。如果要在计算机显示器上打印,则使用stdout作为参数。与puts()函数不同,fputs()函数不会在待输出字符串末尾添加一个换行符。

例:

#include <stdio.h>
#define LEN 14
int main(void){
    
    char words[LEN];
   
    puts("Enter a String");
    fgets(words,LEN, stdin);
    puts(words);  //puts()函数会添加换行符n
    fputs(words, stdout);
    
    return 0;
    
}

在这里插入图片描述
输入apple后,applen 被存储在数组中。
我们看到控制台输出的内容发现输出的两个apple之间有一行空白,因为puts()函数会添加换行符n。

1⃣️fgets()优缺点:

fgets()储存换行符有好有坏

  1. 缺点是你可能并不想把换行符储存在字符串中,这样的换行符会带来一些麻烦。
  2. 优点是对于储存的字符串而言,检查末尾是否有换行符可以判读是否读取了一整行。如果不是一整行,要处理好一行中剩下的字符。

2⃣️fgets()返回值:

读取成功,返回读取到的字符串,即string;失败或读到文件结尾返回NULL。

下面的程序验证读到文件结尾返回NULL。读入并显示用户输入的内容,直到fgets()读到文件结尾或空行(即,首字符为换行符)。

3⃣️fgets()操作实例:

#include <stdio.h>
#define LEN 10
int main(void){
    
    char words[LEN];
   
    puts("Enter Strings (empty line to quit): ");
    while(fgets(words, LEN, stdin) != NULL && words[0] != 'n'){
        fputs(words, stdout);
    }
    
    puts("Done!");
    
    return 0;
    
}

在这里插入图片描述
LEN设置的为10,所以fgets()一次读取9个字符(剩余一个字符留给’’),第一次读取到" I’m Kevin ",并存储为I’m Kevin,接着fputs()打印出来,并且没有换行。然后while进入下一轮迭代,fgets()继续读取,第二次读取到“ ,from Chi ",并存储为,from Chi,接着fputs()打印出来,并且没有换行。直到读取完所有字符为止。最后一次输入时,直接键入回车,所以跳出while循环,程序结束并打印Done!

3⃣️fgets()操作进阶:

如果说我们想第一次的输入 “I’m Kevin,from China.” 只读取前9个字符,然后丢弃掉其他的字符,第二次输入也是如此,那该怎么办???
换句话说该想法就是:按照设定的大小读取输入行,并删除储存在字符串中的换行符,如果没有换行符,则丢弃数组装不下的字符。
再拆分成小的问题则就是以下的两个问题:

  1. 那如果不希望把换行符储存在字符串中,如何处理掉换行符呢??
    我们可以在已储存的字符串中查找换行符,并将其替换为空字符:
while(words[i] != 'n' ) {
	i++;
	}
words[i] = '0;
  1. 如果仍然有字符串留在输入行怎么办??
    丢弃掉其余的字符串即可。
    详细原理可以查看主页文章《C语言 getchar()原理及易错点解析》
while(getchar() != 'n')
	continue;

我们把这两个问题整合到上面的代码中:

#include <stdio.h>
#define LEN 10
int main(void){
    
    char words[LEN];
   
    puts("Enter Strings (empty line to quit): ");
    while(fgets(words, LEN, stdin) != NULL && words[0] != 'n'){
       
        int i=0;
        
        while(words[i] != 'n' && words[i] != ''){
            i++;
        }
        
            if(words[i] == 'n'){
                words[i] = '';
            }else{
                while(getchar() != 'n')
                    continue;
            }
        
        puts(words);
    }
    
    puts("Done!");
    
    return 0;
    
}

在这里插入图片描述

   while(words[i] != 'n' && words[i] != ''){
                i++;
            }

这段代码说的是,遍历字符串,直至遇到换行符或者空字符。如果先遇到换行符,下面的if语句将其换成空字符;如何先遇到空字符,else就将输入行舍弃。

注意⚠️:空字符与空格不一样!!!!空字符是’ ',ASCII码为0;空格的ASCII为32. 下面程序可以验证:

#include <stdio.h>
void main()
{
    char a=' ';
    char b='';
    printf ("%dn",a);
    printf ("%dn",b);
    
}

Output:

32
0

最后

以上就是谨慎高山为你收集整理的C语言字符串的输出与输入学习笔记字符串的输入与输入的全部内容,希望文章能够帮你解决C语言字符串的输出与输入学习笔记字符串的输入与输入所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部