C language_0313 Notes_String: exist in the form of an array/or a pointer/how to choose? /char */input and output/common errors/array expresses many strings (char *a[])/main standard definition

10.1.1 Strings

char word[]={'h','e','l','l','o','!'};//不是字符串
char word[]={'h','e','l','l','o','!','\0'};//是C语言的字符串 又是数组
  • \0: There is \0 in it, and its meaning is 0. You can directly put a single 0 in this position without adding single quotes and backslashes.

This 0 makes the word variable a string, which is essentially still a character array and has dual functions .

String (actually an array)

  • Backslash 0 in single quotes: [mark the end of the string] directly writing 0 may be an int or larger type

  • 0 in single quotes: 0 in ASCII, 48 in decimal

Define string (essentially an array)

  • There are several ways to define strings:

  • The first type: a pointer named str points to a character array Hello, where is the content, and I will talk about it later

  • The second type: Now there is a character array named word, the content is Hello

  • The third type: there is a character array named line, the size is 10 , and the first 6 (0~5) are Hello+0

string constant

  • Things enclosed in double quotes like "Hello" are called string constants (literals)

  • "Hello" will be turned into a character array by the compiler and placed somewhere (length 6, with 0 at the end ) [Length as seen by eyes + 1]

  • Can be seen in various statements, scanf, printf, etc.

  • Two adjacent character constants will be automatically linked together , and can also be linked with a slash

summary

10.1.2 String constants and variables

String pointer: try to change its value

char* s="Hello World!";
This means that s is a string (verbally) whose value is HelloWorld.
  • For example, I change the first letter H to B and output it:

char* s="Hello World!";
s[0]='B';
 
printf("s[0] = %c\n",s[0]);
//编译,没有问题,而运行会报错,而且printf没有执行,说明是在s[0]这一句这里出错了。【代码段 只读】
char* s ="Hello World!";
char* s2="Hello World!";
 
printf("s  = %p\n",s);
printf("s2 = %p\n",s2);
 
printf("s[0] = %c\n",s[0]);

//得到的结果竟然是相同的,而这两个的地址值都远小于正常变量的地址(定义一个int i,其地址为0xbff1fd6c),说明这两个字符串存放在很远的地方。

那么实际上,这样定义的字符串是将HelloWorld放到了程序的代码段,是 只读 的(也就是字符串常量),在编译时候就已经定义好了,然后让指针指向它。

由于这个常量位置特殊,实际上s是const char* s,但编译器也接受现在的写法,试图对一个字符串常量做变更和写入会导致出错。

赋值一样的字符串?

//学习了字符串函数后 可以重新开辟一个新的字符串并且使它等于title

如何修改字符串:用数组定义

//所以如果想要修改字符串,应该用数组定义

char s[]="Hello World!";

这样定义的内部过程是这样:在内存中给数组开辟空间之后,把只读部分的那个字符串拷贝到数组内。于是就可以修改其值

char s[] = "Hello World";
 
s[0] = 'B';
printf(s[0] = %c\n, s[0]);

这样就完成了之前做不到的事情。

二者的区别

我们在定义字符串时,到底用指针还是数组呢?

char *str = "Hello";

char s[] = "Hello";
  • 1. 指针:(不知道这个字符串在哪)只想定义一个常量;用来表达函数参数,因为数组用来做函数参数时候和指针是一样的;分配动态空间malloc;【不可写】

  • 2. 数组:字符串就在数组所在地址,由于是本地变量所以空间在使用后会被回收【是本地变量】

  • 因此想要构造一个字符串,用数组;想要处理一个字符串,用指针。

思考:char*

  1. 字符串可以表达为char *

  1. char* 不一定是字符串

  1. char * 表达这里有一个指针,指针指向一个字节or一串连续的字节,但不一定是字符串

  1. 可能指向单个,可能指向数组

  1. 只有char* 所指的字符数组有结尾的0 ——char* 所指的是个字符串

10.1.3字符串的输入输出

对于字符、整型数据等我们可以用scanf、printf等通过格式化字符进行输入输出,那么对于字符串其实也有特殊字符,%s

