替换字符串中的字符的问题
problem with replacing characters in a string
目前,我正在尝试编写一个代码,用字母 'A'.
替换字符串中的第 1、3、5 个字符...(奇数)
E.x:'hello world' 将是 'AeAlA AoAlD'。
但是相反,我得到 'hAllA AArld' 这不是我想要的结果。
有人可以帮帮我吗?
编辑:问题是我检查了ASCII table,ASCII table中字母'e'、'o'、'w'的值是奇数,其他字母不是。所以我的程序正在检查字母的值是否为奇数或不替换为 'A' 而不是字符串中的第 1、3、5 个字符。
代码如下:
#include <stdio.h>
#include <string.h>
int main() {
char str1[100];
scanf("%[^\n]", str1);
for (int i=0; i<strlen(str1); i++) {
if (str1[i]%2==1) {
str1[i]='A';
}
}
printf("%s", str1);
}
你有几个问题:
strlen
returns一个size_t
类型,所以i
最好匹配那个类型
i
未初始化,应该从 0 开始,因为 C 中的数组是从 0 开始的(第一个元素从位置 0 开始,而不是 1)。
str1[i]%2
是不正确的数学。你想对索引 i
取模,而不是字符串中的实际字符。
这是一个修复版本:
for (size_t i=0; i<strlen(str1); i++) {
if (i%2==0) {
str1[i]='A';
}
}
printf("%s", str1);
更新
正如@chux 在评论中所建议的那样,删除 strlen
并检查 NULL 字符作为循环中的终止条件会更有效。但是,对于像这样的迪克西杯程序,我怀疑是否会实现很多性能提升,最终建议使用您最清楚的 code/method:
方法一
for (size_t i=0; str1[i]!='[=11=]'; i++) {
// or simply str1[i]; since 0 will evaluate to false
if (i%2==0) {
str1[i]='A';
}
}
此外,您可以完全绕过模数,每次在循环中将 i
前进 2,因为它是您想要的偶数数组位置(奇数字符计数):
方法二
for (size_t i=0; i<strlen(str1); i=i+2) {
str1[i]='A';
}
沿着效率之路前进(并且知道您不会更改字符串的长度 in-loop),您还可以
方法三
size_t len = strlen(str1); // ensure strlen is only called once
for (size_t i=0; i<len; i=i+2) {
str1[i]='A';
}
或者,完全绕过 strlen
:
方法四
for (size_t i=0; str1[i]; i=i+2) {
str1[i]='A';
if (!str1[i+1]) break;
}
更新 2
在 Godbolt 上进行了一些试验后,@chux 是正确的。即使启用了优化,每次通过方法 2 的循环都会调用 strlen
。实际上在我看来,方法 3 是最有效的。我不是汇编专家,但这完全绕过了 strlen
调用,看起来循环中的指令最少。我已经为任何感兴趣的人创建了 this playground here。
目前,我正在尝试编写一个代码,用字母 'A'.
替换字符串中的第 1、3、5 个字符...(奇数)
E.x:'hello world' 将是 'AeAlA AoAlD'。
但是相反,我得到 'hAllA AArld' 这不是我想要的结果。
有人可以帮帮我吗?
编辑:问题是我检查了ASCII table,ASCII table中字母'e'、'o'、'w'的值是奇数,其他字母不是。所以我的程序正在检查字母的值是否为奇数或不替换为 'A' 而不是字符串中的第 1、3、5 个字符。
代码如下:
#include <stdio.h>
#include <string.h>
int main() {
char str1[100];
scanf("%[^\n]", str1);
for (int i=0; i<strlen(str1); i++) {
if (str1[i]%2==1) {
str1[i]='A';
}
}
printf("%s", str1);
}
你有几个问题:
strlen
returns一个size_t
类型,所以i
最好匹配那个类型i
未初始化,应该从 0 开始,因为 C 中的数组是从 0 开始的(第一个元素从位置 0 开始,而不是 1)。str1[i]%2
是不正确的数学。你想对索引i
取模,而不是字符串中的实际字符。
这是一个修复版本:
for (size_t i=0; i<strlen(str1); i++) {
if (i%2==0) {
str1[i]='A';
}
}
printf("%s", str1);
更新
正如@chux 在评论中所建议的那样,删除 strlen
并检查 NULL 字符作为循环中的终止条件会更有效。但是,对于像这样的迪克西杯程序,我怀疑是否会实现很多性能提升,最终建议使用您最清楚的 code/method:
方法一
for (size_t i=0; str1[i]!='[=11=]'; i++) {
// or simply str1[i]; since 0 will evaluate to false
if (i%2==0) {
str1[i]='A';
}
}
此外,您可以完全绕过模数,每次在循环中将 i
前进 2,因为它是您想要的偶数数组位置(奇数字符计数):
方法二
for (size_t i=0; i<strlen(str1); i=i+2) {
str1[i]='A';
}
沿着效率之路前进(并且知道您不会更改字符串的长度 in-loop),您还可以
方法三
size_t len = strlen(str1); // ensure strlen is only called once
for (size_t i=0; i<len; i=i+2) {
str1[i]='A';
}
或者,完全绕过 strlen
:
方法四
for (size_t i=0; str1[i]; i=i+2) {
str1[i]='A';
if (!str1[i+1]) break;
}
更新 2
在 Godbolt 上进行了一些试验后,@chux 是正确的。即使启用了优化,每次通过方法 2 的循环都会调用 strlen
。实际上在我看来,方法 3 是最有效的。我不是汇编专家,但这完全绕过了 strlen
调用,看起来循环中的指令最少。我已经为任何感兴趣的人创建了 this playground here。