字符串的赋值

  字符串的输入与输出

  对C语言的基础类型,比如int、double等类型,scanf、printf有专门的格式转换,而对字符串,scanf、printf使用%s格式字符进行输入与输出。当使用scanf进行读一个字符串的时候,读到什么东西,读到什么位置为止是很微妙的,试一下:

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

  程序在输出时,在%s后面添加两个##,来提示我们输出释放结束。编译运行后输入hello world,结果如下,输出只有hello,没有world,也没有hello和world之间的空格。

hello world
hello## --------------------------------
Process exited after 5.404 seconds with return value 0
请按任意键继续. . .

  对代码再修改如下,试着能到world,新建了两个字符串,使用scanf读取两次再使用printf输出两次,结果第一次读到的是hello不带空格,第二次读到的是world也不带空格,因为空格是区分hello和world的,是分隔符。如果输入hello会出,然后输入world再回车,输出结果依然是hello##world##,没有回车。

 #include <stdio.h>
int main(void){
char word[];
char word2[]; scanf("%s",word);
scanf("%s",word2);
printf("%s##%s##\n",word,word2); return ;
}
hello world
hello##world## --------------------------------
Process exited after 7.528 seconds with return value 0
请按任意键继续. . .

  所以综上,%s读到的是一个“单词”,这个单词不是英文中的单词,而是读到空格、tab或回车为止。可见scanf是不安全的,它不知道要读入的内容的长度是多少,再使用scanf时,没有给scanf任何字符串word有多大,我们再学数组时知道,数组作为函数参数时,传进去的是个指针。再上述程序中,开了8个字节的一个数组,那么当你输入的东西超过8个会怎么样?在32位编译系统中,当输入超过8个时有可能输出部分结果,也有可能运行结果崩溃,崩溃的原因是输入越界了。

  那么给字符串写入时,怎么使scanf函数安全哪?在%s前面加一个7,因为申请8个字节,有一个字节是结束符\0。程序修改如下:

 #include <stdio.h>

 int main(){
char word[];
char word2[]; scanf("%7s",word);
scanf("%7s",word2);
printf("%s##%s##\n",word,word2); return ;
}
1234567812345678
1234567##8123456## --------------------------------
Process exited after 8.191 seconds with return value 0
请按任意键继续. . .

  当输入1234567812345678时,前7个字符给了第一个scanf,而8123456近邻的这7个字符给了第二个scanf。所以在%和s之间的数字表示最多允许读入的字符的数量,这个数组应该比数组的大小小1.所以有数字控制读多少个,而字符后有没有空格、tab等还有没有用,当读入的个数不超过7个时,出现空格、tab或回车等,依然有效,但当超过7个时,只读入7个字符,因为读入的个数由%和s之间的数字确定。那么读入7个后下面的内容会交给其他scanf等。

  常见错误

  误解1:比如下面代码,使用char*定义后就可以直接使用了,以为char*是字符串类型,定义了一个字符串类型的变量string就以为可直接使用了,但实际上char*只是定义了一个指向某一块内存空间的指针,但是这个指针没有被初始化,然后char*是本地变量,本地变量没有默认的初始值,所以很可能指向一个未知的不可写的空间,那么在使用scanf写入一些东西时,系统就会崩溃。(未见每一次都崩溃,但是早晚有一天就崩溃了,或者在这台电脑没有崩溃,换一台电脑运行同一块代码就会崩溃)。

char * string;
scanf(“%s”,string);

  误解2:关于空字符串。比如下面代码,相邻的紧挨着”“意思是这是一个空字符串,第一行制定数组是100,依然是一个有效的字符串,但是这个字符串的buffer[0]='\0'。但第二行没有指定buffer的大小,这个字符串数组的长度是1,不可以写入东西。

