C++ 字符串输入问题

C++ 字符串输入问题,第1张

目录

一、对字符数组的输入方法(char str[N]):

1、cin 使用空白字符作为一次输入的结尾,并忽略该空字符。

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

3、数字与字符串的混合输入问题

二、对 string 对象的输入方法


C++中常用的输入方式为 cin 。通过 cin 来获取字符串是常用的 *** 作,但是字符串中往往可能会包含空格等空白字符,而在一般的输入场景中,由于不能通过键盘输入字符 '\0'(在存储中,字符串都以空字符 '\0' 结尾),因此 cin 使用空白字符(空格、制表符和换行符)来确定字符串的结束位置,因此想要输入空格必须得修改输入的方式。

一、对字符数组的输入方法(char str[N]): 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;  // 输出 "ss"
    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
    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
    char s[7];
    cin >> a;
    // cin >> b;
    // cin.get();    
    (cin >> b).get();
    cin.getline(s, 7); // 得到换行符,直接赋空值
    cout << a << " " << b << " " << s << endl;
}
/* 测试用例
123
456
string
123 456 string
*/
二、对 string 对象的输入方法

使用 cin<

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 对象的输入方式了,所以最后才会演变出这两种方式。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1329890.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-12
下一篇 2022-06-12

发表评论

登录后才能评论

评论列表(0条)

保存