5

I would like to compare a character literal with the first element of string, to check for comments in a file. Why use a char? I want to make this into a function, which accepts a character var for the comment. I don't want to allow a string because I want to limit it to a single character in length.

With that in mind I assumed the easy way to go would be to address the character and pass it to the std::string's compare function. However this is giving me unintended results.

My code is as follows:

#include <string>
#include <iostream>

int main ( int argc, char *argv[] )
{
  std::string my_string = "bob";
  char my_char1 = 'a';
  char my_char2 = 'b';

  std::cout << "STRING : " << my_string.substr(0,1) << std::endl
        << "CHAR : " << my_char1 << std::endl;
  if (my_string.substr(0,1).compare(&my_char1)==0)
    std::cout << "WOW!" << std::endl;
  else
    std::cout << "NOPE..." << std::endl;

  std::cout << "STRING : " << my_string.substr(0,1) << std::endl
        << "CHAR : " << my_char2 << std::endl;
  if (my_string.substr(0,1).compare(&my_char2)==0)
    std::cout << "WOW!" << std::endl;
  else
    std::cout << "NOPE..." << std::endl;

  std::cout << "STRING : " << my_string << std::endl
        << "STRING 2 : " << "bob" << std::endl;
  if (my_string.compare("bob")==0)
    std::cout << "WOW!" << std::endl;
  else
    std::cout << "NOPE..." << std::endl;
}

Gives me...

STRING : b
CHAR : a
NOPE...
STRING : b
CHAR : b
NOPE...
STRING : bob
STRING 2 : bob
WOW!

Why does the function think the sub-string and character aren't the same. What's the shortest way to properly compare chars and std::string vars?

(a short rant to avoid reclassification of my question.... feel free to skip)
When I say shortest I mean that out of a desire for coding eloquence. Please note, this is NOT a homework question. I am a chemical engineering Ph.D candidate and am coding as part of independent research. One of my last questions was reclassified as "homework" by user msw (who also made a snide remark) when I asked about efficiency, which I considered on the border of abuse. My code may or may not be reused by others, but I'm trying to make it easy to read and maintainable. I also have a bizarre desire to make my code as efficient as possible where possible. Hence the questions on efficiency and eloquence.

5 Answers 5

15

Doing this:

  if (my_string.substr(0,1).compare(&my_char2)==0)

Won't work because you're "tricking" the string into thinking it's getting a pointer to a null-terminated C-string. This will have weird effects up to and including crashing your program. Instead, just use normal equality to compare the first character of the string with my_char:

 if (my_string[0] == my_char)
   // do stuff
Sign up to request clarification or add additional context in comments.

1 Comment

And don't forget to check that 0 < my_string.length() before you try to access my_string[0].
4

Why not just use the indexing operator on your string? It will return a char type.

if (my_string[0] == my_char1)

Comments

3

You can use the operator[] of string to compare it to a single char

// string::operator[]
#include <iostream>
#include <string>
using namespace std;

int main ()
{
    string str ("Test string");
    int i; char c = 't';
    for (i=0; i < str.length(); i++)
    {
        if (c == str[i]) {
            std::cout << "Equal at position i = " << i << std::endl;
        }
    }
    return 0;
}

Comments

1

The behaviour of the first two calls to compare is entirely dependent on what random memory contents follows the address of each char. You are calling basic_string::compare(const char*) and the param here is assumed to be a C-String (null-terminated), not a single char. The compare() call will compare your desired char, followed by everything in memory after that char up to the next 0x00 byte, with the std::string in hand.

Otoh the << operator does have a proper overload for char input so your output does not reflect what you are actually comparing here.

Convert the decls of and b to be const char[] a = "a"; and you will get what you want to happen.

Comments

1

Pretty standard, strings in c++ are null-terminated; characters are not. So by using the standard compare method you're really checking if "b\0" == 'b'.

I used this and got the desired output:

if (my_string.substr(0,1).compare( 0, 1, &my_char2, 1)==0 )
    std::cout << "WOW!" << std::endl;
else
    std::cout << "NOPE..." << std::endl;

What this is saying is start at position 0 of the substring, use a length of 1, and compare it to my character reference with a length of 1. Reference

2 Comments

Strings in c++ are NOT null-terminated. They are null-terminated in C, because they are actually a pointer to char.
@Draco: std::string is not required to be null-terminated (although that is changing in 0x), but there are still plenty of places in the C++ standard that assumes null-terminated array of char. Including a number of methods within std::string, as this question illustrates.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.