从字符串中删除常量
Removing Constants from a string
我编写了一个代码来从字符串和 return 元音中删除常量。我的代码不适用于由 space 分隔的单词数的字符串。这是我的代码:
int T;// integer T denoting the number of test cases. For each test case, we input a string.
cin>>T;
string s;
char arr[10] = {'a', 'e', 'i', 'o', 'u','A', 'E', 'I', 'O', 'U'};
for(int n = 0; n < T; n++){
cin>>s;
for(int i = 0; i < s.size(); i++){
for(int j = 0; j < 10; j++){
if(s[i] == arr[j]){cout<<s[i];}
}
if(isspace(s[i])){cout<<"n";}
}
cout<<endl;
}
输入:wdTSFuI IvfHOSNv ,
它的正确输出是:uI IO ,
我的输出是:uI
上述错误是因为通过命令行输入时 C++ 省略了 space 之后的数据,所以它只读取 space 之前的数据,这就是为什么你得到的元音只出现在上半场
克服此错误的三种方法。
- 使用 getline 读取带有 spaces 的字符串,新的更改代码是
#include <iostream>
#include <string>
using namespace std;
int main() {
int T;// integer T denoting the number of test cases. For each test case, we input a string.
cin>>T;
string s;
char arr[10] = {'a', 'e', 'i', 'o', 'u','A', 'E', 'I', 'O', 'U'};
for(int n = 0; n < T; n++){
getline(cin,s);
for(int i = 0; i < s.size(); i++){
for(int j = 0; j < 10; j++){
if(s[i] == arr[j]){
cout<<s[i];
}
}
if(isspace(s[i])){cout<<"n";}
}
cout<<endl;
}
}
使用字符数组来克服这个错误。
或提供不带 spaces 的输入。
我认为这可能会解决您的问题
当然解决办法是用std::getline
读完整行,包括spaces.
我不明白你的行 if(isspace(s[i])){cout<<"n";}
,因为在你显示的输出示例中,你想显示 spaces 而不是“n”。我想这是一个错字,应该是“ ”。
无论如何。使用 std::getline
你的函数看起来像
#include <iostream>
#include <string>
int main() {
// We need to operate on a given number of test cases
size_t numberOfTestCases{}; std::cin >> numberOfTestCases;
// Handle all test cases
while (numberOfTestCases--) {
// Read a complete line with text
std::string line{}; std::getline(std::cin, line);
// In case of space or vowel, print that
for (const char c : line)
if ((c == 32) or ((0x208222 >> (c & 0x1f)) & 1)) std::cout << c;
std::cout << '\n';
}
return 0;
}
并且因为我看到了一些带有“测试用例”的东西,我猜你正在访问这些不神圣的“竞赛编程”网站中的一些。
这就是我使用条件 ((0x208222 >> (c & 0x1f)) & 1)
来检查字符是否为元音的原因。这知道如何已有数十年历史。对于此类网站来说已经足够了。
如果有人对它的工作原理感兴趣,请发表评论,我会编辑答案并进行解释。
编辑
应要求,我将解释 for 循环。首先,我们有一个基于范围的 for 循环。与写法相同:
for (int i=0; i < line.length(); ++i) {
const char c = line[i];
. . .
}
然后你可以看到,我们首先检查字符c是否等于32。32是space的ASCII码。你可以看到这个here.
那么,现在,如何检查一个字符是否是元音字母。
如果我们使用ASCII码对字母进行编码,那么我们会看到以下内容:
我们看到大写字母和小写字母的ASCII码只是低5位不同。
因此,如果我们用 0x1F 屏蔽 ASCII 码,那么 char c{'a'}; unsigned int x{c & 0x1F}
,我们将得到 1 到 26 之间的值。
所以,我们可以为每个字母计算一个 5 位的值。
如果我们现在用 1 标记所有元音,我们可以构建一个由 32 位(unsigned int)组成的二进制数,并在元音为真的每个位置设置一个位。然后我们得到类似
的东西
Bit position
3322 2222 2222 1111 1111 1100 0000 0000
1098 7654 3210 9876 5432 1098 7654 3210
Position with vowels:
0000 0000 0010 0000 1000 0010 0010 0010
这个数字可以转换为0x208222。
如果我们现在想知道,如果一个字母(不管是大写还是小写)是元音,那么我们屏蔽掉字符中不需要的位( C & 1F )并移动二进制数向右的位置与生成的字母代码一样多。如果该位设置在 LSB 位置,则我们有一个元音。这知道怎么有几十年了。
示例:字符 'e'。 ASCII码是101,用1F掩码就是5,然后我们把0x208222(等于0000 0000 0010 0000 1000 0010 0010 0010
)这5个位置右移,得到0000 0000 0000 0001 0000 0100 0001 0001
。最低位,带有 'e' 标记的设置。因此,它是一个元音。
啊哈。不太容易,但适用于 ASCII 编码字母。
顺便说一句,它也适用于其他选择的字符。
结果是:
auto isVowel = [](char c) { return (0x208222 >> (c & 0x1f)) & 1; };
酷。 . .
我编写了一个代码来从字符串和 return 元音中删除常量。我的代码不适用于由 space 分隔的单词数的字符串。这是我的代码:
int T;// integer T denoting the number of test cases. For each test case, we input a string.
cin>>T;
string s;
char arr[10] = {'a', 'e', 'i', 'o', 'u','A', 'E', 'I', 'O', 'U'};
for(int n = 0; n < T; n++){
cin>>s;
for(int i = 0; i < s.size(); i++){
for(int j = 0; j < 10; j++){
if(s[i] == arr[j]){cout<<s[i];}
}
if(isspace(s[i])){cout<<"n";}
}
cout<<endl;
}
输入:wdTSFuI IvfHOSNv , 它的正确输出是:uI IO , 我的输出是:uI
上述错误是因为通过命令行输入时 C++ 省略了 space 之后的数据,所以它只读取 space 之前的数据,这就是为什么你得到的元音只出现在上半场
克服此错误的三种方法。
- 使用 getline 读取带有 spaces 的字符串,新的更改代码是
#include <iostream>
#include <string>
using namespace std;
int main() {
int T;// integer T denoting the number of test cases. For each test case, we input a string.
cin>>T;
string s;
char arr[10] = {'a', 'e', 'i', 'o', 'u','A', 'E', 'I', 'O', 'U'};
for(int n = 0; n < T; n++){
getline(cin,s);
for(int i = 0; i < s.size(); i++){
for(int j = 0; j < 10; j++){
if(s[i] == arr[j]){
cout<<s[i];
}
}
if(isspace(s[i])){cout<<"n";}
}
cout<<endl;
}
}
使用字符数组来克服这个错误。
或提供不带 spaces 的输入。
我认为这可能会解决您的问题
当然解决办法是用std::getline
读完整行,包括spaces.
我不明白你的行 if(isspace(s[i])){cout<<"n";}
,因为在你显示的输出示例中,你想显示 spaces 而不是“n”。我想这是一个错字,应该是“ ”。
无论如何。使用 std::getline
你的函数看起来像
#include <iostream>
#include <string>
int main() {
// We need to operate on a given number of test cases
size_t numberOfTestCases{}; std::cin >> numberOfTestCases;
// Handle all test cases
while (numberOfTestCases--) {
// Read a complete line with text
std::string line{}; std::getline(std::cin, line);
// In case of space or vowel, print that
for (const char c : line)
if ((c == 32) or ((0x208222 >> (c & 0x1f)) & 1)) std::cout << c;
std::cout << '\n';
}
return 0;
}
并且因为我看到了一些带有“测试用例”的东西,我猜你正在访问这些不神圣的“竞赛编程”网站中的一些。
这就是我使用条件 ((0x208222 >> (c & 0x1f)) & 1)
来检查字符是否为元音的原因。这知道如何已有数十年历史。对于此类网站来说已经足够了。
如果有人对它的工作原理感兴趣,请发表评论,我会编辑答案并进行解释。
编辑
应要求,我将解释 for 循环。首先,我们有一个基于范围的 for 循环。与写法相同:
for (int i=0; i < line.length(); ++i) {
const char c = line[i];
. . .
}
然后你可以看到,我们首先检查字符c是否等于32。32是space的ASCII码。你可以看到这个here.
那么,现在,如何检查一个字符是否是元音字母。
如果我们使用ASCII码对字母进行编码,那么我们会看到以下内容:
我们看到大写字母和小写字母的ASCII码只是低5位不同。
因此,如果我们用 0x1F 屏蔽 ASCII 码,那么 char c{'a'}; unsigned int x{c & 0x1F}
,我们将得到 1 到 26 之间的值。
所以,我们可以为每个字母计算一个 5 位的值。
如果我们现在用 1 标记所有元音,我们可以构建一个由 32 位(unsigned int)组成的二进制数,并在元音为真的每个位置设置一个位。然后我们得到类似
的东西Bit position
3322 2222 2222 1111 1111 1100 0000 0000
1098 7654 3210 9876 5432 1098 7654 3210
Position with vowels:
0000 0000 0010 0000 1000 0010 0010 0010
这个数字可以转换为0x208222。
如果我们现在想知道,如果一个字母(不管是大写还是小写)是元音,那么我们屏蔽掉字符中不需要的位( C & 1F )并移动二进制数向右的位置与生成的字母代码一样多。如果该位设置在 LSB 位置,则我们有一个元音。这知道怎么有几十年了。
示例:字符 'e'。 ASCII码是101,用1F掩码就是5,然后我们把0x208222(等于0000 0000 0010 0000 1000 0010 0010 0010
)这5个位置右移,得到0000 0000 0000 0001 0000 0100 0001 0001
。最低位,带有 'e' 标记的设置。因此,它是一个元音。
啊哈。不太容易,但适用于 ASCII 编码字母。
顺便说一句,它也适用于其他选择的字符。
结果是:
auto isVowel = [](char c) { return (0x208222 >> (c & 0x1f)) & 1; };
酷。 . .