04-2.C(字符串和函数)

简介: 01.scanf1)scanf将回车空格都当作字符串结束的标志2)以回车键作为输入完成的标识,但是回车键本身不会作为字符串的一部分3)存在安全问题,加入用户在键盘输入的内容超过scanf参数中的数组长度,就会内存溢出,发生奔溃,这也就是微软在使用...

01.scanf

1)scanf将回车空格都当作字符串结束的标志
2)以回车键作为输入完成的标识,但是回车键本身不会作为字符串的一部分
3)存在安全问题,加入用户在键盘输入的内容超过scanf参数中的数组长度,就会内存溢出,发生奔溃,这也就是微软在使用scanf函数时需要加上顶部#define


#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main() {
    char buf[100] = { 0 };
    printf("请输入字符串buf:");
    scanf("%s",buf);
    printf("buf=%s\n", buf);

    char temp[100] = { 0 };
    printf("请输入字符串temp:");
    scanf("%s", temp);
    printf("buf=%s\n", temp);

    //scanf不做越界检查,所以是不安全的,
    //如果输入的数量超过了数组长度,就会发生异常
    char str[10] = { 0 };
    printf("请输入字符串str:");
    scanf("%s", str);
    printf("buf=%s\n", str);

    system("pause");
}

控制台:

请输入字符串buf:hello
buf=hello
请输入字符串temp:world
buf=world
请输入字符串str:haha
buf=haha
请按任意键继续. . .

加入我这样输入,一次性输入三个单词,以空格隔开,看打印的情况,

请输入字符串buf:hello world haha
buf=hello
请输入字符串temp:buf=world
请输入字符串str:buf=haha
请按任意键继续. . .

我们可以分析一下scanf的工作原理,在键盘上输入hello world haha
回车之后,会将hello world haha\n放入缓冲区(内存),这时运行
到scanf函数的时候,会去缓冲区中检查,看有没有输入的内容,如
果没有则等待输入,如果有,则取出一个,以空格为标识,取出了
第一个hello,然后第二个scanf同样道理,取出第二个单词world,第
三个取出最后一个

sscanf(按照指定的格式提取内容)

scanf可以理解为按照指定格式(以空格分隔的格式),从标准输入中提取内容,那么sscanf就是按照指定格式(不再局限于空格分隔),从指定的内容中,一般是字符串中,提取内容,可以看到下面的程序最后一次提取是没有成功的,提取字符串用逗号分割会有问题,用空格可以,提取整型数据用逗号可以实现,用空格也可以实现


#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main() {
    char buf[] = "1 2 3";
    int a, b, c;
    //从buf中指定的格式提取内容
    sscanf(buf, "%d %d %d", &a, &b, &c);
    printf("a = %d,b=%d,c=%d",a, b, c);
    printf("\n---------------------------------------------\n");
    //提取整型变量是最方便的
    char str[] = "a=1,b=2,c=3";
    a = 0;
    b = 0;
    c = 0;
    sscanf(str, "a=%d,b=%d,c=%d", &a, &b, &c);
    printf("a = %d,b=%d,c=%d", a, b, c);
    printf("\n---------------------------------------------\n");
    char str2[] = "1;2;3";
    a = 0;
    b = 0;
    c = 0;
    sscanf(str2, "%d;%d;%d", &a, &b, &c);
    printf("a = %d,b=%d,c=%d", a, b, c);
    printf("\n---------------------------------------------\n");
    char temp[] = "abc ren 434";
    char m[10], n[10], o[10];
    sscanf(temp, "%s %s %s", m, n, o);
    printf("m = %s,n=%s,o=%s", m, n, o);
    printf("\n---------------------------------------------\n");
    char temp2[] = "abc,ren,434";
    char m2[10], n2[10], o2[10];
    sscanf(temp2, "%s,%s,%s", m2, n2, o2);
    printf("m = %s,n=%s,o=%s", m2, n2, o2);
    system("pause");
}

