字符串输入输出问题和几种常见函数(不全找我)

单引号括起来的一个字符被称作 char 型字面值双引号括起来的零个或多个字符则构成字符串型字面值。字符串字面值的类型实际上就是由常量字符构成的数组,,编译器在每一个字符串后面添加一个空字符('\0'),因此字符串的实际长度要比他的内容多1。

如字面值 'A' 表示的就是单独字符 A ,而字符串 "A" 代表了一个包含两个字符的字符数组,分别是字母 A 和空字符。

一.常见功能

二.字符串的定义

使用标准库类型 string 声明并初始化一个字符串,需要包含头文件 string。可以初始化的方式如下:

    string s1;    // 初始化一个空字符串
    string s2 = s1;   // 初始化s2,并用s1初始化
    string s3(s2);    // 作用同上
    string s4 = "hello world";   // 用 "hello world" 初始化 s4,除了最后的空字符外其他都拷贝到s4中
    string s5("hello world");    // 作用同上
    string s6(6,'a');  // 初始化s6为:aaaaaa
    string s7(s6, 3);  // s7 是从 s6 的下标 3 开始的字符拷贝
    string s8(s6, pos, len);  // s7 是从 s6 的下标 pos 开始的 len 个字符的拷贝

使用 = 的是拷贝初始化,使用 () 的是直接初始化。当初始值只有一个时,两者都可。当初始值有多个时一般来说要使用直接初始化,如上述最后一个的形式。

三.字符串输入输出问题

1、cin 使用空白字符作为一次输入的结尾,并忽略该空字符。
int main(void)
{
    char line[10];
    cout << "input what you want:";
    cin >> line;  // 可以尝试输入 "123 456"
    cout << "what you input is:" << line << endl;  // 只能输出 "123"
    return 0;
}
/* 测试用例
input what you want:123 456
what you input is:123
*/

也就是说,这种情况下一次只能完成一个单词的输入,其后的单词都会被忽略掉。

2、使用 getline() / get() 函数完成面向行的输入

getline() / get() 函数都可以接收一行字符串输入,并以回车作为输入的结尾。区别就是 getline 会在输入结束后丢弃最后的换行符,而 get 则会在输入队列中保留最后的换行符。

1)cin.getline()

可以通过 cin.getline(line, nums, (optional)delim) 实现调用:从输入队列中获取 nums-1 个字符到 line 中,因为字符串的最后一个字符是 '\0'。如果输入的长度超出 nums-1 个,则 getline 和 get 将把余下的字符留在输入队列中,另外 getline 还会设置失效位,并关闭后面的输入(即后面的所有输入将不可用),此时可以用 cin.clear() 清除标准位就可以恢复后面的输入。

这种句点表示法表明,函数 getline() 是 istream 类的一个方法。另外需要注意的是 cin 是一个 istream 对象。cin.getline() 的第一个参数是目标数组,第二个参数是数组长度,这样来避免超越数组的边界。后面介绍通过输入对 string 赋值的时候调用方式会有区别。

cin.getline(line, nums)

int main(void)
{
    char line1[10];
    char line2[10];
    char line3[10];
    cout << "input what you want:" << endl;
    cin.getline(line1, 10);  // 可以尝试输入 "123 456 789" ('\n') 含有11个字符
    // cin.clear();
    cin.getline(line2, 10);  // 不可用,直接退出
    cin.getline(line3, 10);  // 不可用,直接退出
    cout << "what you input is:" << endl;
    cout << "line1:" << line1 << endl;  // 输出 "123 456 7"
    cout << "line2:" << line2 << endl;  // 输出 空
    cout << "line3:" << line3 << endl;  // 输出 空
    return 0;
}
/*
input what you want:
123 456 789
what you input is:
line1:123 456 7
line2:
line3:
*/
 
 
// 使用 clear
int main(void)
{
    char line1[10];
    char line2[10];
    char line3[10];
    cout << "input what you want:" << endl;
    cin.getline(line1, 10);  // 可以尝试输入 "123 456 789" ('\n') 含有11个字符
    cin.clear();   // 清除标志位
    cin.getline(line2, 10);  // 可用,输出 "89",这是上一步输入队列中的字符
    cin.getline(line3, 10);  // 可用,你输入啥输出啥
    cout << "what you input is:" << endl;
    cout << "line1:" << line1 << endl;  // 输出 "123 456 7"
    cout << "line2:" << line2 << endl;  // 输出 空
    cout << "line3:" << line3 << endl;  // 输出 空
    return 0;
}
/*
input what you want:
123 456 789
123
what you input is:
line1:123 456 7
line2:89
line3:123
*/

