-2

I'd like to automatically move to the next item in a char array in a count_x() function. What does my array initialization need to look like, or how should I pass in my arguments to be able to have the following function work?

int count_x(char* p, char x)
     // count the number of occurrences of x in p[]
     // p is assumed to point to a zero-terminated array of char (or to nothing)
{
     int count = 0;
     while (p) {
          if (*p==x)
                ++count;
          ++p;
     }
     return count;
}

See that third line? The comment? That's nagging me. does zero-terminated mean that the last element in the array is nullptr or something?

btelles
  • 5,390
  • 7
  • 46
  • 78
  • 2
    A third argument that is the length of the array. – Brian Roach Mar 09 '14 at 02:12
  • 1
    Or use `std::vector` instead. – Sebastian Hoffmann Mar 09 '14 at 02:12
  • Brian, according to the book I'm reading (A Tour of C++), I should be able to make p_int_array a zero-terminated array. I'm not quite sure how to do that though. – btelles Mar 09 '14 at 02:13
  • 2
    @btelles Sure, that's option B. A "poison pill" that indicates you're at the end. But for that to work you'd need to be looking at the *value pointed at* by p_int_array, not the memory address; `while(*p_int_array)`. – Brian Roach Mar 09 '14 at 02:15
  • Add a zero to the end and keep iterating until you hit a zero: `while(p_int_array[count])` – yizzlez Mar 09 '14 at 02:15
  • 1
    @awesomeyi No it would be `while(*p_int_array)`. Notice though that if your array is ill-formed your function will utterly fail and chaos and destruction is going to await you at its end. – Sebastian Hoffmann Mar 09 '14 at 02:16
  • 1
    That said - as it is that's not going to work because `0` is the *first* value in your array. You could pass `int**` and then you could *null terminate* the array of `int` pointers. There's any number of approaches to this :) – Brian Roach Mar 09 '14 at 02:24
  • 1
    @btelles Your edit is a *completely different thing*. An array of `char` in C is generally thought of as a "string" where the values map to a character set and the array is null terminated ("NULL" is `0`, and is not a valid character or part of any byte sequence in any charset). – Brian Roach Mar 09 '14 at 02:28
  • Sweet. That helps a bunch Brian. Thanks! In that case, how do I zero-terminate a string? – btelles Mar 09 '14 at 02:37
  • @btelles, did you get the code from "A Tour of C++"? If you did, take a look at [my question](http://stackoverflow.com/questions/22237408/buggy-code-in-a-tour-of-c-or-non-compliant-compiler). – R Sahu Mar 09 '14 at 02:49
  • Where is the `count_if` function? – Shoe Mar 09 '14 at 02:51

2 Answers2

3

The example in your edit and your original code are really two completely different things.

In C, a char[] is used to represent a "string"; a bunch of bytes that are going to be mapped to some character set by the terminal or windowing system for human consumption.

Strings are "null terminated"; by placing a 0 in the array, functions that are operating on the array know that indicates the end of the string. (This is glossing over things a bit, as 0 is defined explicitly to terminate strings in C, and UTF-8 and US-ASCII for example explicitly define 0 as the "null character").

Your first example is dealing with int ... there's no terminating value here, unless you define one as such. This is going to entirely depend on the expected inputs to the method. A simple example would be to define -1 as your "poison pill" and check for that:

Lets say you redefined your array to be:

int v[] = {0,1,2,3,4,5,6,7,8,8,8,9,-1};

Now your while statement would look like:

while(*p_int_array != -1) {

Edit from comments:

Since you edited your Q to be entirely about strings ... A string literal is automatically null terminated:

char *foo = "hi!";

is really:

char foo[] = {'h','i','!', 0}; // or, '\0'  

That said, the example you now show is wrong, and will seg-fault. It needs to be looking at what p is pointing at, not the pointer (memory address) itself.

while (*p) {
Sebastian Hoffmann
  • 11,127
  • 7
  • 49
  • 77
Brian Roach
  • 76,169
  • 12
  • 136
  • 161
1

The best approach would be to use vector from standard library, but you can do this by passing the length of the array and changing the loop or, which is probably the worst solution, but keeps your current approach:

int count_if(int* p_int_array, int * p_last_object, int desired_value)
{
    int count = 0;

    // I want this loop and the ++p_int_array below
    // to work together to iterate through an array.
    while(p_int_array != p_last_object) {
        int current_int = *p_int_array;
        if(current_int == desired_value)
            ++count;
        ++p_int_array;
    }

    return count;
}
void print()
{
    int v[] = {0,1,2,3,4,5,6,7,8,8,8,9};

    int desired_value = 8;

    // What should I pass into count_if, in order to get the
    // loop "while(p_int_array)" to work?
    // Also, do the names adhere to naming conventions in C++
    int count = count_if(&v[0], &v[11], desired_value);

    cout << "There are " << count << " " << desired_value << " in v\n";
}
mcopik
  • 341
  • 2
  • 6