char buffer[100]="";
char buffer[]="";

  字符串数组

  如果你想写一个数组去表达很多个字符串,char**a,a是一个指针,指向另一个指针,而那个指针指向一个字符(串),所以这不是我们需要的字符串数组。

  char[][]是什么呢,a是一个二维数组的变量,在二维数组中,第二维一定需要一个确切的大小的,否则编译通不过。试一下这件事情,代码如下,编译时出错,错误提示为:4 11 D:\Cexample\char.cpp [Error] declaration of 'a' as multidimensional array must have bounds for all dimensions except the first,如我们所述一样,二维数组的第二维需要一个确切的大小。

 #include <stdio.h>

 int main(void){
char a[][]={"hello",}; return ;
}

  那么修改上述代码为 char a[][10]={"hello",};,表示a这个数组里的每个单元是一个char [10],也就是a[0]相当于一个数组,当然这么写,如果输入超过10个字符时,编译器就会出错:4 54 D:\Cexample\char.cpp [Error] initializer-string for array of chars is too long [-fpermissive]。

 #include <stdio.h>

 int main(void){
char a[][]={"hello","world","alksjfklasjlkfjsklfj"}; return ;
}

  那么如果我们将char a[][]改为char *a[],这个时候就不会出错,在这个时候,a[0]相当于char *。这两种形式是不一样的,当定义char a[][10]时,意思是在内存里有一个很大的矩形,每个a[]都是10个字符。而定义成char *a[]的形式,意思是每个元素都比较小,a[0]是一个指针,指向外面的某个地方。

  作业:试着使用字符串数组完成输入月份,那么输出这个月份的英文单词。

  程序参数-主函数参数

  字符串数组还有一个应用就是可作为main函数的参数:int main(int argc,char const *argv[]),main参数表里不是空的,有两个参数,一个是整数,一个是字符串数组,整数是告诉我们后面数组到底有多少字符串的,下面试一下,输出参数中所有字符串,看下到底是些什么?

 #include <stdio.h>

 int main(int argc, char const *argv[]){
int i;
for (i=;i<argc;i++){
printf("%d:%s\n",i,argv[i]);
} return ;
}

  共有argc个字符串,使用for循环,输出每一个字符串,输出格式是”i:字符串内容“,i是从0开始。结果截图如下,目前只有一个字符串,也就是i=0时的字符串,该字符串内容和终端左上角是一样的,也就是第0个参数是可执行文件:

  在devc++的运行菜单选择参数,弹出下列对话框,在传递给主程序的参数中输入任意字符串,然后再运行时,结果有四个参数,第0个参数是生成的可执行文件,第1个、2个、3个参数是用户执行该程序的输入,具体有几个参数看用户输入几个。

0:D:\Cexample\char3.exe
1:niu
2:xiao
3:xia --------------------------------
Process exited after 0.02373 seconds with return value 0
请按任意键继续. . .

听翁恺老师mooc笔记(8)--字符串2的更多相关文章

  1. 听翁恺老师mooc笔记(7)--字符串1

    C语言中字符串的定义 如果定义一个字符数组word,并使用大括号对其初始化,如下图所示: 但是这个不是C语言的字符串,只是字符数组,不是字符串,因为不能使用字符串的方式进行计算.那么C语言的字符串长什 ...

  2. 听翁恺老师mooc笔记(15)--文件的输入与输出

    <>重定向 如果使用标准的printf输出,有一个比较简便的方法,可以将程序的结果写入一个文件.使用<和>符号,将程序运行结果重定向到文件中去,具体使用到的代码如下: ./te ...

  3. 听翁恺老师mooc笔记(14)--格式化的输入与输出

    关于C语言如何做文件和底层操作: 文件操作,从根本上说,和C语言无关.这部分的内容,是教你如何使用C语言的标准库所提供的一系列函数来操作文件,最基本的最原始的文件操作.你需要理解,我们在这部分所学习的 ...

  4. 听翁恺老师mooc笔记(13)--类型定义和联合

    typedef 虽然我们知道使用struct这个关键字定义一个结构类型,然后可以使用该结构类型定义变量.但是每次要使用的时候都需要带着struct这个关键字,那么如何摆脱这个关键字哪?C语言提供了一个 ...

  5. 听翁恺老师mooc笔记(2)-第一个程序--&运算符

    使用devC++写hello world 第一步:文件-新建-源代码.然后输入"输出hello world"程序: 注意:写程序时关闭中文输入法,否则语句输入的分号可能会被识别为错 ...

  6. 听翁恺老师mooc笔记(16)--程序设计与C语言

    问题1:计算机遍布生活的各个方面,若你需要一个功能可以下载APP,我们需要的大部分功能都可以找到对应的APP,如果没有可以自己写一个软件,但是很少人需要这么做,那么我们为什么学习计算机编程语言? 学习 ...

  7. 听翁恺老师mooc笔记(12)--结构中的结构

    结构数组: 和C语言中的int,double一样,一旦我们做出一个结构类型,就可以定义这个结构类型的变量,也可以定义这个结构类型的数组.比如下面这个例子: struct date dates[100] ...

  8. 听翁恺老师mooc笔记(11)--结构和函数

    结构作为函数参数: 声明了一个结构就有了一种自定义的数据类型,这个数据类型和int.float.double一样,int等基本类型可以作为函数的参数,那么这种个自定义的结构类型也应该可以作为函数参数, ...

  9. 听翁恺老师mooc笔记(10)--结构

    定义结构: 在程序里,如果想要表达一个数据就需要一个变量,而每个变量又都需要一个类型,之前学过C语言中有int.double.float.char等这些基础类型,还有指针.数组等.如果你要表达的数据比 ...

