简体   繁体   English

从头开始在 C 中创建 strstr function,但使用修改后的字符串

[英]Create the strstr function in C from scratch, but with modified strings

To summarize, if the function is given arguments char *str1 = "Watch out the streets?";总而言之,如果 function 被赋予 arguments char *str1 = "小心街道?"; char *str2 = "street?";, it should return a pointer in str1 to the first instance of "street", starting from s. char *str2 = "street?";,它应该返回 str1 中指向 "street" 的第一个实例的指针,从 s 开始。

I am completely stuck and appreciate any help.我完全被卡住了,感谢任何帮助。 I have a feeling my problem is with pointers.我感觉我的问题出在指针上。 I'm a beginner as you might imagine.正如你想象的那样,我是一个初学者。

I just edited the code to my latest attempt.我刚刚将代码编辑为我最近的尝试。 I am very close, but cannot still find the idea to modify the first string.我非常接近,但仍然找不到修改第一个字符串的想法。

Output image: Output 图像:

输出图像

    const char *qstr_strstr(const char *str1, const char *str2) {
    int j = 0;
    char newstr2[256];
    while (str2[j]) {  
        if (str2[j] == '?') {  
            break;  
        } else {
            newstr2[j] = str2[j];
        }
        j++;
    }
    newstr2[j] = '\0';
    size_t n = strlen(newstr2);
    while(*str1) {
        if (!memcmp(str1++, newstr2, n)) {
            return (str1 - 1);
        }
    }
    return NULL;
}

You are heading in the right direction, and you are starting to think about stepping through stings correctly, but you are getting wrapped up in your use of any additional string -- there is no need for that.您正朝着正确的方向前进,并且您开始考虑正确地通过刺痛,但是您正在使用任何额外的字符串 - 没有必要这样做。

When you are analyzing stings and substrings, all you care about is:当您分析字符串和子字符串时,您只关心:

  1. the index (position) within the original string (to iterate);原始字符串中的索引(位置)(迭代);
  2. whether you have found the beginning of the substring yet (if so set flag indicating in word matching chars);您是否已经找到 substring 的开头(如果是,则设置在单词匹配字符中指示的标志); and
  3. whether you make it all the way to the end of the substring while your flag is set (if you do, you have found your substring).在设置标志时是否一直到 ZE83AED3DDF4667DEC0DAAAACB2BB3BE0BZ 的末尾(如果这样做,您已经找到了子字符串)。 Otherwise, if there is a mismatch in characters before reaching the end, unset your flag and keep going.否则,如果在到达结尾之前字符不匹配,请取消设置标志并继续前进。 Repeat until you run out of str1 .重复直到你用完str1

Complicating your case here is the Red-Herring '?'使您的情况复杂化的是红鲱鱼'?' character.特点。 You can either use it as a test for end-of-substring, or ignore it altogether.您可以将其用作子字符串结尾的测试,也可以完全忽略它。 Your goal is to locate str2 "street" within str1 "... streets?"您的目标是在str1 "... streets?"中找到str2 "street" . . You would generally use ispunct() from ctype.h to identify '?'您通常会使用ctype.h中的ispunct()来识别'?' as a non-word character and not part of the string anyway.作为非单词字符,无论如何都不是字符串的一部分。 Here, you can simply check for '?'在这里,您可以简单地检查'?' in a similar way that you would check for '\0' to mark end-of-string .以类似的方式检查'\0'以标记end-of-string

Putting it altogether and not using any of the string.h or ctype.h functions, you could do:把它放在一起而不使用任何string.hctype.h函数,你可以这样做:

#include <stdio.h>

const char *qstr_strstr (const char *str1, const char *str2)
{
    int i = 0, instr2 = 0, ndx = 0;         /* str1 index, in-str2 flag, str2 index */
    
    if (str1 == NULL || str2 == NULL)       /* validte both str1 and str2 not NULL */
        return NULL;
    
    do {    /* loop over each char in str1 */
        /* if in str2 and (at end or at '?') */
        if (instr2 && (!str2[ndx] || str2[ndx] == '?'))
            return &str1[i-ndx];            /* return address in str1 to start of str2 */
        /* if char in str1 and str2 equal */
        if (str1[i] == str2[ndx]) {
            ndx += 1;                       /* increment str2 index */
            instr2 = 1;                     /* set in-str2 flag true (done each time) */
        }
        else    /* otherwise chars not equal */
            ndx = instr2 = 0;               /* reset str2 index, set in-str2 flag false */
    } while (str1[i++]);                    /* includes \0, allows match at end of both */
    
    return NULL;
}

int main (void) {
    
    const char *str1 = "Watch of the streets?",
               *str2 = "street?",
               *ptr = qstr_strstr (str1, str2);
    
    if (ptr) {
        size_t i = ptr - str1;
        printf ("ptr       : %s\nptr addr  : %p\n---\n"
                "&str1[%zu] : %s\n&str1[%zu] : %p\n",
                ptr, (void*)ptr, i, str1 + i, i, (void*)(str1 + i));
    }
}

Example Use/Output示例使用/输出

Outputting the string and adderss retuned by qstr_strstr() as well as the address of that string and address located within the original str1 you would have:输出由qstr_strstr()重新调整的字符串和 adderss 以及该字符串的地址和位于原始str1中的地址,您将拥有:

$ ./bin/strstrawk
ptr       : streets?
ptr addr  : 0x4006c1
---
&str1[13] : streets?
&str1[13] : 0x4006c1

You can further copy just the substring street from the address in str1 or whatever else you need to do.您可以进一步从str1中的地址复制 substring street或您需要做的任何其他事情。 Look things over and let me know if you have further questions.如果您还有其他问题,请仔细查看并告诉我。


Edit Based On Picture Added根据添加的图片编辑

If you want to output just the characters before the '?'如果你想 output 只是'?'之前的字符from the pointer returned by qstr_strstr() , then you can do that trivially by using the precision modifier with the "%s" output conversion specifier in your printf format string and limit the number of characters output to just the number before the '?' from the pointer returned by qstr_strstr() , then you can do that trivially by using the precision modifier with the "%s" output conversion specifier in your printf format string and limit the number of characters output to just the number before the '?' in str2 .str2中。 Your format conversion specifier would look like "%.*s" where it expects 2 arguments, the first of type int being the number of characters, and the second the string.您的格式转换说明符看起来像"%.*s" ,它需要 2 个 arguments,第一个int类型是字符数,第二个是字符串。

In the case above the arguments would be:在上述情况下,arguments 将是:

            (int)strcspn (str2, "?"), ptr

Where strcspn() returns the number of characters before the '?'其中strcspn()返回'?'之前的字符数in str2 (cast to int ) and ptr the return from qstr_strstr() .str2 (转换为int )和ptrqstr_strstr()返回。 Changing the code above you would have:更改上面的代码,您将拥有:

...
#include <string.h>
...
        printf ("ptr       : %.*s\nptr addr  : %p\n---\n"
                "&str1[%zu] : %s\n&str1[%zu] : %p\n",
                (int)strcspn (str2, "?"), ptr, (void*)ptr, 
                i, str1 + i, i, (void*)(str1 + i));

(the remaining code is unchanged) (其余代码不变)

$ ./bin/strstrawk
ptr       : street
ptr addr  : 0x4006c1
---
&str1[13] : streets?
&str1[13] : 0x4006c1

Where the output using ptr as the string and the length from str2 is not "street" .其中 output 使用ptr作为字符串并且str2的长度不是"street"

Let me know if you have further questions.如果您还有其他问题,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM