-1
#include <iostream>
#include <string>

using namespace std;
int score(string s);
char scrabbleLetters[] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
int scrabblePoints[] = {1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10};

int main()
{
    string sWord;
    cout << "Enter the scrabble word you'd like to score.";
    cin >> sWord;
    cout << "You scored " << score(sWord)<< " points for that word!";

}

int score(string s)
{   int points = 0;
    for (int i = 0; i < s.length(); i++)
    {
        for (int j = 0; j < scrabbleLetters.length(); j++)
        {
            if (s[i] == scrabbleLetters[j])
                points += scrabblePoints[j];
        }
    }
    return points;
}

I can't seem to figure out why my code isn't compiling. The program is supposed to ask a user for a word and then score the word based on points per letter.

The current error I'm receiving is: "error: request for member 'length' in 'scrabbleLetters', which is of non-class type 'char [26]'|"

Ron
  • 51
  • 1
  • 4

3 Answers3

2

C++ built-in arrays don't have a length() member function. One way to find the size is to use

for (int i = 0; i < std::distance(std::begin(s), std::end(s)); ++i) {
    ...
}

Given that the above approach is a bit ugly, it is possible to package it up a function, e.g.:

template <typename T, std::size_t Size>
constexpr std::size_t length(T const (&)[Size]) {
    return Size;
}
...
for (std::size_t i(0); i != length(s); ++i) {
    ...
}

Specifically for an array of char (or, in general for any type T with sizeof(T) == 1) is to use sizeof(s). Note, however, that this does not work for types where sizeof(T) != 1. You may be better off not to use a built-in array but rather use a std::vector<char>:

std::vector<int> s{'a', 'b' /*...*/ };
for (std::size_t i(0); i != s.size(); ++i) {
    ...
}
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • Your answer is much better than what I was going to put lol. +1 for you when my upvote recharges. – John Odom Nov 05 '14 at 20:55
  • This answer will suffer if the array is decayed, by, i.e., passing it to a function as a parameter – LoPiTaL Nov 05 '14 at 21:15
  • @LoPiTaL: you mean, the first two code samples will - correctly - not compile in that case, alerting the user to the problem? ... motivating further to change to use `std::vector`? – Dietmar Kühl Nov 05 '14 at 21:19
  • Yes, sorry. I have not commented here the compile-time error (see my comment in Sahu answer), but it is true. It will fail to compile, which, at least, tells you that something happened. `std::vector` would be a really better solution than the others. – LoPiTaL Nov 05 '14 at 21:23
0

You could eliminate the search and use direct access.

  1. Convert the string to all lowercase
  2. Subtract 'a' from the letter to get a relative offset.
  3. Use the relative offset as an index into the points array

Here's some code snippet examples:

const unsigned int scrabblePoints[] =
{1, 3, 3,  2, 1, 4, 2, 4, 1, 8, 5, 1,  3,
 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10};

int main()
{
    string sWord;
    cout << "Enter the scrabble word you'd like to score.";
    cin >> sWord;

    // Transform the word into all lowercase.
    std::transform(sWord.begin(), sWord.end(), sWord.begin, std::tolower);

    unsigned int points = 0;
    for (unsigned int i = 0; i < sWord.length(); ++i)
    {
       const char c = sWord[i];

       // Check if the character is a letter,
       //    it could be something like '?'.
       if (isalpha(c))
       {
         // Since the point's array starts with the letter 'a',
         // the index can be calculated by subtracting 'a' from
         // the character.
         unsigned int index = c - 'a';
         points += scrabblePoints[index];
       }
    }
    cout << "You scored "
         << points
         << " points for that word!"
         << "\n";
  return 0; // Since main() returns a value.    
}
Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
-1

Couple of more ways to solve the problem (in addition to the answer by Dietmar Kühl)

  1. Compute the length of the array holding the scrabble letters before looping starts.

    int score(string s)
    {
       int points = 0;
       int len = sizeof(scrabbleLetters);
       for (int i = 0; i < s.length(); i++)
       {
          for (int j = 0; j < len; j++)
          {
             if (s[i] == scrabbleLetters[j])
                points += scrabblePoints[j];
          }
       }
       return points;
    }
    

    Word of caution: This approach is brittle. The definition of scrabbleLetters must be visible to the function for this to work. Otherwise, sizeof(scrabbleLetters) will end up being sizeof(char*), which will not work.

  2. A much better approach - avoid the inner loop altogether.

    int score(string s)
    {
       int points = 0;
       for (int i = 0; i < s.length(); i++)
       {
          char ch = s[i];
          points += scrabblePoints[ch-'a'];
       }
       return points;
    }
    
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Your first solution will suffer if the array is decayed, by, i.e., passing it to a function as a parameter. That solution is even worse than Dietman Kuhl's one, since his would throw a compile-time error, while yours will silently compile sizeof(scrabbleLetters) as sizeof(char *) – LoPiTaL Nov 05 '14 at 21:18
  • @LoPiTaL, I realize that. The place where it is being used, the full declaration of the variable is visible. Hence `sizeof` will evaluate to the number of elements in the array since its elements are of type `char`. – R Sahu Nov 05 '14 at 21:22