C++ 中的 C 风格字符串回文检测器(不区分大小写)
C Style String palindrome detector (case insensitive) in C++
我一直在尝试创建一个程序,它从用户那里获取 C 风格的字符串并回答它是否是回文。我已经构建了一个函数 (purg),它取出所有非小写字母(并将大写字母变为小写字母)。另一个是 returns true 或 false 是否为回文。 purg 函数可以按预期打印修改后的字符串(例如 "Race 111 car" 打印为 "racecar"),但是回文函数不会将该修改后的字符串标记为回文,这是怎么回事?
#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
using namespace std;
bool isit(char *test, int u){
char *well = test;
bool chk = false;
for (int i = 0; i<2; i++) {
if (well[i] != well[u-i-1]) {
return false;
}
cout << well[i];
}
return true;
}
void purg(char *ini){
int x = 0;
bool answ;
char *elim = ini;
for (int i = 0; ini[i] != '[=10=]'; i++) {
if (ini[i] >= 'A' && ini[i] <= 'Z') {
elim[i] = ini[i] + 32;
x++;
} else if (!(ini[i] >= 'a' && ini[i] <= 'z')) {
elim[i]='[=10=]';
} else{
x++;
}
cout << elim[i]; //This reliably prints the answer I expect ("11race car_!" to "racecar")
}
answ = isit(&elim[0], x); //Is this passed correctly?
cout << endl;
if (answ == true){
cout << "It is a palindrome." << endl; //(user inputs like "RACecar", "racecar111", "racecar" and "WAAAAW111" are correct)
} else {
cout << "No palindrome here..." << endl; //("race car", "1racecar", and "d1o1d" are not, but they print as expected "racecar" and "dod")
}
}
int main(){
string str;//I'm not supposed to use C++ strings, should I replace this with char str[512]={}?
cout<<"Give me a string"<<endl;
getline(cin,str);
purg(&str[0]);
return 0;
}
快速浏览您的代码后 - 似乎您将所有非字母字符替换为“\0”,然后期望包含随机“\0”字符的字符串通过回文测试,该测试测试字符相等,将 '\0' 视为必须与另一侧的镜像 '\0' 匹配的常规字符。
此外,您将包含 '\0' 字符的全长字符串传递给 isit
函数,但只给出未替换字符的数量作为长度。
您的字符串显示正确打印的原因是,当您打印“\0”时,它什么也没做。用调试器查看 ini
的内容,你会发现它确实被那些被替换的 '\0' 字符弄得乱七八糟。
尝试给它一个不包含任何非字母字符的字符串,如果我是正确的,它应该通过。
首先让我们将您的代码分成两个具有两个不同目的的不同函数,这样我们就可以分别讨论它们:
清除字符串中的非字母
您的代码:
void purge(char *ini) {
int x = 0;
bool answ;
char *elim = ini;
for (int i = 0; ini[i] != '[=10=]'; i++) {
if (ini[i] >= 'A' && ini[i] <= 'Z') {
elim[i] = ini[i] + 32;
x++;
} else if (!(ini[i] >= 'a' && ini[i] <= 'z')) {
elim[i]='[=10=]';
} else{
x++;
}
}
}
此代码的主要问题:
x
应该做什么?看起来它应该跟踪有效字符的数量,但您从未使用过它。事实上,如果我们运行一个测试:
char s[256] = "a!bc";
purge(s);
ASSERT_EQ("abc", s); // This fails, purge changed the string s into just "a".
我们该如何解决这个问题?
嗯,通过使用 x
!
void purge(char *str) {
int x = 0;
for (int i = 0; ini[i] != '[=12=]'; i++) {
if (str[i] >= 'A' && str[i] <= 'Z') {
str[x] = str[i] - 'A' + 'a';
x++;
} else if (str[i] >= 'a' && str[i] <= 'z') {
str[x] = str[i];
x++;
}
}
// Make sure we null terminate the new string.
str[x] = '[=12=]';
}
测试字符串是否为回文
您的代码:
bool is_palindrome(char *test, int u){
char *well = test;
bool chk = false;
for (int i = 0; i<2; i++) {
if (well[i] != well[u-i-1]) {
return false;
}
cout << well[i];
}
return true;
}
代码问题:
- 错误的变量名。
u
应该是什么? well
应该是什么?
- 为什么你只从
i=0..2
开始循环?
我们如何解决这个问题...
bool is_palindrome(char *str, int str_length) {
for (int i = 0; i < str_length / 2; i++) {
if (str[i] != str[str_length - i - 1]) {
return false;
}
}
return true;
}
其他想法
通过将代码重写为两个单独的函数,我们可以开始向这段代码添加测试。例如,我们可以使用 google 的单元测试基础设施来做类似的事情:
TEST(MyTests, Purge_Nothing) {
char a[256] = "abc";
purge(a);
EXPECT_EQ(std::string("abc"), a);
}
TEST(MyTests, Purge_Non_Letters_At_Front) {
char a[256] = "!abc";
purge(a);
EXPECT_EQ(std::string("abc"), a);
}
TEST(MyTests, Purge_Non_Letter_In_Middle) {
char a[256] = "ab!c";
purge(a);
EXPECT_EQ(std::string("abc"), a);
}
TEST(MyTests, Purge_Non_Letters_At_End) {
char a[256] = "abc!";
purge(a);
EXPECT_EQ(std::string("abc"), a);
}
TEST(MyTests, Purge_Uppercase) {
char a[256] = "Abc!";
purge(a);
EXPECT_EQ(std::string("abc", a);
}
TEST(MyTests, Palindrome) {
EXPECT_TRUE(is_palindrome("abcba");
EXPECT_TRUE(is_palindrome("abba"));
EXPECT_TRUE(is_palindrome("aba"));
EXPECT_TRUE(is_palindrome("aa"));
EXPECT_TRUE(is_palindrome("z"));
EXPECT_TRUE(is_palindrome(""));
EXPECT_FALSE(is_palindrome("abcda");
EXPECT_FALSE(is_palindrome("abda");
EXPECT_FALSE(is_palindrome("abd");
EXPECT_FALSE(is_palindrome("ad");
}
用于回文测试的不区分大小写函数的 C 示例。您可以像在 C++ 代码中一样使用它。
#include <string.h>
#include <ctype.h>
int is_palindrome(const char * str) {
const char * tail = str + strlen(str) - 1;
for ( ; str < tail && toupper(*str) == toupper(*tail); ++str, --tail )
;
return str >= tail;
}
我一直在尝试创建一个程序,它从用户那里获取 C 风格的字符串并回答它是否是回文。我已经构建了一个函数 (purg),它取出所有非小写字母(并将大写字母变为小写字母)。另一个是 returns true 或 false 是否为回文。 purg 函数可以按预期打印修改后的字符串(例如 "Race 111 car" 打印为 "racecar"),但是回文函数不会将该修改后的字符串标记为回文,这是怎么回事?
#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
using namespace std;
bool isit(char *test, int u){
char *well = test;
bool chk = false;
for (int i = 0; i<2; i++) {
if (well[i] != well[u-i-1]) {
return false;
}
cout << well[i];
}
return true;
}
void purg(char *ini){
int x = 0;
bool answ;
char *elim = ini;
for (int i = 0; ini[i] != '[=10=]'; i++) {
if (ini[i] >= 'A' && ini[i] <= 'Z') {
elim[i] = ini[i] + 32;
x++;
} else if (!(ini[i] >= 'a' && ini[i] <= 'z')) {
elim[i]='[=10=]';
} else{
x++;
}
cout << elim[i]; //This reliably prints the answer I expect ("11race car_!" to "racecar")
}
answ = isit(&elim[0], x); //Is this passed correctly?
cout << endl;
if (answ == true){
cout << "It is a palindrome." << endl; //(user inputs like "RACecar", "racecar111", "racecar" and "WAAAAW111" are correct)
} else {
cout << "No palindrome here..." << endl; //("race car", "1racecar", and "d1o1d" are not, but they print as expected "racecar" and "dod")
}
}
int main(){
string str;//I'm not supposed to use C++ strings, should I replace this with char str[512]={}?
cout<<"Give me a string"<<endl;
getline(cin,str);
purg(&str[0]);
return 0;
}
快速浏览您的代码后 - 似乎您将所有非字母字符替换为“\0”,然后期望包含随机“\0”字符的字符串通过回文测试,该测试测试字符相等,将 '\0' 视为必须与另一侧的镜像 '\0' 匹配的常规字符。
此外,您将包含 '\0' 字符的全长字符串传递给 isit
函数,但只给出未替换字符的数量作为长度。
您的字符串显示正确打印的原因是,当您打印“\0”时,它什么也没做。用调试器查看 ini
的内容,你会发现它确实被那些被替换的 '\0' 字符弄得乱七八糟。
尝试给它一个不包含任何非字母字符的字符串,如果我是正确的,它应该通过。
首先让我们将您的代码分成两个具有两个不同目的的不同函数,这样我们就可以分别讨论它们:
清除字符串中的非字母
您的代码:
void purge(char *ini) {
int x = 0;
bool answ;
char *elim = ini;
for (int i = 0; ini[i] != '[=10=]'; i++) {
if (ini[i] >= 'A' && ini[i] <= 'Z') {
elim[i] = ini[i] + 32;
x++;
} else if (!(ini[i] >= 'a' && ini[i] <= 'z')) {
elim[i]='[=10=]';
} else{
x++;
}
}
}
此代码的主要问题:
x
应该做什么?看起来它应该跟踪有效字符的数量,但您从未使用过它。事实上,如果我们运行一个测试:
char s[256] = "a!bc";
purge(s);
ASSERT_EQ("abc", s); // This fails, purge changed the string s into just "a".
我们该如何解决这个问题?
嗯,通过使用 x
!
void purge(char *str) {
int x = 0;
for (int i = 0; ini[i] != '[=12=]'; i++) {
if (str[i] >= 'A' && str[i] <= 'Z') {
str[x] = str[i] - 'A' + 'a';
x++;
} else if (str[i] >= 'a' && str[i] <= 'z') {
str[x] = str[i];
x++;
}
}
// Make sure we null terminate the new string.
str[x] = '[=12=]';
}
测试字符串是否为回文
您的代码:
bool is_palindrome(char *test, int u){
char *well = test;
bool chk = false;
for (int i = 0; i<2; i++) {
if (well[i] != well[u-i-1]) {
return false;
}
cout << well[i];
}
return true;
}
代码问题:
- 错误的变量名。
u
应该是什么?well
应该是什么? - 为什么你只从
i=0..2
开始循环?
我们如何解决这个问题...
bool is_palindrome(char *str, int str_length) {
for (int i = 0; i < str_length / 2; i++) {
if (str[i] != str[str_length - i - 1]) {
return false;
}
}
return true;
}
其他想法
通过将代码重写为两个单独的函数,我们可以开始向这段代码添加测试。例如,我们可以使用 google 的单元测试基础设施来做类似的事情:
TEST(MyTests, Purge_Nothing) {
char a[256] = "abc";
purge(a);
EXPECT_EQ(std::string("abc"), a);
}
TEST(MyTests, Purge_Non_Letters_At_Front) {
char a[256] = "!abc";
purge(a);
EXPECT_EQ(std::string("abc"), a);
}
TEST(MyTests, Purge_Non_Letter_In_Middle) {
char a[256] = "ab!c";
purge(a);
EXPECT_EQ(std::string("abc"), a);
}
TEST(MyTests, Purge_Non_Letters_At_End) {
char a[256] = "abc!";
purge(a);
EXPECT_EQ(std::string("abc"), a);
}
TEST(MyTests, Purge_Uppercase) {
char a[256] = "Abc!";
purge(a);
EXPECT_EQ(std::string("abc", a);
}
TEST(MyTests, Palindrome) {
EXPECT_TRUE(is_palindrome("abcba");
EXPECT_TRUE(is_palindrome("abba"));
EXPECT_TRUE(is_palindrome("aba"));
EXPECT_TRUE(is_palindrome("aa"));
EXPECT_TRUE(is_palindrome("z"));
EXPECT_TRUE(is_palindrome(""));
EXPECT_FALSE(is_palindrome("abcda");
EXPECT_FALSE(is_palindrome("abda");
EXPECT_FALSE(is_palindrome("abd");
EXPECT_FALSE(is_palindrome("ad");
}
用于回文测试的不区分大小写函数的 C 示例。您可以像在 C++ 代码中一样使用它。
#include <string.h>
#include <ctype.h>
int is_palindrome(const char * str) {
const char * tail = str + strlen(str) - 1;
for ( ; str < tail && toupper(*str) == toupper(*tail); ++str, --tail )
;
return str >= tail;
}