我有两个C风格的字符串:

char st[100] = "to be  or not to be ";
char sub_s[100] = "be";


我需要用strstr(st, sub_s)查找“ be”的开头并将其更改为大写字母。新字符串必须为“”,否则为“;”;

我设法做到了没有这样的功能:

void main()
{
    char st[100] = "to be  or not to be ";
    char sub_s[100] = "be";
    char* p;
    int i;

    while (p = strstr(st, sub_s))
    {
        for (i = 0; i < strlen(sub_s); i++)
        {
            p[i] -= 32;
        }
    }

    printf("%s\n", st);
}


但是,当我将此代码放入其自己的函数中时,它将不再起作用:

void main()
{
    char st[100] = "to be  or not to be ";
    char sub_s[100] = "be";
    replaceSubstring(st, sub_s);
}

void replaceSubstring(char* str, char* substr)
{
    int* p;
    int i;

    while (p = strstr(str, substr))
    {
        for (i = 0; i < strlen(substr); i++)
        {
            p[i] -= 32;
        }
    }

    printf("%s\n", st);
}


这里发生了什么?

最佳答案

在编写的函数中,将p的类型设置为int*,而不是char *。这意味着当你写

p[i] -= 32;


编译器将假定p指向的每个元素都是int,因此在内存中采用的大小为sizeof(int),而不是在内存中采用的大小为1。换句话说,代码被解释为

Start at the location pointed at by p.
Jump forward i * sizeof(int) bytes.
Read an integer value from that location.
Subtract 32 from it.
Write it back


而不是

Start at the location pointed at by p.
Find the character i steps down from there.
Subtract 32 from that character.


要解决此问题,请将p的类型更改为char*,而不是int*

如果将编译器警告级别提高到最高水平,可能会很容易检测到这种错误。我强烈建议您在学习编码时这样做,然后询问有关您不理解的警告的问题。

其他一些流浪笔记:


main的返回类型应为int,而不是void
可以使用tolower标头中的<ctype.h>函数,而不是从每个字符中减去32(这是有效的,但不是单词中最清楚的东西)。
如果您要搜索的子字符串仅由非字母字符(例如":-)")组成,则此代码可能导致无限循环。你明白为什么吗?考虑一下如何解决。

关于c - 大写单词的所有副本:为什么此代码在其自身功能中失败?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41769472/

10-11 22:13
查看更多