You are here:

C++/Error C2228 and what is std::string::npos?

Advertisement


Question
Hi Mr.McArdell, thanks for the answers given for the subject: Count the number of occurrences of a word in string.

1) I applied the given samples into a function but I have error: "error C2228: left of '.find' must have class/struct/union type." Why?

2) When do we use "std::string::npos" ?

This is the code:

#include <iostream.h>
#include <string>

int countAnds(char str[]);

int main()
{
    char myString[80];
    int numberAnds;
    cout << "Enter a string to be evaluated:\n";
    cin.get(myString, 80);
  
    numberAnds = countAnds(myString);
    return 0;
}

int countAnds(char str[])
{   int count=0;
  int and_pos=0;
  
  while ( and_pos!=std::string::npos )
  {
    and_pos = str.find("and", and_pos );
    if ( and_pos != std::string::npos )
     {
      ++count;
      and_pos += 3;
     }
  }
return count;
}

Thanks a lot for the explanation! I use Microsoft Visual C++ 6.

Answer
First I would like to point out that you should not freak out when you get errors from the compiler it is a complete stickler for correctness as it sees it (even if the way it sees it is different from the C++ standard). You have to please it to get it to do its job. However, we all make mistakes I still quite often see the very same error as you have here but usually for different reasons! No one I know types in correct code to start with very often even if all we did was mistype a name or forget to end a statement with a semicolon. In fact I usually expect the compiler to complain if I change or add more than a couple of lines and get suspicious if it says all is well did it actually re-compile the changed code?

In this case you did not read my answer and samples carefully enough.

In your posted code I see the following:

       int countAnds(char str[])

In my code I think you saw this:

       int WordOccurrenceCount
       ( std::string const & str, std::string const & word )

Can you spot the difference?

My str is the type std::string a class defined in the namespace std (in fact it is a reference to a constant object of that type you can find out for yourself about reference types and const if you have not come across them before). Your str type is the type char str[] a built in array of char.

The built in array types have no member functions such as the operation find. The compiler worked out that find refers to a member of the object str but str in your code is a built in array so the compiler gave you an error.

The error in this case is quite reasonable: '.find' must have class/struct/union type as using .find implies it is a member of some type and such things only apply to objects of user defined compound types such as std::string and not to built in types such as arrays of char which is the type of your str parameter.

Note that we speak of user defined types and built in types. User defined types are any types defined in code that is compiled by the compiler. Build in types are those the compiler knows about already such as int, double, char, and (built in) array, pointer and reference types of other types.

Now std::string, and other C++ library types, although not defined by you as a user but provided with the compiler, is defined in code you as a user include in your code and it therefore counts as a user defined type. It is not something the compiler knows about until it sees the code that defines it. In fact you can replace the provided C++ library with 3rd party alternatives see http://www.stlport.org/ for a free C++ library implementation that is usable by various compilers and http://www.dinkumware.com/ for an example of commercial standard library vendor (in fact as far as I know Dinkumware provided MS with the VC6 C++ library but it is the same as the one for VC5 so the out-of-the-box VC6 C++ standard library is very old, not quite standard as some things were added or changed after it was written, and has a few bugs...check out the Dinkumware site for details on patches and upgrades).

As to std::string::npos we use this with certain values that std::string returns to us it is used to indicate no position and is most often the result of a failed find operation in which cases no position can be read to mean not found.

Note that the various find operations of std::string return a value of the type std::string::size_type which is an alias for (i.e. another name for) an unsigned integer type exactly which unsigned integer type depends on the specific C++ library implementation it could be unsigned long or maybe unsigned short.

A potential problem is that the std::string::npos value is -1 represented as an unsigned integer which on pretty much all modern platforms will be the highest value supported by that integer type (all its bits will be 1s) i.e. we loose the negativity and instead have the largest representable positive value. My C++ library reference (The C++ Standard Library A Tutotial and Reference by Nicolai M. Josuttis) indicates that this may be a problem if you store the found positions in a type other than std::string::size_type due to this oddity. I agree with this as in general mixing signed and unsigned values and integers of different sizes can have problems when the values cross the boundaries of the limits of these types.

However I tried it with various unsigned and signed types using -1 for VC7.1 and could not get a problem. If you would like to see what I mean try the following:

       unsigned short npos(-1);
       long pos(npos);
 
       bool is_pos_npos( pos == npos );
       bool is_npos_pos( npos == pos );

If you set a break point on the line after is_npos_pos and check out the values of npos, pos, is_pos_npos, and is_npos_pos in the debugger you should get 65535, 65535, true, true. Now try it with the following type combinations for npos and pos:

       unsigned long npos(-1);
       long pos(npos);
and
       unsigned long npos(-1);
       short pos(npos);

This should cover the cases where npos is has less bits than pos, npos is the same bit length as pos so the only difference is that npos is unsigned and pos is signed and npos has more bits than pos.

If you do not know how to use the VC6 debugger then I suggest you learn. Hint: to set a breakpoint set the typing position caret in the editor to somewhere on the line you wish execution to break at and press F9 (which may vary depending on your setup). A red circle appears to the left of the line. Pressing F9 again will remove the break point. Some lines cannot be broken on but VC will only complain when you start debugging the program (F5 or Build->Debug->Go or the Go button on the build toolbar). You might also like to enable the Debug tool bar (Tools->Customize->Toolbars). When broken you can use F5 or Go to continue, F10 to step over to the next line without entering a function etc.. You can also examine the value of variables such as npos, pos etc.  

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.