cin.getline 还有第三个参数 delim(全称应该是 delimiter,中文意思:定界符/分隔符),作用是指定用作分界符的字符(没有这个参数的版本将以换行符为分界符)。

遇到分界符后,当前字符串的输入将停止,即使还未读取最大数目的字符。因此在默认情况下,这种分界符的方式或者到达输入的指定数目都将停止读取输入。和默认情况一样 get() 将分界符留在输入队列中,而 getline() 不保留。

cin.getline(line, nums, delim),也就是以 delim 指定的字符作为一次字符串输入的结束,其后的在 nums-1 范围内的输入会保留在输入队列中作为下一个字符串的开始。

int main(void)
{
    char line1[10];
    char line2[10];
    cout << "input what you want:" << endl;
    cin.getline(line1, 10, 's');  // 可以尝试输入 "123s456" ('\n')
    cin.getline(line2, 10);  // 
    cout << "what you input is:" << endl;
    cout << "line1:" << line1 << endl;  // 输出 "123"
    cout << "line2:" << line2 << endl;  // 输出 "456"
    return 0;
}
/* 测试用例
input what you want:
123s456
what you input is:
line1:123
line2:456
*/

getline 函数每次读取一行,它通过换行符来确定行尾,但不保存换行符。相反,在存储字符串时他用空字符 '\0' 来替换换行符。

2)cin.get()

调用方式类似 getline,即cin.get(line, nums, (optional)delim)

前面说过,get 函数会在输入队列中保留最后的换行符。注意是输入队列,也就是在一个 get()

函数完成输入后,会在输入缓存中保留组后的换行符,如果不做处理在下次运行 get() 时会出问题。

int main(void)
{
    char line1[10];
    char line2[10];
    cout << "input what you want:" << endl;
    cin.get(line1, 10);  // 可以尝试输入 "123" ('\n'), 此时回车符将会留在输入队列中
    cin.get(line2, 10);  // 可以尝试输入 "456",可以发现 line1 输入完后,这步直接被“跳过了”
    cout << "line1:" << line1 << endl;  // 输出 "123"
    cout << "line2:" << line2 << endl;  // 输出空字符,由于 cin.get(line2, 10); 读入的是上一个字符输入结束时留输入队列中的回车符
    return 0;
}
 
/* 测试用例
input what you want:
123
what you input is:
line1:123
line2:
*/

由于第一次调用后换行符留在了输入队列中,因此第二次看到第一个字符便是换行符,因此就直接结束了。如果不借助与任何帮助,get() 将不能跨过该换行符(在多个get的情况下)。可以使用下面这种方式避免这种情况:

cin.get(line2, 10).get();
\\ 或者
cin.get(line2, 10);
get();
3、数字与字符串的混合输入问题

使用 cin 输入一个整数后,最后的回车符会留在输入队列中,类似于get,这会对后续的 getline 和 get 输入产生影响,因为 getline / get 看到换行符后会认为是一个空行,然后会把空字符赋给后面的字符串,如下:

int main(void)
{
    int a, b;  // 输入 123 ('\n') 456 ('\n')
    char s[5];
    cin >> a;
    cin >> b;
    cin.getline(s, 5); // 得到换行符,直接赋空值
    cout << a << " " << b << " " << s << endl;
}
/* 测试用例
123
456
123 456 
*/

此时可以使用在后面添加 cin.get() 或者 (cin >> b).get() 的方式来解决这个问题:

​
int main(void)
{
    int a, b;  // 输入 123 ('\n') 456 ('\n')
    char s[7];
    cin >> a;
    // cin >> b;
    // cin.get();    
    (cin >> b).get();
    cin.getline(s, 7); // 输入 "string" ('\n')
    cout << a << " " << b << " " << s << endl;
}
/* 测试用例
123
456
string
123 456 string
*/

4.对 string 对象的输入方法

使用 cin<<str 的语法来将输入存储到 string 对象中与字符数组的操作是一样的。不同的是当每次读取一行而不是一个单词时使用的语法是不同的。

int main(void)
{
    string str;
    cout << "input what you want:" << endl;
    getline(cin, str);
    cout << "what you input is:" << endl;
    cout << str << endl;
}
/* 测试用例
input what you want:
123 456 789
what you input is:
123 456 789
*/

注意这里的面向行的输入是 getline(cin, str)

这里没有使用句点表示法,这表明这个 getline 不是类方法。他将 cin 作为参数,指出到哪里去查找输入。另外也没有指出字符串长度的参数,因为 string 对象将根据字符串的长度自动调整自己的大小。

至于为什么字符数组和string对象的 getline 方法不一样呢,其实这是个历史问题。早期的 C++ 还没引入 string 类的时候就有 istream 类了,因此当时也就没有针对 string 对象的输入方式了,所以最后才会演变出这两种方式。

