Using pointers to iterate through char

Write your question here.

1
2
3
4
5
6
7
8
9
10
11
12
13
/* this functions return true if line matches pattern 
e.g
p_r('joker kills batman', 'bat') --> return 1.
p_r('joker laugh', 'bat') --> return 0. 
p_r('joker kills batman', '%bat%') --> return 0 
p_r('joker kills batman', '%batman%') --> return 1   
p_r('joker kills batman', '%batma%%') --> return 0 with an error message saying "invalid special case"
*/

  int p_r(char *line, char *pattern) {

       return 0;
}


My thoughts: So I will have two pointers. A pointer for line and a pointer for pattern. If both pointer successfully increment to the end the function will return true. The problem is I don't know how to implement the special case %???%. Also, pointers are not like arrays right? so how can a pointer increment to the "end".
Last edited on
Also, pointers are not like arrays right? so how can a pointer increment to the "end".

A "feature" from C that C++ inherited is that arrays decay to pointers.
This means that whenever you use the name of an array, it becomes a pointer to the first element.

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

int main()
{
    int arr[30];

    if (arr == &arr[0])
    {
        std::clog << "arr is the same as &arr[0],\n";
        std::clog << "(which is the memory address of the first element)\n";
    }
}


Unfortunately because of this "decay" the size information is lost when you pass the array to a function.

So what can you do?

1) Use std::strlen() inside p_r() to find out the sizes of line and pattern.
2) Change p_r() to also accept lengths of line and pattern.
3) Use C++ strings (std::string) like any C++ programmer would.

Example C++ code for 1):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <cstddef>
#include <cstring>

// ...

// you should use pointers to const char instead of pointers to char,
// because you probably don't intend to change the original line and pattern
int p_r(const char *line, const char *pattern)
{
    const std::size_t line_len = std::strlen(line);
    const std::size_t pattern_len = std::strlen(pattern);

    // ...
}


If you're programming in C, the code above uses different header names and the std:: qualifiers must be removed.

1
2
3
4
5
6
7
8
9
10
11
12
#include <stddef.h>
#include <string.h>

// ...

int p_r(const char *line, const char *pattern)
{
    const size_t line_len = strlen(line);
    const size_t pattern_len = strlen(pattern);

    // ...
}


Example C code for 2):

1
2
3
4
5
6
7
8
#include <stddef.h>

// ...

int p_r(const char *line, size_t line_len, const char *pattern, size_t pattern_len)
{
    // ...
}


Example C++ code for 3) (this is the "proper" way to do this in C++):

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>

// ...

// pass line and pattern as const references for performance
int p_r(const std::string &line, const std::string &pattern)
{
    std::clog << "length of line is: " << line.length() << '\n';
    std::clog << "length of pattern is: " << pattern.length() << '\n';

    // ...
}


If you want to be able to modify line inside p_r() and without changes being visible outside p_r(), simply pass line by value instead of by const reference:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>

// ...

int p_r(std::string line, const std::string &pattern)
{
    line = "Hello.";
    // in this function we have our own local copy of line, so
    // we can freely change its contents to whatever we want

    // ...
}


The problem is I don't know how to implement the special case %???%. Also, pointers are not like arrays right?

One approach could be splitting the line into words (words being separated by whitespace). From the example in your original post this should work fine because there is no punctuation.

Then the "%word%" pattern means that the "word" has to match completely.
Remove the percent signs % then check each words in line, against "word".

Splitting the line into words can be done easily by using C++ string streams.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <cstddef>
#include <iostream>
#include <sstream>
#include <string>

int main()
{
    const std::string line = "Batman defeats the Joker in the end";

    std::stringstream words(line);
    std::string current_word;
    std::size_t count = 0;

    while (words >> current_word)
    {
        std::cout << "Word number " << count << " is: \"" << current_word << "\"\n";
        ++count;
    }

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


If you're programming in C, then instead of C++ string streams you will use the function strtok(), described here:

http://www.cplusplus.com/reference/cstring/strtok/

Finally, your task seems to be about implementing a simple regular expressions (regex) library.

Because pattern matching is very useful feature for a programming language to have, C++ already has one regex library of its own.

http://www.cplusplus.com/reference/regex/
Last edited on
Topic archived. No new replies allowed.