打印:
a = 1,b=2,c=3
---------------------------------------------
a = 1,b=2,c=3
---------------------------------------------
a = 1,b=2,c=3
---------------------------------------------
m = abc,n=ren,o=434
---------------------------------------------
m = abc,ren,434,n=烫烫烫烫烫烫烫烫烫烫abc,ren,434,o=烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫abc,ren,434请按任意键继续. . .

02.gets(已经不建议使用了)

#include <stdio.h>
char *gets(char *s)

从标准输入读取字符,并保存到s(一般是个数组,s是数组首地址)指定的内存空间,知道出现换行符或读取到文件结尾为止,和scanf不同之处,在于可以读取空格,有数组越界的风险,比如输入的大于数组的极限

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main() {
    char buf[10];
    gets(buf);
    printf("%s\n", buf);
    system("pause");
}

02.fgets(可以指定读取的大小,是安全的)

#include <stdio.h>
char *fgets(char *s,int size,FILE *stream);

从stream指定的文件流读入字符,保存到s所指定的内存空间,直到出现换行符都到文件结尾或是已读了size-1个字符为止,最后会自动加上字符'\0'作为字符串结束标志

#include <stdio.h>

int main() {
    char buf[10];
        //从stdin,也就是键盘输入流读取内容,如果输入内容大
        //于sizeof(buf)-1,只读取sizeof(buf),注意它会把换行            符也读
        //进去
    fgets(buf, sizeof(buf), stdin);
    printf("buf = %s\n", buf);
    system("pause");
}
打印:
abcdefghijklmn
buf = abcdefghi
请按任意键继续. . .

03.puts(字符串输出到屏幕,类似printf)

include <stdio.h>
int puts(const char *)

标准设备输出字符串,在输出完成后,自动输出一个'\n',换行,注意字符串本身没有变化

#include <stdio.h>

int main() {
    char buf[] = "hello";
    //打印字符串buf,可以证明这个字符串本身是没有换行的
    printf("buf = %s", buf);
    //把buf内容输出到屏幕,自动在屏幕加换行,在屏幕加,字符串本身没变化
    puts(buf);
    //再次打印字符串,证明字符串本身没有变化
    printf("buf = %s", buf);
    system("pause");
}
打印
buf = hellohello
buf = hello请按任意键继续. . .

04.fputs(是puts的文件操作版本,但不会输出换行)

#include <stdio.h>
int fputs(const char *str,FILE *stream)

把指定内容输出到一个文件流中,puts是输出到屏幕,和puts区别在于它可以指定输出到哪个文件流,这个文件流也包括屏幕,只要将stream指定为stdout即可,并且不会在输出内容上加换行符

#include <stdio.h>

int main() {
    char buf[] = "hello";
    fputs(buf, stdout);
    system("pause");
}
输出:
hello请按任意键继续. . .(没有换行)

05.strlen

#include<string.h>
size_t strlen (const char *s)

计算指定字符串s的长度,不包含字符串结束符'\0'(size_t为unsigned int 类型)

#include <stdio.h>
#include <string.h>

int main() {
    char buf[] = "hello";
    //strlen是从首元素开始,到结束符为止的长度,结束符不算
    //到\0为止,所以如果手动加上了\0,比如he\0llo的strlen结果就是2
    int len = strlen(buf);
    printf("len = %d\n",len);
    printf("sizeof(buf) = %d\n", sizeof(buf));

    char buf2[] = "\0hello";
    len = strlen(buf2);
    printf("len2 = %d\n", len);
    //sizeof测量的是数据类型的长度,不会因为结束符而提前结束,他的计算结果
    //包括结束符,所以buf2的sizeof结果是7,因为最后还有一个结束符
    printf("sizeof(buf2) = %d\n", sizeof(buf2));
    system("pause");
}
打印:
len = 5
sizeof(buf) = 6
len2 = 0
sizeof(buf2) = 7
请按任意键继续. . .

6.strcpy

#include <string.h>
char *strcpy (char *dest,const char *src);

