简体   繁体   中英

Pointers and Strings?

I want to write a program that erases all characters in string 1 that appear in string 2 , using pointers . This is what I did , but it did not work .

#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() expects that its source and destination arguments don't overlap in memory — in other words, writing to the destination string shouldn't overwrite parts of the source string. So you can't use it to "shift" a string by an amount that's less than its length. Instead, you can use memmove() , which supports overlapping ranges.

You can replace your strcpy line with:

memmove(p1, p1+1, strlen(p1+1));

which will correctly do what you had expected the strcpy() call to do.


Also, your termination condition for the inner loop is p2<ch2 , which is always false since they start out equal. You probably meant to write p2<ch2+100 .

Your loop conditions have another problem, though: they go past the end of the actual string that's stored in the array. If the user types fewer than 99 characters of input for either string, the corresponding array will contain garbage characters after the null terminator. In the ch1 array, scanning past the end of the string may cause strlen() to go past the end of the whole array looking for another null terminator, and in ch2 , going past the end of the string will cause the program to filter out characters that the user didn't specify.

You should change the two loop conditions to *p1 != '\\0' and *p2 != '\\0' . This will make the loops stop when they reach the end of the two strings.

NEVER USE GETS()

It's unsafe to use gets() under any circumstances, because it doesn't check the length of its input against the length of the array. Use fgets() instead.

Now that you understand that, take a look at your inner loop:

for(p2=ch2;p2<ch2;p2++)

You set p2=ch2 , then check if p2<ch2 . This will always be false. Perhaps you mean to check if p2<ch2+100 ?

First of all, you need bounds checking. gets() does not provide bounds checking.

As for for your loops, you will never enter the nested loops: for(p2=ch2;p2<ch2;p2++) Your initialization will always make your condition false, and you will never enter the loop.

Here is one solution to the problem. This code eliminates the inner loop of the question code by implementing strchr() to determine if a specific character of string1 is present in string2:

#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);
   }

Execution example of the above code:

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> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM