听翁恺老师mooc笔记(8)--字符串2

  字符串的赋值

  字符串的输入与输出

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

1 #include <stdio.h>
2 int main(void){
3     char word[8];
4     scanf("%s",word);
5     printf("%s##\n",word);
6
7     return 0;
8  } 

  程序在输出时,在%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##,没有回车。

 1 #include <stdio.h>
 2 int main(void){
 3     char word[8];
 4     char word2[8];
 5
 6     scanf("%s",word);
 7     scanf("%s",word2);
 8     printf("%s##%s##\n",word,word2);
 9
10     return 0;
11  } 

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。程序修改如下:

 1 #include <stdio.h>
 2
 3 int main(){
 4     char word[8];
 5     char word2[8];
 6
 7     scanf("%7s",word);
 8     scanf("%7s",word2);
 9     printf("%s##%s##\n",word,word2);
10
11     return 0;
12  }
13  

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,如我们所述一样,二维数组的第二维需要一个确切的大小。

1 #include <stdio.h>
2
3 int main(void){
4     char a[][]={"hello",};
5
6     return 0;
7 }

  那么修改上述代码为 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]。

1 #include <stdio.h>
2
3 int main(void){
4     char a[][10]={"hello","world","alksjfklasjlkfjsklfj"};
5
6     return 0;
7 }

  那么如果我们将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参数表里不是空的,有两个参数,一个是整数,一个是字符串数组,整数是告诉我们后面数组到底有多少字符串的,下面试一下,输出参数中所有字符串,看下到底是些什么?

 1 #include <stdio.h>
 2
 3 int main(int argc, char const *argv[]){
 4     int i;
 5     for (i=0;i<argc;i++){
 6         printf("%d:%s\n",i,argv[i]);
 7     }
 8
 9     return 0;
10 }

  共有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
请按任意键继续. . .
时间: 2024-10-05 15:34:17

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

听翁恺老师mooc笔记(5)--指针与数组

如果我们通过函数的参数将一个数组传递到参数中去,那么在函数里接收到的是什么东西呢?我们知道如果传递一个普通变量,那么参数接收到的是值,如果传递一个指针变量,参数接收到的也是值,只不过这时的值是地址.那么数组是什么?将数组作为值传给一个函数,在函数的参数里有一个数组变量来接收这个数组,看下到底接收到数组变量的什么东西呢?以minmax作为例子来测试下: 在minmax函数中能不能计算出数组a的个数?在minmax和main中分别添加printf函数,从结果可以看出,在main里a的大小是68,而在

翁恺老师C语言入门第三周编程题之《数字特征值》

题目内容: 对数字求特征值是常用的编码算法,奇偶特征是一种简单的特征值.对于一个整数,从个位开始对每一位数字编号,个位是1号,十位是2号,以此类推.这个整数在第n位上的数字记作x,如果x和n的奇偶性相同,则记下一个1,否则记下一个0.按照整数的顺序把对应位的表示奇偶性的0和1都记录下来,就形成了一个二进制数字.比如,对于342315,这个二进制数字就是001101. 这里的计算可以用下面的表格来表示: 数字 3 4 2 3 1 5 数位 6 5 4 3 2 1 数字奇偶 奇 偶 偶 奇 奇 奇

翁恺老师零基础学JAVA语言第五周数组--求平均数例题-个人理解

// 用户输入一系列数字,然后求出这些数字的平均数,并输出输入数字中大于平均数的数 Scanner in = new Scanner(System.in); System.out.println("你打算输入多少个数值?请输入:"); // 计算平均数,需要有:1.记录输入的每个数n:输入数的和sum:输入数值的个数cnt: int cnt = in.nextInt(); // 算平均数,定义sum为浮点数 double sum = 0; System.out.println(&quo

翁恺老师零基础学JAVA语言第五周数组--投票程序例题-个人理解

// 输入数量不确定的[0,9]范围内的整数,统计每一种数字出现的次数,输入-1表示结束 // 需要一个int[10]的数组来录入每次输入的数字;需要一个n表示每次输入的数字 // num[] = {0,1,2,3,4,5,6,7,8,9},刚好对应0-9这10个数字 Scanner in = new Scanner(System.in); int[] num = new int[10]; int n = in.nextInt(); if(n >= 0 && n <= 9) {

[JAVA]翁恺老师零基础学java语言第五周素数例题中continue的困惑

第五周求前50个素数的例子中,continue跳出当次循环后的疑问 例题中的这段: ======================================== MAIN_LOOP: for(int x = 3; cnt<50 ;x++) { for (int i=0 ;i<cnt ; i++) { if ( x%primes[i] == 0) { continue MAIN_LOOP; } } } =============================================

初识C语言中的函数(男神翁凯老师MOOC)

什么是函数? 函数是一块代码,接收零个或多个参数,做一件事情,并返回零个或一个值. 可以先想象成数学中的函数: y=f(x) 例如 求begin到end和的函数定义 void sum(int begin, int end) // void 为返回类型(不返回任何东西) sum 为函数名 (int begin, int end)为参数表) { int i; int sum; for(i=0;i<=end;i++){ sum +=i; } printf("%d到%d的和是%d\n",

素数和 翁恺老师C语言程序设计CAP第5章编程题

题目内容: 我们认为2是第一个素数,3是第二个素数,5是第三个素数,依次类推. 现在,给定两个整数n和m,0<n<=m<=200,你的程序要计算第n个素数到第m个素数之间所有的素数的和,包括第n个素数和第m个素数. 注意:是第n个素数到第m个素数,不是n和m之间的素数! 输入格式: 两个正整数,第一个表示n,第二个表示m. 输出格式: 一个整数,表示第n个素数到第m个素数之间所有的素数的和,包括第n个素数和第m个素数. 输入样例: 2 4 输出样例: 15 时间限制:500ms 内存限制

时间换算 翁恺老师C语言程序设计CAP第3章编程题

题目内容: UTC是世界协调时,BJT是北京时间,UTC时间相当于BJT减去8.现在,你的程序要读入一个整数,表示BJT的时和分.整数的个位和十位表示分,百位和千位表示小时.如果小时小于10,则没有千位部分:如果小时是0,则没有百位部分:如果小时不是0而分小于10分,需要保留十位上的0:如果小时是0而分小于10分的,则不需要保留十位上的0.如1124表示11点24分,而905表示9点5分,36表示0点36分,7表示0点7分. 有效的输入范围是0到2359,即你的程序不可能从测试服务器读到0到23

分解质因数 翁恺老师C语言程序设计CAP第5章编程题

题目内容: 每个非素数(合数)都可以写成几个素数(也可称为质数)相乘的形式,这几个素数就都叫做这个合数的质因数.比如,6可以被分解为2x3,而24可以被分解为2x2x2x3. 现在,你的程序要读入一个[2,100000]范围内的整数,然后输出它的质因数分解式:当读到的就是素数时,输出它本身. 输入格式: 一个整数,范围在[2,100000]内. 输出格式: 形如: n=axbxcxd 或 n=n 所有的符号之间都没有空格,x是小写字母x. 输入样例: 18 输出样例: 18=2x3x3 时间限制