把src所指向的字符串复制到dest所指向的空间中,'\0也会拷贝过去',成功则返回dest字符的首地址,如果dest的空间不够大可能会溢出,当它复制的时候会从首地址开始,到\0结束,所以第二个打印只有一个hello输出

//因为不是安全的,所以要加上这个
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main() {
    char src[100] = "hello world";
    char dest[100];
    strcpy(dest,src);
    printf("dest = %s\n", dest);

    char src2[100] = "hello\0 world";
    char dest2[100];
    strcpy(dest2, src2);
    printf("dest2 = %s\n", dest2);
    system("pause");
}

打印
dest = hello world
dest2 = hello
请按任意键继续. . .

7.strncpy(没有溢出的隐患,安全)

这个也会以\0结束,

#include <stdio.h>
#include <string.h>

int main() {
    char src[100] = "hello world";
    char dest[100];
        //拷贝一个字符到dest
    strncpy(dest,src,1);
    printf("dest = %s\n", dest);
    system("pause");
}

strcmp

#include <string.h>
char *strcmp(const char *s1,const char *s2);

比较s1和s2的大小,比较的是字符ASCII码大小,0表示相等,>0表示大于,小于0表示小于

#include <stdio.h>
#include <string.h>

int main() {
    char s1[] = "abc";
    char s2[] = "abcd";
    int flag = strcmp(s1, s2);
    if (flag == 0) {
        printf("相等");
    }
    else if (flag > 0)
    {
        printf("s1 > s2");

    }
    else if (flag < 0)
    {
        printf("s1 < s2");

    }
    system("pause");
}

打印结果:s1<s2

strcnmp (可以指定比较的字符范围)

#include <stdio.h>
#include <string.h>

int main() {
    char s1[] = "abc";
    char s2[] = "abcdef";
    int flag = strncmp(s1, s2,3);
    if (flag == 0) {
        printf("相等");
    }
    else if (flag > 0)
    {
        printf("s1 > s2");

    }
    else if (flag < 0)
    {
        printf("s1 < s2");

    }
    system("pause");
}

打印结果:相等

strcat 字符串追加

#define _CRT_SECURE_NO_WARNINGS  //不安全
#include <stdio.h>
#include <string.h>

int main() {
    char s1[] = "abc";
    char s2[] = " defg";
    strcat(s1, s2);
    printf("%s\n",s1);
    system("pause");
}

abc defg
请按任意键继续. . .

strncat 指定追加字符串的长度(也是不安全的,strncat_s是安全的)

严重性 代码 说明 项目 文件 行 禁止显示状态
错误 C4996 'strncat': This function or variable may be unsafe. Consider using strncat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 函数 c:\users\renzhenming\documents\visual studio 2015\projects\函数\函数\1.c 9

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main() {
    char s1[] = "abc";
    char s2[] = " defg";
    strncat(s1, s2,strlen(" def"));
    printf("%s\n",s1);
    system("pause");
}

打印:abc def

sprintf 格式化字符串

严重性 代码 说明 项目 文件 行 禁止显示状态
错误 C4996 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 函数 c:\users\renzhenming\documents\visual studio 2015\projects\函数\函数\1.c 16


#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main() {
    int a = 10;
    char c = 'd';
    char buf[] = "hello";

    //格式化一个字符串,把这个字符串输出到屏幕
    printf("a = %d, ch = %c , buf = %s \n",a,c,buf);

    //格式化一个字符串,把这个字符串保存到指定的数组
    char dest[100];
    sprintf(dest, "a = %d, ch = %c , buf = %s \n", a, c, buf);

    printf("%s\n",dest);
        system("pause");
}


a = 10, ch = d , buf = hello
a = 10, ch = d , buf = hello

请按任意键继续. . .

strchr(在字符串s中查找字母c出现的位置)

#include <string.h>
char *strchr(const char *s ,int c);
#include <stdio.h>
#include <string.h>