四.拼接、比较、修改、反转操作

s1+s2          // 返回 s1 和 s2 拼接后的结果。加号两边至少有一个 string 对象,不能都是字面值
s1 == s2       // 如果 s1 和 s2 中的元素完全相等则它们相等,区分大小写
s1 != s2
<, <=, >, >=   // 利用字符的字典序进行比较,区分大小写

在 pos 之前插入 args 指定的字符。pos是一个下标或者迭代器。接受下标的版本返回一个指向 s 的引用;接受迭代器的版本返回一个指向第一个插入字符的迭代器 。

s.insert(pos, args)  
// 在 s 的位置 0 之前插入 s2 的拷贝
s.insert(0, s2)  

删除从 pos 开始的 len 个字符。如果 len 省略,则删除 pos 开始的后面所有字符。返回一个指向 s 的引用。

s.erase(pos, len)  

将 s 中的字符替换为 args 指定的字符。返回一个指向 s 的引用。

s.assign(args)  

将 args 追加到 s 。返回一个指向 s 的引用。args 不能是单引号字符,若是单个字符则必须用双引号表示。如,可以是 s.append("A") 但不能是 s.append('A')    

s.append(args)  

将 s 中范围为 range 内的字符替换为 args 指定的字符。range 或者是一个下标或长度,或者是一对指向 s 的迭代器。返回一个指向 s 的引用。

s.replace(range, args) 
// 从位置 3 开始,删除 6 个字符,并插入 "aaa".删除插入的字符数量不必相等
s.replace(3, 6, "aaa")  

使用 <algorithm> 头文件中的 reverse() 方法:

    string s2 = "12345";    // 初始化一个字符串
    reverse(s2.begin(), s2.end()); // 反转 string 定义的字符串 s2 
    cout << s2 << endl; // 输出 54321

五.find函数

1.正向查找

1.1 s.find(str)

string中find()返回值是字母在母串中的下标位置。
如果没有找到,那么会返回一个特别的标记npos,一般写作string::npos

string s, c;
int main() {
  s = "apple";
  c = "l";
  int index = s.find(c);
  if (index != string::npos)
    cout << index << endl;
}

 输出:

3
1.2 s.find(str,pos)

find(str,pos)是用来寻找从pos开始(包括pos处字符)匹配str的位置。

string s, c;
int main() {
  s = "laaaal";
  c = "l";
  int index = s.find(c,3);//从字符串s下标3的位置开始寻找
  if (index != string::npos)
  cout << index << endl;
}

上述等价于从字符串"aal"开始找"l",省略第一个"l"。
输出结果:

5
1.4查找目标字符串在字符串出现的总次数

核心代码:index=s.find(c,index),index每次都会更新下一次找到的位置,如果没有找到跳出循环。

string s, c;

int main() {
  while (cin >> s >> c) {
    int index = 0;//用来存储不断更新最新找到的位置
    int sum = 0;//累加出现的次数
    while ((index = s.find(c,index)) != string::npos) {
      cout << "sum: " << sum+1 << " index: " << index <<endl;
      index += c.length();//上一次s中与c完全匹配的字符应跳过,不再比较
      sum++;
    }
    cout << sum << endl;
  }
}
llllll
ll
sum: 1 index: 0
sum: 2 index: 2
sum: 3 index: 4
3

2.逆向查找rfind()

s.rfind(str): 是从字符串右侧开始匹配str,并返回在字符串中的下标位置

string s = "apple";
cout << s.rfind("l") << endl;

这时结果是否还是跟find()查找一样,输出结果是3呢?让我们往下看。
结果显示:

3
  • rfind(str,pos): 从pos开始,向前查找符合条件的字符串。

 六.常用函数

1.strlen函数

原型:size_t strlen(char* str)

头文件 #include<string.h>

作用:测量字符串str的长度,返回str的长度(数值)

#include<stdio.h>
#include<string.h>
int main()
{
	char str[] = "Welcom!";
	int a=strlen(str);
	printf("%d",a);
}
//输出结果为7

2.strcpy函数

原型: char *strcpy(char* strA,const char *strB)

头文件 #include<string.h>

作用:把字符串strB复制到字符串strA中,返回字符串strA

前提条件:字符串strA要足够大,足以容纳字符串strB(例如strA[100],strB[50],strA的字符容纳量大于strB),否则就会溢出错误。

#include<stdio.h>
#include<string.h>
int main()
{
	char strA[20];
	char strB[15] = "I LOVE YOU";
	strcpy(strA, strB);
	puts(strA);
}

 3.strncpy函数

原型 :char* strncpy(char *strA,char *strB,int *n)

头文件:#include<string.h>

作用:把字符串strB前n个字符复制(拷贝)到字符串strA,返回strA

