0

I'm trying to compare two strings, and even though they look the same, I wasn't getting a match. Turns out one string contains \n.

So my question is, is a way to check if a string contains '\n'? I'm using the strcmp function;

char *tempData;
char *checkThis;
tempData = "Hello \n";
checkThis = "Hello";
if(strcmp(tempData, checkThis) == 0)
{
  printf("Match");
}
Coren
  • 5,517
  • 1
  • 21
  • 34
user1005253
  • 404
  • 2
  • 7
  • 21

3 Answers3

2

You could strip the white-space before comparing, then you do not require a check for '\n'. But instead you can just compare the strings, assuming that is what you want to do.

This question has some answers on how to do that in C.

Community
  • 1
  • 1
Veger
  • 37,240
  • 11
  • 105
  • 116
2

Create your own comparing function, that ignores the \n or any other char you pass in:

int strcmp_ignoring_char(const char* s1, const char* s2, const char ignore)
{
   while ( *s1 != '\0' && *s1 != '\0' )
   {
      if ( *s1 == ignore )
      {
          s1++;
          continue;
      }

     if ( *s2 == ignore )
      {
          s2++;
          continue;
      }

      if ( *s1 != *s2 )
          return *s1 > *s2 ? 1 : -1;

      s1++;
      s2++;
   }

   /* modified to account for trailing ignore chars, as per Lundin comment */

   if ( *s1 == '\0' && *s2 == '\0' )
      return 0;

   const char* nonEmpty = *s1 == '\0' ? s2 : s1;
   while ( *nonEmpty != '\0' )
       if  ( *nonEmpty++ != ignore )
       return 1;

   return 0;
}

This way you won't scan the strings twice.

You could also create a variation that ignores a string, not a single char:

int strcmp_ignoring_char(const char* s1, const char* s2, const char* ignore)
vulkanino
  • 9,074
  • 7
  • 44
  • 71
  • 1
    I like the idea, but if a `ignore`-char is found, your example will never end. As `s1` and/or `s2` are not updated... Furthermore, in your while statement you check `s1` twice. – Veger Mar 02 '12 at 13:03
  • @Veger you are perfectly right. I'll change my answer for that. – vulkanino Mar 02 '12 at 13:04
  • It contains another error: if for example `*s1 == ignore` s2 should not get increased (and vice versa) – Veger Mar 02 '12 at 13:07
  • Thankyou. I'm new to C, what does the '0? 1' and '1: -1' do? Is it saying if s1 = s2, then true (0) else false 1? – user1005253 Mar 02 '12 at 13:16
  • it is a ternary if: `boolean_expression ? A : B` it returns A if the boolean_expression is true, B otherwise. – vulkanino Mar 02 '12 at 13:17
  • Sorry, one more question. I don't quite understand this bit of code ' if ( *s1 != *s2 ) return *s1 > *s2 ? 1 : -1;' Could you please explain it to me? – user1005253 Mar 02 '12 at 13:31
  • `*s1` takes the **value** of the pointer `s1`, that is, being `s1` a pointer to chars (declared as `const char* s1`), I don't want to get its address, I want its value, that is the single `char`. Same for `s2` I want the char. If the two chars are different (`!=`) then return 1 or -1 depending if the `s1` char is greater or less than the char `s2`. This is to replicate the behavior of the standard `strcmp`, which returns 0 if the strings match, 1 if the first character that does not match has a greater value in s1 than in s2; and a value less than zero indicates the opposite. – vulkanino Mar 02 '12 at 13:38
  • `*s1` is the same as `s1[0]`, so the piece of code checks whether the chars of s1 and s2 are the same, and if so return 1 or -1 depending whether s1 or s2 is higher. – Veger Mar 02 '12 at 13:39
  • One problem is that there might be trailing ignore characters at the end of one string, when the other string has reached '\0'. Your code doesn't handle this case, so it doesn't work as you expect: such cases will be compared as unequal. – Lundin Mar 02 '12 at 14:44
0

Here is my attempt. I have tried to keep it MISRA-C compliant, save for the C99 features.

#include <stdint.h>
#include <stdbool.h>
#include <ctype.h>
#include <stdio.h>


int8_t strcmp_ignore_space (const uint8_t* s1, const uint8_t* s2)
{
  while ((*s1 != '\0') && (*s2 != '\0'))
  {
    bool space1 = isspace(*s1);
    bool space2 = isspace(*s2);

    if(space1)
    {
      s1++;
    }
    if(space2)
    {
      s2++;
    }

    if (!space1 && !space2)
    {
      if (*s1 != *s2)
      {
        break;
      }
      else
      {
        s1++;
        s2++;
      }
    }
  } // while ((*s1 != '\0') && (*s2 != '\0'))

  if(*s1 != '\0')                      // remove trailing white spaces
  {
    while(isspace(*s1))
    {
      s1++;
    }
  }

  if(*s2 != '\0')                      // remove trailing white spaces
  {
    while(isspace(*s2))
    {
      s2++;
    }
  }

  return (int8_t)( (int16_t)*s1 - (int16_t)*s2 );
}


int main()
{
  // obscure strings with various white space characters, but otherwise equal
  if(strcmp_ignore_space("  He\vllo \n",
                         "\r He\fll o ") == 0)
  {
    printf("Same\n");
  }
  else
  {
    printf("Different\n");
  }


  return 0;
}
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • doesn't work, what is it supposed to return? tried with `printf("%d\n", strcmp_ignore_space("Ciao", "ciao"));` and it returns `-32` – vulkanino Mar 02 '12 at 15:05
  • @vulkanino `The strcmp function returns an integer greater than, equal to, or less than zero, accordingly as the string pointed to by s1 is greater than, equal to, or less than the string pointed to by s2.`. 'C'-'c' = 67-99 = -32. So it behaves correctly. – Lundin Mar 02 '12 at 15:17
  • Looks like a nice and simple implementation :) – Veger Mar 02 '12 at 15:46