- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我尝试编写自己的 strchr() 方法实现。
现在看起来像这样:
char *mystrchr(const char *s, int c) {
while (*s != (char) c) {
if (!*s++) {
return NULL;
}
}
return (char *)s;
}
最后一行原本是
return s;
但这不起作用,因为 s 是常量。我发现需要这个类型转换 (char *),但老实说我不知道我在那里做什么 :( 有人可以解释一下吗?
最佳答案
我相信这实际上是 C 标准对 strchr()
的定义中的一个缺陷。功能。 (我会很高兴被证明是错误的。)(回复评论,它是否真的是一个缺陷是有争议的;恕我直言,它仍然是糟糕的设计。它可以安全地使用,但它太容易了不安全地使用它。)
这是 C 标准所说的:
char *strchr(const char *s, int c);
The strchr function locates the first occurrence of c (converted to a char) in the string pointed to by s. The terminating null character is considered to be part of the string.
这意味着这个程序:
#include <stdio.h>
#include <string.h>
int main(void) {
const char *s = "hello";
char *p = strchr(s, 'l');
*p = 'L';
return 0;
}
尽管它小心地将指向字符串文字的指针定义为指向 const
的指针 char
, 具有未定义的行为,因为它修改了字符串文字。至少 gcc 不会对此发出警告,程序会因段错误而终止。
问题是 strchr()
需要 const char*
参数,这意味着它 promise 不会修改 s
的数据指向 -- 但它返回一个普通的 char*
, 这允许调用者修改相同的数据。
这是另一个例子;
它没有未定义的行为,但是
它悄悄地修改了一个const
没有任何强制转换的合格对象(经过进一步思考,我相信它具有未定义的行为):
#include <stdio.h>
#include <string.h>
int main(void) {
const char s[] = "hello";
char *p = strchr(s, 'l');
*p = 'L';
printf("s = \"%s\"\n", s);
return 0;
}
这意味着,我认为(回答您的问题)strchr()
的 C 实现必须将其结果转换为 const char*
至 char*
,或做一些等效的事情。
这就是为什么 C++ 在对 C 标准库所做的少数更改之一中替换了 strchr()
。具有两个同名的重载函数:
const char * strchr ( const char * str, int character );
char * strchr ( char * str, int character );
C当然做不到。
替代方案是替换 strchr
通过两个函数,一个取 const char*
并返回 const char*
, 另一个服用 char*
并返回 char*
.与 C++ 不同,这两个函数必须具有不同的名称,可能是 strchr
。和 strcchr
.
(历史上,const
是在定义了 strchr()
之后添加到 C 中的。这可能是保留 strchr()
而不破坏现有代码的唯一方法。)
strchr()
不是唯一有此问题的 C 标准库函数。受影响的功能列表(我认为这个列表是完整的,但我不保证)是:
void *memchr(const void *s, int c, size_t n);
char *strchr(const char *s, int c);
char *strpbrk(const char *s1, const char *s2);
char *strrchr(const char *s, int c);
char *strstr(const char *s1, const char *s2);
(全部在 <string.h>
中声明)和:
void *bsearch(const void *key, const void *base,
size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
(在 <stdlib.h>
中声明)。所有这些函数都带有指向 const
的指针。指向数组初始元素的数据,并返回非 const
指向该数组元素的指针。
关于c - strchr 实现如何工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14367727/
我正在研究 CS50 习题集。在此函数中,我迭代一行以确保它符合某些规则:“方法 SP 请求-目标 SP HTTP-版本 CRLF”,其中 SP 是空格,CRLF 是回车/换行符。 我通过字符串的最后
我对 C 语言还很陌生,因为我只是将其作为入门类(class),并且我遇到了家庭作业问题。该程序的目标是将字符串类型的数组名称和动态选择的字符从循环传递给函数。该函数必须检查字符串中是否有所选字符,如
我正在查看 strchr() 的示例:http://www.cplusplus.com/reference/cstring/strchr/ 为什么这样可以正确找到索引?直觉上它看起来应该给出负索引:
我不明白为什么下面的 C 代码不起作用: int obtainStringLength(char* str, char c1, char c2) { char* firstOcurrence
我在以下代码中收到错误assignment makes pointer from integer without a cast,这是什么意思? char * splitter; if(splitter
这个问题在这里已经有了答案: Why does strchr take an int for the char to be found? (4 个答案) 关闭 5 年前。 尝试创建一个简单的函数来查
我尝试编写自己的 strchr() 方法实现。 现在看起来像这样: char *mystrchr(const char *s, int c) { while (*s != (char) c)
我的学期快结束了,我正在写一个函数来查找字符串中某个字符的编号,给定老师分配的函数原型(prototype)。我知道我一定是在做一些愚蠢的事情,但是这段代码要么被锁定,要么在我的函数中无限循环。 这是
我的任务是编写我自己的 strchr 版本,但它似乎不起作用。任何建议将不胜感激。这是: char *strchr (const char *s, int c) //we are looking fo
#include #include int main () { const char str[] = "http://www.tutorialspoint.com"; const ch
这行代码给我带来了段错误: g_object_set(G_OBJECT(data.udpsrc), "port", 5000, "caps", caps, NULL); 哪里 data.udpsrc
我正在使用一个用 C 编写的程序,该程序涉及比较带连字符的姓氏。例如,它可能会将 Mary Jay-Blige 与 Mary Kay-Blige 进行比较。查找连字符并将变量设置为其位置的代码是: A
我正在尝试重载 >> 运算符以读取单个(使用 enum Symbol {e,a,b,c,d}; 创建)符号: istream & operator >> (istream & is, Symbol &
我正在为 C++ 练习编写 ROT13。但是这里的这段代码返回错误并且无法编译,我不明白为什么!我在以下几行中发布了一段代码 string encode(string &x) { char a
所以我正在尝试检查一个字符串,看看它是否: 有 8 个或更多字符 至少有一个大写字母 至少有一个小写字母 至少有以下字符之一 .,?!;:_!@# 这是我的代码: #include #include
这个问题在这里已经有了答案: How does strchr implementation work (5 个答案) 关闭 7 年前。 char a[20]="this is"; cout<
我想处理字符(运算符)来操作一些数字。但关键是角色来自堆栈。当我声明 Char 类型堆栈并使用 top() 方法获取字符(运算符)时,它在 strchr 函数中不起作用。我不知道为什么。我真的很想知道
我正在深入研究 C 中的指针和字符串,但我仍然不习惯一些概念。我尝试实现 strchr() 函数的一个版本——与 string.h 中的相同——出于学习目的,但一些基本的东西仍然不正确。 这是我的代码
我有以下内容: LPSTR email // Has data in it already LPSTR index=strchr(email,'@'); 现在我想插入一个新字符串: LPSTR use
我正在为一个类(class)编写一个 C 程序,该类(class)要求我获取请求行并将其分解为后续部分。这是出于学习目的,所以我可以期待一个相当标准的请求行。 考虑到这个问题,我打算使用某种 for(
我是一名优秀的程序员,十分优秀!