注意事项:strA的容纳量要比n大,字符串strB的容纳量也要大于n,否则会出现溢出错误。

#include<stdio.h>
#include<string.h>
int main()
{
	char strA[20];//char strA[20]={0};
	char strB[] = "computer";
	strncpy(strA, strB,4);
	strA[4] = '\0';//此时strA是没有终止符的,所以要在strA[4]加上'\0'终止,否则会出现乱码
//或者可以对strA进行初始化
	puts(strA);
	return 0;
}

输出:

comp

4.strcat函数

原型:char* strcat(char* strA,char* strB)

头文件:#include<string.h>

作用:把字符串strB拼接到字符串strA末尾(例如:char strA[20]="CHINA",strB[]="Chinese",strcat(char strA,char strB),返回的结果是 CHINAChinese)

注意事项: 函数的返回值是strA,其总长度是原来strA与strB的总长度,所以要对strA进行字符容纳设定,其可容纳字符必须大于strA与strB字符串的字符数总量。

#include<stdio.h>
#include<string.h>
int main()
{
	char strA[50] ="Chin";//要对strA进行容纳字符数设定
	char strB[] = "ese";
	strcat(strA, strB);
	puts(strA);
	return 0;
}

输出:

Chinese

5.strncat函数

原型:char* strncat(char* strA,char* strB,int n)

头文件:#include<string.h>

作用:把字符串strB的前n个字符拼接到字符串strA的末尾。

注意事项: 函数的返回值是strA,其总长度是原来strA与strB前n个字符的总长度,所以要对strA进行字符容纳设定,其可容纳字符必须大于strA与字符串trB前n个字符的字符数总量。

#include<stdio.h>
#include<string.h>
int main()
{
	char strA[20] ="hello";
	char strB[] = "world";
	strncat(strA, strB,3);
	puts(strA);
	return 0;
}

 输出:

hellowor

6.strcmp函数

原型:int strcmp(char* strA,const char* strB)

头文件:#include<string.h>

作用:对字符串strA与字符串strB进行每一个字符的阿斯克码比较,直到出现不同的字符,或者到达字符串strB的末尾(即‘\0’)。

返回值:当遇到不同的字符时,如果strA此字符的阿斯克码大于strB此字符的阿斯克码,返回值是1,反之-1;如果strA与strB相等返回值即0。

//示例1:
//由于w的阿斯克码大于l,返回-1
#include<stdio.h>
#include<string.h>
int main()
{
	char strA[] ="hello";
	char strB[] = "hewl";
	int a = strcmp(strA, strB);
	printf("%d", a);
	return 0;
}
 
//示例2
//用户输入两个字符串,进行比较,如果不同那么输出no,如果相同输出yes
#include<stdio.h>
#include<string.h>
int main()
{
	char strA[20];
	char strB[20];
	gets(strA);//输入之后要回车
	gets(strB);
	if (strcmp(strA, strB) == 0)
		printf("yes");
	else
		printf("no");
	return 0;
}

7.strncmp函数

原型:int strncmp(char* strA,const char* strB,int n)

头文件:#include<string.h>

作用:将strA与strB的前n个字符进行比较,返回原理同上。

//示例:
//用户自行输入两个字符串,将第二个字符串的前n个与第一个字符串进行比较,如果相同那么输出yue,否则输出no
 
#include<stdio.h>
#include<string.h>
int main()
{
	char strA[20];
	char strB[20];
	int n;
	gets(strA);//输入完后要回车
	gets(strB);//输入完后要回车
	scanf("%d", &n);//输入一个数字n,作用表示strB的前n个字符
	if (strncmp(strA, strB,n) == 0)
		printf("yes");
	else
		printf("no");
	return 0;
}

输出:

hello
hell
4
yes

 8.strchr函数

原型:char* strchar(const char* str ,int a)

头文件:#include<string.h>

作用:在字符串str查找字符a。strchr函数会检索str的每一个字符,如果找到a就返回a首次出现的位置,反正返回NULL。可以应用到字符检索,查找字符。

//示例1
#include<stdio.h>
#include<string.h>
int main()
{
	char str[]="Thank you for reading";
	char a;
	scanf("%c", &a);
	printf("%x", strchr(str, a));//返回的是a在str首次出现的位置,以十六进制数输出
	return 0;
}
 
 
//示例2
//用户输入一个字符串和一个字符,检测这个字符在该字符串是否出现
#include<stdio.h>
#include<string.h>
int main()
{
	char str[100];
	char a;
	int k = 0;
	gets(str);//要回车换行
	scanf("%c", &a);
	if (strchr(str, a))
		printf("yes");
	else
		printf("no");
 
	return 0;
}

 完结撒花!!!

  • 29
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值