Design a Character Searching Function, While Forced to Use strchr

时间:2018-03-22 23:57:25

标签: c algorithm search

Background Information

I was recently approached by a friend who was given a homework problem to develop a searching algorithm. Before anyone asks, I did think of a solution! However, my solution is not what the teacher is asking for...

Anyway, this is an introductory C programming course where the students have been asked to write a search function called ch_search that is supposed to search an array of characters to determine how many times a specific character occurs. The constraints are what I don't understand...

Constraints:

  1. The arguments are: array to search, character to search for, and length of the array being searched.
  2. The function must use a for-loop.
  3. The algorithm must use the strchr function.

Okay, so the first two constraints I can understand... but the 3rd constraint is what really gets me... I was initially thinking that we could just use a for-loop to iterate through the string from the beginning to the end, simply counting each instance of the character. When the student originally described the problem to me, I came up with (although incorrect) the solution:

Proposed Solution

int ch_search(char array_to_search[], char char_to_search_for, int array_size)
{
    int count = 0;

    for (int i = 0; i < array_size; i++)
    {
        // count each character instance
        if (array_to_search[i] == char_to_search_for)
        {
            // keep incrementing the count
            count++;
        }
    }

    return count;
}

Then I was told that I had to specifically use the character position function (and apparently it has to be strchr and not strrchr so we can't start at the end I guess?)... I just don't see how that wouldn't be overcomplicating this. I don't see how that would help at all, especially counting from the beginning... Even strrchr might make a little more sense to me. Thoughts?

4 个答案:

答案 0 :(得分:2)

It's true that having the length of the array and having to use a for loop, the most natural thing to do would be to iterate over every characters of the source array. But you can also loop over the result of strchr like this:

int ch_search(char haystack[], char needle, int size)
{
    int count = 0;

    char *found;

    for(; (found = strchr(haystack, needle)) != NULL; haystack = found + 1)
        count++;

    return count;
}

In this case you don't need the size of the array but the assignment doesn't say that you have to use it. Obviously this solution requires the source to be '\0'-terminated.

答案 1 :(得分:0)

I think the teacher wanted you to use strchr to navigate to the next occurrence of the char_to_search_for within a string:

int ch_search(char array_to_search[], char char_to_search_for, int array_size) {
    int count = 0;
    for (char *ptr = array_to_search ; ptr != &array_to_search[array_size] ; ptr++) {
        ptr = strchr(ptr, char_to_search_for);
        if (!ptr) {
            break; // Character is not found
        }
        count++;
    }
    return count;
}

Note that array_to_search must be null-terminated in order to be used together with strchr solution above.

答案 2 :(得分:0)

strchr is a very convenient function to search for a char in a string.

Find and read more about strchr. This is my favorite function ever!

The C library function char *strchr(const char *str, int c) searches for the first occurrence of the character c (an unsigned char) in the string pointed to by the argument str.

Declaration

Following is the declaration for strchr() function.

char *strchr(const char *str, int c)

Parameters

  • str − This is the C string to be scanned.

  • c − This is the character to be searched in str.

Return value

Function returns a pointer to the first occurrence of the character c in the string str, or NULL if the character is not found.

Constraints:

1) The arguments are: array to search, character to search for, and length of the array being searched.

This constrain gives the length of the array to be searched. The given array has to contain '\0' at some point. However the length of search search can be shorter and specified by the search_length.

Following compact solution takes this under account.

int ch_search(char array_to_search[], char char_to_search_for, int search_length)
{
    int count = 0;
    for(char *p = array_to_search; ;p++)
    {
        p = strchr(p, char_to_search_for);
        if( p != NULL && (p - array_to_search < search_length) )
            count++;
        else
            break;
    }
    return count;
}

Or equivalent ch_search2:

#include<stdio.h>
#include<string.h>

int ch_search(char array_to_search[], char char_to_search_for, int search_length)
{
    int count = 0;
    for(char *p = array_to_search; ;p++)
    {
        p = strchr(p, char_to_search_for);
        if( p != NULL && (p - array_to_search < search_length) )
            count++;
        else
            break;
    }
    return count;
}

// Your original function:
int ch_search1(char array_to_search[], char char_to_search_for, int array_size)
{
    int count = 0;  
    for (int i = 0; i < array_size; i++){
        // count each character instance
        if (array_to_search[i] == char_to_search_for){
            count++;  // keep incrementing the count
        }
    }
    return count;
}

int ch_search2(char array_to_search[], char char_to_search_for, int array_size)
{
    int count = 0;
    char *p = array_to_search;

    for(;;)
    {
        p = strchr(p, char_to_search_for);
        if( p != NULL )
        {
            if (p - array_to_search >= array_size) // we reached beyond 
            {
                break;
            }
            else
            {
                count++;
                p++;
            }               
        }
        else
           break;  // char not found

    }
    return count;
}

int main(void)
{
    // the arr has to contain '\0' terminator but we can search within the specified length.
    char arr[]={'1','1','2','2','1','1','3','3','3','1','4','4', '1','1','!','1','\0','1'}; 
    char arr1[] = "zdxbab";

    printf("count %d count %d \n",ch_search(arr , '1', 12),ch_search2(arr , '1', 12));
    printf("count %d count %d \n",ch_search(arr1,'b',strlen(arr1)),ch_search2(arr1,'b',strlen(arr1)));

    return 0;
}

Output:

count 5 count 5                                                                                                                              
count 2 count 2

答案 3 :(得分:0)

这听起来像你的朋友被给了一个技巧问题。该函数获取一个字符数组和该数组的长度但是需要使用strchr(),即使该函数仅适用于'\0'终止的字符串(并且没有任何保证该数组为{ {1}}已终止。

你可能认为在数组上使用'\0'然后将返回的指针与数组的给定长度进行比较以检查它是否超过了数组的末尾。但是有两个问题:

  • 如果strchr()搜索超出数组末尾,那么在进行检查之前,您已经有未定义的行为。程序可能在从strchr()返回之前崩溃,返回的指针可能是一些总垃圾,或者你可能得到一个指向地址的指针比内存的结尾更远。
  • 即使返回的指针只是位于内存中比地址末端更远的地址,那么存在的问题是比较两个指针(或减去它们以找到指向的地址之间的距离)是未定义的行为除非它们都指向同一个内存对象的一部分(或者超过对象末尾的一个位置)。在这个例子中,它意味着检查返回的指针是否在数组的边界内只是定义了行为,如果返回的指针在数组的边界内(或一个超过结束),使得检查有点无用。

唯一的解决方案是确保strchr()使用strchr()终止字符串。例如:

'\0'