3

Let's say I have the following code and output:

for (j = 0; j <= i; j++) 
    printf("substring %d is %s\n", j, sub_str[j]);

Output:

substring 0 is max_n=20
substring 1 is max_m=20

Now I only want to print some substrings. However, if I try to do this conditionally:

for (j=0; j <=i; j++) {
   if (sub_str[j] == "max_n=20") {
      printf("substring %d is %s\n", j, sub_str[j]);
   }
}

I get no output at all. What's wrong with my code?

Zeta
  • 103,620
  • 13
  • 194
  • 236
friends
  • 589
  • 5
  • 10
  • 16

4 Answers4

7

You can't use == to compare strings in C. You must use strcmp.

for (j=0; j<=i; j++) { 
   if (strcmp(sub_str[j], "max_n=20") == 0) { 
      printf("substring %d is %s\n", j, sub_str[j]); 
   } 
} 
Starkey
  • 9,673
  • 6
  • 31
  • 51
5

You can't compare strings in C with == operator. You need to use strcmp function or strncmp.

kgiannakakis
  • 103,016
  • 27
  • 158
  • 194
2

You can use strncmp:

if (!strncmp(sub_str[j], "max_n=20", 9)) {

Note the 9 is the length of the comparison string plus the final '\0'. strncmp is a little bit safer than strcmp because you specify how many comparisons will be made at most.

Diego Sevilla
  • 28,636
  • 4
  • 59
  • 87
  • 1
    Classic error - if `sub_str[0]` points to a string `"max_n=200"`, this call to `strncmp` will indicate equality. Since you've made an error, where Starkey didn't, this means `strncmp` is *less* safe than `strcmp`, not more ;-p – Steve Jessop Nov 01 '10 at 15:03
  • Mmm... interesting. You're right. However, it *is* more safe. It is just me not knowing how to use it well. If I put 9, then the comparison is completely right because of the final '\0' of the string. So, applying it well it *is* really safer. Thanks for the correction. I applied it. – Diego Sevilla Nov 01 '10 at 15:05
  • 1
    @Diego: no, because you can still read-overrun whatever buffer `sub_str[j]` points to, if it is shorter than the string literal and isn't itself nul-terminated. The safety that `strncmp` provides is if you know how long the buffer is *supposed* to be, but don't know its contents, and use `strncmp` to ensure you don't overrun. In this case, we know that a string literal is always nul-terminated, and we don't know how long the other buffer is supposed to be, so it's no use at all. It guarantees no more than 9 comparisons: *and so does `strcmp`* because we know literals are terminated. – Steve Jessop Nov 01 '10 at 15:08
  • @Steve: Yes, you can overrun the buffer, but still here you have a known bound that is semantically appliable in this comparison. In fact, for this case of comparing a string with a character string literal, it may be no advantage of `strncmp`, but in general, bouding loops is better than not bounding them. – Diego Sevilla Nov 01 '10 at 15:12
  • 2
    @Diego: I disagree. Bounding loops provides the programmer with a new and subtly different opportunity to screw up. In some cases this new opportunity is less dangerous than some other opportunity it replaces (for instance `strcpy_s` can have definite benefits over `strcpy`, although I would never go so far as to call it "safe" as some people do). In some cases (including this one) it's just one extra thing the programmer can get wrong, in addition to all the things available to get wrong before. – Steve Jessop Nov 01 '10 at 15:19
  • @Steve: perfect. Disagreement is the mother of science :) Unless you disagree on this one... :) I still think that, even when for this example is not safer, adding the bound makes the programmer to think in the bounds, thing that is not automatically done when using `strcmp`. – Diego Sevilla Nov 01 '10 at 15:23
2

Make certain you use strncmp and not strcmp. strcmp is profoundly unsafe.

BSD manpages (any nix will give you this info though):

man strncmp

int strncmp(const char *s1, const char *s2, size_t n);

The strcmp() and strncmp() functions lexicographically compare the null-terminated strings s1 and s2.