int main() {
    char buf[] = "abddddeee";
    //在buf中查询字符d,如果找到,返回d所在位置的地址,如果打印p
    //将得到从d所在位置开始到字符串结束的那个字符串
    char *p = strchr(buf, 'e');
    if (p == NULL) {
        printf("查询失败\n");
    }
    else {
        printf("p = %s\n",p);
    }
    system("pause");
}

strstr(在字符串haystack中查找needle出现的位置)

#include<string.h>
char *strstr(const char *haystack,const char *needle);
#include <stdio.h>
#include <string.h>

int main() {
    char buf[] = "abddddeee";
    //在buf中查询字符串,如果找到,返回d所在位置的地址,如果打印p
    //将得到从d所在位置开始到字符串结束的那个字符串
    char *p = strstr(buf, 'de');
    if (p == NULL) {
        printf("查询失败\n");
    }
    else {
        printf("p = %s\n",p);
    }
    system("pause");
}

strtok字符串切割

#include <string.h>
char *strtok(char *str ,const char *delim)

用来将字符串切割成一个个片段,当strtok再参数s的字符串中发现参数delim中包含的分割字符时,则会将该字符改为\0字符,当连续出现多个时只替换第一个\0,这个函数是不安全的要加声明

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main() {
    char buf[] = "hello,world,tomorrow";
    //第一次调用,第一个参数写源字符串,第二个参数写切割字符
    //返回值就是切割后的字符串,在匹配切割字符的地方,换成结束符,
    char *p = strtok(buf,",");
    printf("p=%s\n", p);
    //使用strtok会破环原来的字符串结构,这时打印字符串得到的是切割后的
    printf("buf=%s\n", buf);
    printf("buf[5]=%d\n", buf[5]);
    system("pause");
}

p=hello
buf=hello
buf[5]=0
请按任意键继续. .

第二次切割

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main() {
    char buf[] = "hello,world,tomorrow";
    //如果没有切割成功,返回NULL
    char *p = strtok(buf,",");
    printf("p1=%s\n", p);
    //第二次调用,第一个参数写NULL
    p = strtok(NULL, ",");
    printf("p2=%s\n", p);
    system("pause");
}

循环切割

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main() {
    char buf[] = "hello,world,tomorrow";
    //如果没有切割成功,返回NULL
    char *p = strtok(buf,",");
    while (p != NULL) {
        printf("p = %s\n", p);
        p = strtok(NULL, ",");
    }
    system("pause");
}

atoi

#include <stdlib.h>
int atoi(const char *ch);

atoi会扫描字符串ch,跳过前面的空格符,直到遇到正负号或数字才开始做转换(转换为数字),遇到非数字或字符串结束符\0才结束转换,并将结果返回

类似的函数有:
atof:把小数形式的字符串转换为float类型
atol:把一个字符串转化为long类型

#include <stdio.h>
#include <string.h>

int main() {
    char buf[] = "-10";
    printf("num = %d\n",atoi(buf));
    system("pause");
}
相关文章
|
3月前
|
JavaScript 前端开发 API
|
2月前
操作字符串的函数
C中有大量操作字符串的函数。
15 2
|
8月前
|
Java C语言
字符串的简单介绍和字符串的大小比较
字符串的简单介绍和字符串的大小比较
|
7月前
|
Python
Python函数详解:参数、返回值和文档字符串
Python函数详解:参数、返回值和文档字符串
101 0
|
8月前
|
移动开发 Python Windows
超详细的字符串用法大全
超详细的字符串用法大全
|
10月前
|
索引
字符串方法
字符串方法
67 0
|
10月前
利用函数求字符串长度
利用函数求字符串长度
48 0
|
JavaScript 前端开发
使用字符串方法
使用字符串方法
58 0
|
移动开发
长字符串/多行字符串
长字符串/多行字符串
75 0
如何将一个字符串按要求切割成多个字符串
很少有机会碰到一些实际数据处理问题,简单记录下自己的实现 此问题具体要求: 原字符串:一二三四五 输入1:一,二,三,四,五 输入2:一二,三四,五 输入3:一二三,四五 ...
158 0