输入scanf(什么时候为止)

  • scanf不接收空格、回车、Tab等,会将其视为输入终止。

  • scanf读入单词到空格、回车、制表符\t为止。

//因此当用户输入 Hello World(两个单词中间有空格),输出结果是Hello

char string[8];
scanf("%s",string);//字符串不需要用& 直接指向第一个地址string[0]
printf("%s##\n",string);
~~~~~~~~~~~~~~~~~~~~~~
char word1[8];
char word2[8];
 
scanf("%s",word1);
scanf("%s",word2);
 
printf("%s##%s##\n",word1,word2);

容易溢出的scanf

  • scanf是不安全的读入

  • 因为不知道要读入的内容长度。比如在上方的代码运行时输入:

  • 12345678(回车)12345678(回车)

  • 此时根据版本的不同,可能会报错。根本原因是字符串虽然开了长度8的空间,但最后一位被0占据,因此最多只能接收7个字符。

  • 想要安全输入

  • 需要在scanf("%s",word1);的%s前面加上一位数字且这个数字要比数组长度小1

char word1[8];
scanf("%7s",word1)
//在这种情况下,如果输入超过7个字符,剩下的会被下一个数组接收。此时不是通过空格等分割。

常见错误

  • 把char* string当作字符串。

  • //实际上这只是定义了一个指针变量,要指向的东西还不知道在哪。如果没有进行初始化,不一定会报错,这次运行也许通过了,下次就不一定了。。

  • 使用指针定义字符串的时候,需要初始化,使它指向一个明确的地址

  • 空字符串

  • char string[100]=""; //空字符串(有效的) char string[0]=‘\0’

  • char string[]=""; //这个数组实际上是没用的(无效的),0占据了第一位,因此它的长度是1这里面放不下任何其他字符。

10.1.4 字符串数组

一个数组内包含多个字符串

  • char **a

  • a是一个指针,指向另一个指针,另一个指针指向一个字符/字符串。

  • char [] []

  • 二维数组 ,然而二维数组的第二维必须要有明确的大小

  • 如a[][10],相当于a[ ]是一个数组,数组a[ ]的每一个单元都是char[10],如a[0] = char [10]然而每个数组内的字符长度不能超过10。

  • 若超过10,编译器报错

  • char *a[] , 此时的a[0] 是个指针 相当于 char*(外面某处)

ex曾经的switch case 改进:

//我们可以用数组下标代替月份的数字,在其中包含具体的字符串

#include <stdio.h>
 
int main()
{
    int m;
    char *a[] = { 
        "January",
        "Febrary",
        "March",
        "Aprial",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December",
    };
    
    scanf("%d", &m);
    
    printf("%s\n", a[m - 1]);
    
    return 0;
}

另一个应用:main的参数(底层)

  • 之前都是直接int mian( )

  • 后来建议 int main(void) //在C语言中,对主函数的参数和返回类型检查并不严格,当不需要命令行参数时,就可以将参数列表设置为void。

  • 现在:

main函数称为主函数,是C语言约定的程序执行入口
其标准的定义格式为: int main(int argc, char *argv[]);
其中,参数的含义为
argc: 执行程序时输入的参数个数,包括可执行程序文件名。
argv:前argc个元素(argv[0]到argv[argc-1]),分别为执行程序时的各项参数值,以字符串方式表达。第argc+1个参数(argv[argc])值为NULL。
返回值为int型,会将返回的值回传给主调进程。
在C语言中,对主函数的参数和返回类型检查并不严格,当不需要命令行参数时,就可以将参数列表设置为void。类似的,如果不需要返回信息给主调进程,返回值也可以设定为void类型。
main函数的参数,也可以看到字符串数组
int main(int argc,char const *argv[])

这个数组多大呢?我们需要另一个参数来告诉我们

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

//程序会将你在命令行输入的东西保存到这个数组中,且argv[0]保存的是命令符,起一个快捷方式的作用。

Guess you like

Origin blog.csdn.net/Shmily_as33/article/details/129497672