[英]Pointers and Strings?
我想編寫一個程序,使用指針擦除字符串1中出現在字符串2中的所有字符。 這是我所做的,但是沒有用。
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
main()
{
char ch1[100] , ch2[100] ;
char *p1 , *p2;
printf("first chaine ");
gets(ch1);
printf("sd chaine");
gets(ch2);
for(p1=ch1;p1<ch1+100;p1++)
{
for(p2=ch2;p2<ch2;p2++)
{
if(*p1==*p2)
{
strcpy(p1,p1+1);
}
}
}
puts(ch1);
return 0 ;
}
strcpy()
期望其源參數和目標參數在內存中不重疊-換句話說,寫入目標字符串不應覆蓋源字符串的一部分。 因此,您不能使用它來“移動”字符串,使其長度小於其長度。 相反,您可以使用memmove()
,它支持重疊范圍。
您可以將strcpy
行替換為:
memmove(p1, p1+1, strlen(p1+1));
它將正確執行您期望的strcpy()
調用。
另外,內循環的終止條件是p2<ch2
,因為它們開始相等,所以始終為假。 您可能打算寫p2<ch2+100
。
但是,循環條件還有另一個問題:它們超出了存儲在數組中的實際字符串的末尾。 如果用戶為每個字符串輸入的輸入少於99個字符,則對應的數組將在null終止符后包含垃圾字符。 在ch1
數組中,掃描超過字符串的末尾可能會導致strlen()
越過整個數組的末尾,以尋找另一個空終止符;在ch2
,超過字符串的末尾將導致程序被過濾掉用戶未指定的字符。
您應該將兩個循環條件更改為*p1 != '\\0'
和*p2 != '\\0'
。 這將使循環在到達兩個字符串的末尾時停止。
切勿使用GETS()
在任何情況下都使用gets()
是不安全的,因為它不會根據數組的長度檢查其輸入的長度。 使用fgets()
代替。
現在您已經了解了這一點,請看一下您的內部循環:
for(p2=ch2;p2<ch2;p2++)
設置p2=ch2
,然后檢查p2<ch2
。 這將永遠是錯誤的。 也許您的意思是檢查p2<ch2+100
嗎?
首先,您需要邊界檢查。 gets()
不提供邊界檢查。
至於循環,您永遠不會進入嵌套循環: for(p2=ch2;p2<ch2;p2++)
您的初始化將始終使條件變為假,並且您將永遠不會進入循環。
這是解決該問題的一種方法。 該代碼通過實現strchr()來確定string2中是否存在string1的特定字符,從而消除了問題代碼的內部循環:
#include <stdio.h>
#include <string.h>
int main(void)
{
char ch1[100] , ch2[100];
char *p1, *p2;
/* Get string1 from stdin. */
printf("first chaine ");
fgets(ch1, sizeof(ch1), stdin);
/* Get string2 from stdin. */
printf("sd chaine ");
fgets(ch2, sizeof(ch2), stdin);
/* Eliminate all chars from string1 that appear in string2. */
for(p1=ch1, p2=ch1; *p1; p1++)
{
if(strchr(ch2, *p1))
continue;
*p2++ = *p1;
}
*p2 = '\0';
/* Print modified string1. */
puts(ch1);
return(0);
}
上面代碼的執行示例:
SLES11SP2:~/SO> ./test
first chaine Now is the time for all good men to come to the aid of their country.
sd chaine aeiou
Nw s th tm fr ll gd mn t cm t th d f thr cntry.
SLES11SP2:~/SO>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.