[英]Unexpected output from palindrome function in C
我已經編寫了此函數isPalindrome,該函數旨在從單獨的函數中獲取字符串輸入,如果它是回文,則返回1,否則返回0。 輸入的內容可以是任何字符,也可以有大寫字母,該函數用於對這些字符進行排序,並純粹根據字母字符檢查回文是否是回文。
我已經有一段時間了,我無法弄清楚出了什么問題,整個功能都在下面,但是我無法理解它給我的輸出,有時它會完全跳過最后的else語句,並且停止循環,我不知道為什么。 當連續輸入兩個非字母字符時,變量a或b不會增加兩次,而是將其發送到最后的else語句並返回錯誤的值。
我正在嘗試編寫此函數,而不將任何信息也復制到單獨的數組中。
int isPalindrome(char s[])
{
int logic;
int a = 0;
int b = 0;
int num = 0;
int count = 0;
while ( s[b]!='\0' )
{
if ( isalpha(s[b]) != 0 )
{
num++;
}
b++;
}
b = b - 1;
printf("The number of characters is: %d\n", b);
printf("The number of alpha characters is: %d\n", num);
while ( count < num/2 )
{
if ( !isalpha(s[a]) || s[a] == ' ')
{
a++;
}
else
{
count++;
}
if ( !isalpha(s[b]) || s[b] == ' ')
{
b--;
}
if ( toupper(s[a]) == toupper(s[b]) )
{
printf("s[%d]: %c | s[%d]: %c\n", a, toupper(s[a]), b, toupper(s[b]));
a++;
b--;
if ( a == b )
{
logic = 1;
}
}
else
{
logic = 0;
break;
}
}
return logic;
}
有多個錯誤(1)邏輯必須初始化為1(2)每次循環迭代僅檢查一個無效字符。
如果刪除以下代碼,它應該可以工作(我的意思是沒有有效的字符檢查)。
if ( !isalpha(s[a]) || s[a] == ' ')
{
a++;
}
else
{
count++;
}
if ( !isalpha(s[b]) || s[b] == ' ')
{
b--;
}
要刪除無效字符,最好在進入循環之前執行此操作,或者檢查'a <b'而不是count / 2,然后繼續對無效字符進行如下操作。
logic=1;
while (a<b)
{
if ( !isalpha(s[a]))
{
a++;
continue;
}
if ( !isalpha(s[b]))
{
b--;
continue;
}
if ( toupper(s[a]) == toupper(s[b]) )
{
printf("s[%d]: %c | s[%d]: %c\n", a, toupper(s[a]), b, toupper(s[b]));
a++;
b--;
}
else
{
logic = 0;
break;
}
}
return logic;
看來您希望回文測試人員僅考慮字母字符,而忽略大小寫。 如果真是這樣,您的程序邏輯是錯誤的。
您有a
和b
作為字符串的索引,其中a
從頭開始, b
從頭開始。 我認為最好將b
設置為最后,然后開始工作循環,而不是計算必須執行的測試數量。 只要a < b
為真,循環就會繼續:
int a = 0;
int b = strlen(s) - 1;
while (a < b)
{
在循環的身邊,你應該增加a
,如果s[a]
不能是字母,和減量b
如果s[b]
是不是一個字母,只要a
持續小於b
。
while (a < b && !isalpha(s[a]))
{
++a;
}
while (a < b && !isalpha(s[b]))
{
--b;
}
如果在調整之后, a
仍小於b
,則可以不考慮大小寫而比較s[a]
和s[b]
。 如果它們不相等,則字符串不是回文,因此我們可以從循環中中斷。 否則, a
遞增, b
遞減,循環繼續回到頂部:
if (a < b && toupper(s[a]) != toupper(s[b]))
{
break;
}
++a;
--b;
}
如果循環結束並且a < b
仍然為true,則意味着toupper(s[a]) != toupper(s[b])
,因此該字符串不是回文,我們可以返回false。 否則,它是回文。 因此該函數可以返回以下事實:
if (a < b)
{
return false;
}
else
{
return true;
}
// or more succinctly: return !(a < b);
您的錯誤在導致“有效載荷”回文條件檢查的代碼中:
if ( toupper(s[a]) == toupper(s[b]) )
該檢查之前的代碼應該使a
和b
處於s[a]
和s[b]
均為字母的狀態。
您的代碼無法做到這一點:特別是,當您將一個字母與一個非字母甚至兩個非字母進行比較時,多個非字母字符的序列會使您進入一種狀態。
解決此問題的更簡單方法是將程序分為兩個階段。 第一階段將消除輸入字符串中的所有非字母; 第二階段將執行回文檢查。
復制輸入字符串,然后逐個字符地進行遍歷,僅將字母復制回字符串中。 您最終會得到一個比原始字符串短或相同長度的字符串。
現在回文檢查變得無足輕重了:從兩端開始,檢查是否有toupper
直到兩端在中間相遇。 不要忘記釋放您的字符串副本!
您跳過非字母字符的代碼無法處理多個連續的非字母字符的情況。 您可以從預處理過程中知道有多少個字母字符,因此您需要用while
循環替換if
語句,並使else
的主體成為無條件的。
我會自動在代碼中進行許多其他簡化。
#include <ctype.h>
#include <stdio.h>
#include <string.h>
static
int isPalindrome(char s[])
{
int a = 0;
int b = 0;
int num = 0;
int count = 0;
while (s[b] != '\0')
{
if (isalpha(s[b++]))
num++;
}
printf("The number of characters is: %d\n", b);
printf("The number of alpha characters is: %d\n", num);
while (count < num/2)
{
count++;
while (!isalpha(s[a]))
a++;
while (!isalpha(s[b]))
b--;
if (toupper(s[a]) != toupper(s[b]))
return 0;
printf("s[%d]: %c | s[%d]: %c\n", a, toupper(s[a]), b, toupper(s[b]));
a++;
b--;
}
return 1;
}
int main(void)
{
char line[256];
while (fgets(line, sizeof(line), stdin) != 0)
{
line[strlen(line)-1] = '\0';
printf("Input: <<%s>>\n", line);
if (isPalindrome(line))
puts("Palindrome");
else
puts("Not a palindrome");
}
return 0;
}
這適用於字母和非字母字符的錯誤序列。 它將空行和由所有非字母字符組成的行視為回文。 如果希望它們被拒絕,則可以在對字母字符數進行計數的循環之后,當字母字符數為零時報告“不是回文”,以解決該問題。 當檢測到字符串不能是回文字符串時,該代碼會盡早返回。 您可以在測試之前在循環中移動打印語句; 然后您將看到每個比較的結果,而不僅僅是成功的比較。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.