[英]Modifying an array inside a while loop
我有这个 function 试图删除非字母字符,但是我的代码不起作用。 我试图调试它,它似乎卡在这条线上:
str[i]= str[i+1];
有人可以解释一下为什么它卡在那里吗?
谢谢你。
int Removenonalfa(char *str) {
int i =0;
while (str[i]!='\0')
{
j=0;
if ((str[i]>='A' && str[i]<='Z') || (str[i]>='a' && str[i]<='z'))
;
else
{
str[i]= str[i+1];
continue;
}
i++;
}
return 0; }
continue;
防止循环体的rest被执行,所以i++;
永远不会被执行,所以i
永远不会改变,所以循环会永远以相同的i
值继续。
您应该重新考虑如何构建循环。 您已在字符串i
中使用 position 的一个指标编写它。 但是,由于您要删除非字母字符并返回带有字母字符的字符串,因此您真正想要做的是读取字符串中的每个字符,如果是字母,则将其移动到字符串中的最后位置. 所以需要position的两个指标。 您有一个未使用的j
。 重写循环,使i
每次遍历字符串一个字符——它在每次迭代中始终递增 1,并且您永远不会跳过该递增。 使用j
来跟踪每个字母在字符串中的写入位置。 那么j
只有在处理一个字母时才会增加。
试试这个:
void KeepAlphabeticChars(char *str)
{
int writer = 0, reader = 0;
while (s[reader])
{
if ((str[reader]>='A' && str[reader]<='Z') || (str[reader]>='a' && str[reader]<='z'))
{
str[writer++] = str[reader];
}
reader++;
}
str[writer]=0;
}
你需要像这样声明你的字符串:
char str[] = "ab12cdef";
注意:在您发布的代码中,变量j
未声明,但已初始化为0
。 这不会编译。 声明并使用它。 你需要两个参考点来做你想做的事情。 (有关原因,请参阅下面解决方案代码示例中的注释。)
其他观察:
只有当字符串中有两个连续的数字时,循环才是无限的。 例如,如果str
= "asdf1234",则将str[4]
更改为包含str[5]
的值,这也是一个数字。 因为i
没有递增,所以str[4]
的下一个测试会发现它仍然是一个数字,并导致对str[5]
中的值进行相同的分配。 因此str
变为"asdf2234"
,并在无限循环中保持该值。
在数字不连续的情况下,例如str
= "asdf1a3a",即使算法最终退出循环,生成的字符串也会用以下 position 中包含的值替换任何数字,因此生成的字符串看起来像: "asdfaaaa"
。 我假设通过“尝试删除非字母字符” ,您希望字符串是: "asdfaa"
为什么:
注意 C 编程中的continue语句的工作方式有点像 break 语句。 它不是强制终止,而是强制循环的下一次迭代发生,跳过中间的任何代码。
因此,在您的代码中,一旦条件将执行流程带到continue
语句, i++
就无法递增,从而阻止while
语句中的退出条件得到满足,并且流程无限地限制为以下四行:
...
while (str[i]!='\0')
... //then
if ((str[i]>='A' && str[i]<='Z') || (str[i]>='a' && str[i]<='z'))
... //finally
str[i]= str[i+1];
continue;//then continues back to the beginning of while loop
因为i
不是高级的(注意str[i]= str[i+1];
不会改变i
),字符串数组中超出该点的唯一元素将保持为str[i]
。
以下代码从包含数字的字符串中删除数字,无论数字是否连续。 此外,此示例将缩短字符串以仅包含剩余的非数字字符:
int Removenonalfa(char *str)
{
int i,j;//using both i AND j in this example
for (i = 0; str[i] != '\0'; ++i) {
while (str[i] >= '0' && str[i] <= '9') {//walking through original string
//looking only for digits
for (j = i; str[j] != '\0'; ++j) {//here we use j to track the next
//occurrence to be changed so
//i does not change.
str[j] = str[j + 1];//digit found, overwrite it with
//next value in array.
}
str[j] = '\0';//after advancing characters to fill position
//formerly occupied by digit, terminate new
//string
}
}
return 0;
}
当多个连续字符未通过测试时, while
循环会陷入循环。
考虑包含未通过测试的连续字符'1'
和'2'
的字符串"A12"
:
iter i str[i] str[i+1] str[i+2] str[i+3]
---- -- ------ -------- -------- --------
1 0 'A' '1' '2' '\0'
2 1 '1' '2' '\0' N/A
3 1 '2' '2' '\0' N/A
4 1 '2' '2' '\0' N/A
迭代 4 以后只是重复迭代 3。
修复它的一种方法是使用两个索引,一个用于源字符 position,另一个用于目标字符 position:
int Removenonalfa(char *str) {
int i = 0;
int j = 1;
while (str[i]!='\0')
{
if ((str[i]>='A' && str[i]<='Z') || (str[i]>='a' && str[i]<='z'))
;
else
{
str[i]= str[j];
j++;
continue;
}
i++;
j++;
}
return 0;
}
考虑字符串"A12"
:
iter i str[i] str[i+1] str[i+2] str[i+3] j str[j] str[j+1] str[j+2]
---- -- ------ -------- -------- -------- -- ------ -------- --------
1 0 'A' '1' '2' '\0' 1 '1' '2' '\0'
2 1 '1' '2' '\0' N/A 2 '2' '\0' N/A
3 1 '2' '2' '\0' N/A 3 '\0' N/A N/A
4 1 '\0' '2' '\0' N/A 4 N/A N/A N/A
while
循环在迭代 4 开始时终止,因为str[i]
等于'\0'
。 str[0]
包含'A'
并且str[1]
包含'\0'
。 ( str[2]
包含'2'
和str[3]
包含'\0'
,但这些并不重要。)
示范:
#include <stdio.h>
int Removenonalfa(char *str) {
int i = 0;
int j = 1;
while (str[i]!='\0')
{
if ((str[i]>='A' && str[i]<='Z') || (str[i]>='a' && str[i]<='z'))
;
else
{
str[i]= str[j];
j++;
continue;
}
i++;
j++;
}
return 0;
}
int main(int argc, char *argv[])
{
int i;
for (i = 1; i < argc; i++)
{
printf("[%d] Before: %s\n", i, argv[i]);
Removenonalfa(argv[i]);
printf("[%d] After: %s\n", i, argv[i]);
}
return 0;
}
运行: ./a.out A12 abcde 12345
Output:
[1] Before: A12
[1] After: A
[2] Before: abcde
[2] After: abcde
[3] Before: 12345
[3] After:
注意 C 标准允许修改main()
的argv[]
字符串内容,参考。 C17 5.1.2.2.1/2: — 参数argc
和argv
以及argv
数组指向的字符串应可由程序修改,并在程序启动和程序终止之间保留其最后存储的值。
使用指向字符串文字的指针调用 function Removenonalfa
将导致未定义的行为。 有关用于存储字符串文字的未命名字符数组,请参见 C17 6.4.5/7:如果它们的元素具有适当的值,则未指定这些 arrays 是否不同。 如果程序尝试修改这样的数组,则行为未定义。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.