The strncmp() function compares not more than n characters. Because strncmp() is designed for comparing strings rather than binary data, characters that appear after a `\0' character are not compared.

The strcmp() and strncmp() return an integer greater than, equal to, or less than 0, according as the string s1 is greater than, equal to, or less than the string s2. The comparison is done using unsigned characters, so that \200' is greater than\0'.

From: http://www.codecogs.com/reference/c/string.h/strcmp.php?alias=strncmp

#include <stdio.h>
#include <string.h>

int main()
{
  // define two strings s, t and initialize s
  char s[10] = "testing", t[10];

  // copy s to t
  strcpy(t, s);

  // test if s is identical to t
  if (!strcmp(s, t))
    printf("The strings are identical.\n");
  else
    printf("The strings are different.\n");

  return 0;
}
禪 師 無
  • 422
  • 2
  • 7
  • 2
    I don't see why `strcmp` is less safe than `strncmp`. In any sane implementation, both functions will stop reading at the first `\0` (I believe this is required by the standard). If you have a non-null-terminated string, you shouldn't be using the str* functions anyway. – Chinmay Kanchi Nov 01 '10 at 15:11
  • @Chinmay: that's what "safer" really means when used in this sense - it might help catch coding errors elsewhere which failed to terminate a string, or at least it might help prevent buffer overrun when such errors exist. In this case it's difficult to see how to use `strncmp` to provide any addition safety at all, but people read something that says, "X is safer than Y", and believe it without necessarily knowing what it means. – Steve Jessop Nov 01 '10 at 15:14
  • If you suspect that any strings you have may not be null-terminated, you should use the mem* functions, which all take a `size_t` as the last argument. Personally, I've never seen the value of _any_ of the strn* functions, though `strncmp` is a particularly pointless example. – Chinmay Kanchi Nov 01 '10 at 15:22
  • Described unsafe because for someone who doesn't know what they're doing, strcmp *is* unsafe. You don't hand the toddler a loaded weapon anymore than you give the neophyte strcmp without a warning. – 禪 師 無 Nov 01 '10 at 15:25
  • @Chinmay: the reason not to use `memcmp` for this is that in a case where both strings are correctly nul-terminated, and happen to be equal, it would keep comparing beyond the nul terminator to the end of the specified buffers, and perhaps indicate a false negative for equality as a result. The fundamental issue is that if you don't trust your input to be NUL-terminated, and your input is just a `char*` (or array of `char*` in this case), then *there's nothing you can do with it*. "Safe" functions or "unsafe", if you don't know what the format of the input is then it's useless. – Steve Jessop Nov 01 '10 at 15:28
  • 2
    @禪師-無: by that definition, `strncmp` is also profoundly unsafe. For that matter so is the C programming language. There is no substitute in C for knowing what you're doing. – Steve Jessop Nov 01 '10 at 15:29
  • @Steve: True, but that would be one f***ed up string ;). I agree with you though. If you want safety, use a different language. There is pretty much _no_ way to make string comparisons in C completely safe without quite a lot of voodoo (and breaking compatibility with most of the standard library). – Chinmay Kanchi Nov 01 '10 at 15:36
  • How he came to C isn't my problem, I'm just trying to keep him from falling off the first cliff. The second, third, fourth, fifth...not my province. – 禪 師 無 Nov 01 '10 at 15:40
  • 1
    @Chinmay: To answer an earlier point you made, what `strncmp` is actually *for*, is comparing "strings" that would be copied with `strncpy`. That is, fixed-width character arrays which may be *truncated* with a NUL byte, but which aren't NUL-terminated if they're full width, and also need not be 0-padded as `strncpy` does. If someone is using `strncmp` with anything other than archaic data records (e.g. some platform-specific filesystem structures), chances are they've chosen the wrong set of "safe" string-handling functions, even granted that some kind of buffer-length safety is worthwhile. – Steve Jessop Nov 01 '10 at 16:59
  • What specifically is unsafe about it? See [What's wrong with strcmp?](http://stackoverflow.com/questions/24353504/whats-wrong-with-strcmp). – David Cary Jun 23 '14 at 02:44