-1

I have a function,

string readWord(string line, int start) {
    int i = 0; string out = "";
    while(line[start + i] = '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' || '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') {
        i++;
        out = out + line[start + i];
    }
    return out;
}

The function didn't give me any compiler errors or warnings, so I decided to see if it worked. I printed readWord("Word1 Word(2) Word3", 0), and it gave me "free(): invalid pointer." Do you know how I can get it to do what I want?

Evg
  • 25,259
  • 5
  • 41
  • 83
Sig Moid
  • 31
  • 4
  • `line[start + i] = 'a'` is assignment, not comparison. – 273K Jul 26 '23 at 00:56
  • `'a' || 'b' ||` does not do what you think it does. – 273K Jul 26 '23 at 00:57
  • You missed the end condition for the loop. – 273K Jul 26 '23 at 00:57
  • 2
    Enable -Wall -Wextra -Werror – 273K Jul 26 '23 at 00:59
  • IMHO, a better method: `while (strchr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", line[start + i]) != nullptr)` – Thomas Matthews Jul 26 '23 at 01:17
  • You could simplify: `while (isalpha(line[start + i]))`. I recommend **transform**ing the string to all lowercase or all upper case before comparisons. – Thomas Matthews Jul 26 '23 at 01:19
  • Debugging tip: at the end of your loop body (after updating `i` and `out`), add some diagnostic output: `std::cout << "End of loop: i is " << i << " and out is " << out << ".\n";` Notice anything odd going on? (You didn't say what this function is supposed to do, but at a guess, there is a third bug, less serious than the two already mentioned.) – JaMiT Jul 26 '23 at 02:01
  • [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) – Jesper Juhl Jul 26 '23 at 08:34

3 Answers3

3

As noted in comments, you have multiple issues which likely come down to confusion about C++'s basic syntax.

line[start + i] = 'a' is an assignment and not a comparison. Incidentally, it's also "true."

You were probably looking for line[start + i] == 'a' to compare the two for equality.

Second, you cannot check multiple values for equality against a single value with expressions of the form a == b || c || d.

There are varying approaches to this, but the simplest would probably be a == b || a == c || a == d.

More succinct in your case would be to include <cctype> and then:

string readWord(string line, int start) {
    int i = 0; string out = "";
    while(std::isalpha(line[start + i])) {
        i++;
        out = out + line[start + i];
    }
    return out;
}

Or, leveraging C++ techniques a bit more, we can find the first character that doesn't match with a letter of the alphabet, and use that iterator along with a start iterator to initialize a new string.

#include <cctype>
#include <string>
#include <iostream>

int main() {
    std::string s = "hello world!";
    
    auto end = std::find_if(
      s.begin(), s.end(), 
      [](auto &c){ return !std::isalpha(c); }
    );

    // C++20:
    // auto end = std::find_if_not(s.begin(), s.end(), std::isalpha);

    std::string s2(s.begin(), end);

    std::cout << s2 << std::endl;
}

The above will print "hello".

Chris
  • 26,361
  • 5
  • 21
  • 42
0

The = operator is the assignment operator as opposed to the comparison operator == which you should be using in this case.

If you want to compare a variable against multiple values, you should use the following syntax:

while(x == 1 || x == 2 || x == 3) // etc.

Another issue in your code is that you're incrementing i too early, it should be after the assignment to out. Here is a demonstration on how to fix the issues in your code:

#include <iostream>       
#include <string>

std::string readWord(std::string line, int start)
{
    int i = 0;
    std::string out = "";

    while (line[start + i] == 'a' || line[start + i] == 'b')
    {
        out += line[start + i];
        i++;
    }
    return out;
}

int main()
{
    std::string A = readWord("a012b3", 0);
    std::cout << A << std::endl;
    return 0;
}
machine_1
  • 4,266
  • 2
  • 21
  • 42
-1

The comments below explain some the issues that I think you were having trouble with. Hope this helps!

This is a complete program. It runs.

#include <iostream>
#include <string>

// Avoid `using namespace std;`.
// Instead, just write out `std::` every time you use `string` or `cout`.

bool is_alpha(char const c) 
{
    // Check out function `std::isalpha` found in header `<cctype>`. 
    // It does something similar to what this function is doing.
    return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
}

// `std::string const&` means `reference to const std::string`. 
// It reads backwards from right-to-left. This method for passing strings 
// is usually more efficient when you do not want to modify them.
//
// `int&` means `reference to int` (also reading backwards).
// By using this as the type for parameter `pos`, you make it so that 
// changes made to `pos` in this function also happen in the calling 
// routine. When this routine it finished, `pos` will have been changed 
// to the position where we stopped in this function.
// 
std::string readWord(std::string const& line, int& pos) 
{
    std::string out;
    while (pos < line.size() && is_alpha(line[pos]))
    {
        out.push_back(line[pos]);  // add one character to the end of string `out`
        ++pos;  // prefer `prefix increment` over `postfix increment` for most uses
    }
    return out;
}

void skip_over_non_letters(std::string const& line, int& pos)
{
    while (pos < line.size() && !is_alpha(line[pos]))
    {
        ++pos;
    }
}

int main()
{
    std::string line{ "Rock 'n roll rules the world." };
    std::string word;
    int pos = 0;
    while (pos < line.size())
    {
        skip_over_non_letters(line, pos);
        if (pos < line.size())
        {
            word = readWord(line, pos);
            std::cout << word << '\n';
        }
    }
    return 0;
}

Running it produces the following output:

Rock
n
roll
rules
the
world
tbxfreeware
  • 547
  • 1
  • 9
  • Best to not reinvent the wheel. https://en.cppreference.com/w/cpp/string/byte/isalpha – Retired Ninja Jul 26 '23 at 02:26
  • 1
    Yep. That's why I mentioned `std::isalpha` in the comments. The reason I wrote a custom `is_alpha` was so that the original poster would see one way to code the test he was obviously trying to write. – tbxfreeware Jul 26 '23 at 03:18
  • This doesn't appear to address the actual problems in the OP's code. – Chris Jul 26 '23 at 04:24
  • Admittedly, I took a few liberties. I was trying to put his code in context. As best I could figure, his `readWord` was meant to parse words from a line. The fact that he has parameter `start` hints that `readWord` is meant to be called multiple times on the same `line`. That's why I changed his input (i.e., value) parameter `start` to an in/out (reference) parameter. If you change it back, my `readWord` does _exactly_ what his was attempting. As for the rest of my solution, I think it puts `readWord` in the context the original poster intended. But, I admit, that's a whole lot of surmising. – tbxfreeware Jul 26 '23 at 05:34