![](/img/trans.png)
[英]How to omit the dots, commas and white spaces for a string (needed for checking a palindrome)
[英]How to remove spaces and check if a string is a palindrome?
我試圖弄清楚如何刪除空格,然后檢查帶有刪除空格的字符串是否是回文。
我已經分別嘗試了這兩種方法,但是我無法讓它們一起工作。
int check_palindrome(char *);
int main()
{
char s1[20];
printf("Enter the string...\n");
gets(s1);
int x;
x=check_palindrome(s1);
x?printf("%s = is a Palindrome\n", s1):printf("%s = is Not a Palindrome\n", s1);
}
int check_palindrome(char *s)
{
int i,j;
for(i=0;s[i];i++);
for(i=i-1,j=0;i>j;i--,j++)
{
if(s[i]!=s[j])
{
return 0;
}
}
if(s[i]==s[j])
{
return 1;
}
}
該代碼可用於檢查回文,但如果輸入以大寫字母開頭或包含空格,則該代碼將無效。 例如,我期望“ nurses run是回文”的輸出,但是實際輸出是“ nurses run不是回文”,因為它們之間的空間很大,因此“ Dad”的預期輸出是“爸爸是回文集”,但返回“爸爸不是回文集”。
如果不需要修改后的字符串,則可以節省大量工作,而在比較中忽略空白和大小寫,例如:
int ispalindrome = 1;
while (s < e && ispalindrome) {
while (*s == ' ') s++;
while (*e == ' ') e--;
if (tolower(*s++) != tolower(*e--))
ispalindrome = 0;
}
s
指向字符串的開頭, e
指向字符串的結尾(最后一個字符)。
編輯:
我剛剛意識到,如果整個字符串僅由空格組成,那么在極端情況下可能會發生越界數組訪問。 然后,第二個空間跳過循環將經過數組的“左”端。 因此將其更改為
while (*e == ' ' && e > s) e--;
請注意,在這種情況下, ispalindrome
將為假。 空字符串是否是回文是定義的問題。
我將從格式化字符串開始,以便通過刪除所有特殊/空格字符,然后將所有字母都轉換為大寫或小寫,使其更易於分析。
我喜歡您的簡潔風格。 因此答案必須合適。
1.)大寫字母反轉邏輯:
if(s[i]==s[j])
continue;
if(s[i]==s[j]+DIFF_a_A) continue;
if(s[i]+DIFF_a_A==s[j]) continue;
return false;
與#define DIFF_a_A ('A' - 'a')
2.)空白將增量放入循環中:
for(i=i-1,j=0;i>j;){
if(s[i] == ' ') i--, continue;
if(s[j] == ' ') j++, continue;
...
i--,j++;
}
這符合您的風格嗎?
如何刪除空格並檢查字符串是否是回文?
您的問題分為兩部分: (1) “ 如何刪除空格 ”? 和(2) [如何]“ 檢查字符串是否是回文? ”。 您應該分兩個步驟解決該問題。
可以通過以下兩種方法之一來刪除字符串中的空格: (1)刪除原始字符串中的空格(假定您的原始字符串是可變字符串而不是String Literal ),或者(2)填充空格時刪除空格第二個字符串,其中第一個字符串帶有非空格字符,保留第一個字符串不變(不管原始字符串是否可變,都可以使用)。 您最安全的選擇是后者。
提供源緩沖區和目標緩沖區作為該函數的參數以刪除空白的簡單函數可能很簡單:
void removespace (char *dest, const char *src)
{
size_t n = 0;
while (*src) {
if (!isspace(*src))
dest[n++] = *src;
src++;
}
dest[n] = *src; /* nul-terminate */
}
轉到問題的第二部分,如果您在使用起始和結束指針從字符串的末端到中間進行迭代來檢查字符串是否是回文式時遇到麻煩,可以執行相同的操作與字符串索引。 此外,每當您需要檢查某些內容是否為空格或在字符大小寫之間轉換時,請使用ctype.h
提供的isspace()
或tolower() / toupper()
宏。 (否則,您將負責所需的所有條件檢查)
使用字符串索引的簡單checkpalindrome()
實現可以是:
int checkpalindrome (const char *s)
{
size_t n = 0, len = strlen (s);
while (len-- > n) /* loop over each start/end lowercase char */
if (tolower (s[n++]) != tolower (s[len]))
return 0;
return 1;
}
現在,在main()
實現中,從用戶讀取您的字符串永遠不要使用gets()
。 它是如此不安全並且容易被緩沖區溢出利用,因此已從C11中的標准庫中刪除。 請參閱為什么gets()如此危險,永遠不應該使用它! 。 只需使用fgets()
代替,並通過使用nul終止字符覆蓋行尾來修剪fgets
填充的緩沖區中的行尾。 ( strcspn()
對此很方便)。
將其放在一起(並使用三元控制"is"
或"is not"
輸出),您可以執行以下操作:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAXC 1024 /* if you need a constant, define one (or more) */
void removespace (char *dest, const char *src)
{
size_t n = 0;
while (*src) {
if (!isspace(*src))
dest[n++] = *src;
src++;
}
dest[n] = *src; /* nul-terminate */
}
int checkpalindrome (const char *s)
{
size_t n = 0, len = strlen (s);
while (len-- > n) /* loop over each start/end lowercase char */
if (tolower (s[n++]) != tolower (s[len]))
return 0;
return 1;
}
int main (void) {
char s[MAXC], nospace[MAXC];
fputs ("enter a string: ", stdout);
if (!fgets (s, MAXC, stdin)) { /* Never, Ever use gets() */
fputs ("(user canceled input)\n", stderr);
return 1;
}
s[strcspn (s, "\r\n")] = 0; /* trim line-ending */
removespace (nospace, s); /* remove whitespace from s */
printf ("'%s' => %s a palindrome.\n",
s, checkpalindrome (nospace) ? "is" : "is not");
return 0;
}
( 注意: 決不要跳過緩沖區大小! )
使用/輸出示例
$ ./bin/checkpalindrome
enter a string: a
'a' => is a palindrome.
(您可以根據自己的需要更改處理單個字符串的方式)
$ ./bin/checkpalindrome
enter a string: aa
'aa' => is a palindrome.
$ ./bin/checkpalindrome
enter a string: ab
'ab' => is not a palindrome.
$ ./bin/checkpalindrome
enter a string: aba
'aba' => is a palindrome.
$ ./bin/checkpalindrome
enter a string: abc
'abc' => is not a palindrome.
$ ./bin/checkpalindrome
enter a string: A man a plan a canal Panama
'A man a plan a canal Panama' => is a palindrome.
仔細檢查一下,如果您有任何問題,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.