随机推荐

  1. Python内置函数详解——总结篇

    2个多月来,将3.5版本中的68个内置函数,按顺序逐个进行了自认为详细的解析,现在是时候进行个总结了.为了方便记忆,将这些内置函数进行了如下分类:     数学运算(7个)     类型转换(24个) ...

  2. C#方法有关内容的总结--C#基础

    1.静态方法与实例方法 using System;using System.Collections.Generic;using System.Linq;using System.Text;using ...

  3. 20165304《JAVA程序设计》第二周学习总结

    课本内容总结 第一章 1.标识符与关键字 (1) 标识符由字母.数字.下划线"_".美元符号"$"组成,第一个字符不能是数字. 不能把java关键字和保留字作为 ...

  4. Python Cookbook(第3版)中文版:15.20 处理C语言中的可迭代对象

    15.20 处理C语言中的可迭代对象¶ 问题¶ 你想写C扩展代码处理来自任何可迭代对象如列表.元组.文件或生成器中的元素. 解决方案¶ 下面是一个C扩展函数例子,演示了怎样处理可迭代对象中的元素: s ...

  5. 【BZOJ4650】【NOI2016】优秀的拆分(后缀数组)

    [BZOJ4650][NOI2016]优秀的拆分(后缀数组) 题面 BZOJ Uoj 题解 如果我们知道以某个位置为开始/结尾的\(AA\)串的个数 那就直接做一下乘法就好 这个怎么求? 枚举一个位置 ...

  6. 【BZOJ4530】大融合(Link-Cut Tree)

    [BZOJ4530]大融合(Link-Cut Tree) 题面 讨厌权限题!!! Loj链接 题目描述 小强要在 N个孤立的星球上建立起一套通信系统.这套通信系统就是连接 N个点的一个树.这个树的边是 ...

  7. [BZOJ1602] [Usaco2008 Oct] 牧场行走 (LCA)

    Description N头牛(2<=n<=1000)别人被标记为1到n,在同样被标记1到n的n块土地上吃草,第i头牛在第i块牧场吃草. 这n块土地被n-1条边连接. 奶牛可以在边上行走, ...

  8. SQL基础教程读书笔记-3

    5 复杂查询 5.1 视图 1.表和视图的区别表:保存的是实际的数据视图:保存的是SELECT语句.从视图读取数据时,视图会在内部执行该SELECT语句并创建出一张临时表. 2.视图的优点① 无需保存 ...

  9. TypeScript入门知识四(表达式和循环)

    一,箭头表达式 用来声明匿名函数,消除传统匿名函数的this指针问题 //单行的话可以省略{},多行的不能省. var sum = (arg1,arg2)=> arg1+arg2; //定义一个 ...

  10. 移动端造json假数据时的坑(转义符问题)

    最近在 Json 数据的解析上碰到了一些坑,特此记录一下. 正文 迭代开发中,经常出现服务端接口还没开发完成的情况,所以经常需要移动端自己在本地造一些假数据. emmm,虽然说好像造假数据也不是什么很 ...