当使用导致无限循环的无符号整数时,在 For 循环条件中向后迭代数组以在 0 处停止
iterating an array backwards in For loop condition to stop at 0 when using unsigned integers causing infinite loop
我有一个必须从 j 到 0(含)的循环。我的 j
变量是 size_t
类型,通常是无符号的。
我的代码:
#include<stdio.h>
#include<conio.h>
#define SIZE 100
int main(){
char str[SIZE];
size_t i=0;
size_t j;
puts("Enter any string");
scanf("%s",str);
while(str[i]!='[=10=]'){
i++;
}
for(j=i-1;j>=0;j--){
printf("%c",str[j]);
}
getch();
return 0;
}
我得到一个无限循环。如果我删除零的相等性,它会输出没有第一个字母的字符串的反转。那么这里有什么问题?
size_t
是一个无符号整数,它永远不会小于 0
。所以
for
循环中的条件始终为真:
for(j=i;j>=0;j--)
你可以修改条件为(虽然有点难看):
for(j=i; j-- > 0;){
...
}
请注意,在您的情况下,您也在打印 [=15=]
空字节,这是一个 non-printable 字符。 (因为 j
以等于字符串长度的值开头)。上面的条件也可以解决这个问题。
另外:
- 您可以使用
strlen()
而不是自己循环。
- 如果输入读取 wad 成功,请检查
scanf()
的 return 值。
无符号整数将在 C 中换行。任何无符号整数始终等于或大于 0,在代码中:uint >= 0
,始终为真。
您可以使用与 SIZE_MAX 的比较,因为这是类型 size_t 的最大值。代码将迭代并打印到 0,正如它应该的那样,然后换行到 SIZE_MAX,循环将结束。 (这假设字符串的长度不是 SIZE_MAX。)
for(j=i; j < SIZE_MAX ;j--){
printf("%c",str[j]);
}
另请注意,您的代码打印了空字符。所以起始索引应该是 j=i-1
,这与包装行为很好地配合,因为如果字符串的长度是 0,for 循环将不会打印任何东西,因为 i-1 == SIZE_MAX
.
for(j=i; j>0; j--) {
printf("%c", str[j-1]);
}
将是另一种选择。
对于初学者来说可能更容易理解。
但其他答案会更好。
编辑:我认为最好的是 for(j=i; j-- > 0;)
by l3x。
检查 j 是否大于 0 后递减 j。
使用 do{}while() 循环也可以。
j = i;
do {
j--;
printf("%c", str[j]);
} while (j > 0);
您可以将 j
从 size_t
更改为 long
,这可确保所有数据仍然适合,并且您可以达到 -1
值。
另一种选择是使用以下语句结束 for 循环:
for (j = i - 1;;--j)
{
// code
if (j == 0) break;
}
作为 side-note:您的第一个 while 循环与 string.h
中的 strlen()
相同。
递减计数循环往往会变得有点晦涩难懂。考虑改用此替代方法:
const size_t max = i-1; // maximum value that j can have
for(j=0; j<=max; j++)
{
... str[max-j];
}
无符号值环绕,所以当 j == 0
并且循环执行 j--
时,j >= 0
仍然为真。
一个基本且易于阅读的解决方案如下:
void reversePrint(char str[])
{
size_t j = strlen(str);
while (j-- > 0)
printf("%c", str[j]);
}
将以相反的顺序打印字符串:olleH
.
问题是 j >= 0
总是 true
因为 j
是 unsigned
。
当用 unsigned
倒数到零时,我通常使用后缀 --
:
while (j-- > 0)
我有一个必须从 j 到 0(含)的循环。我的 j
变量是 size_t
类型,通常是无符号的。
我的代码:
#include<stdio.h>
#include<conio.h>
#define SIZE 100
int main(){
char str[SIZE];
size_t i=0;
size_t j;
puts("Enter any string");
scanf("%s",str);
while(str[i]!='[=10=]'){
i++;
}
for(j=i-1;j>=0;j--){
printf("%c",str[j]);
}
getch();
return 0;
}
我得到一个无限循环。如果我删除零的相等性,它会输出没有第一个字母的字符串的反转。那么这里有什么问题?
size_t
是一个无符号整数,它永远不会小于 0
。所以
for
循环中的条件始终为真:
for(j=i;j>=0;j--)
你可以修改条件为(虽然有点难看):
for(j=i; j-- > 0;){
...
}
请注意,在您的情况下,您也在打印 [=15=]
空字节,这是一个 non-printable 字符。 (因为 j
以等于字符串长度的值开头)。上面的条件也可以解决这个问题。
另外:
- 您可以使用
strlen()
而不是自己循环。 - 如果输入读取 wad 成功,请检查
scanf()
的 return 值。
无符号整数将在 C 中换行。任何无符号整数始终等于或大于 0,在代码中:uint >= 0
,始终为真。
您可以使用与 SIZE_MAX 的比较,因为这是类型 size_t 的最大值。代码将迭代并打印到 0,正如它应该的那样,然后换行到 SIZE_MAX,循环将结束。 (这假设字符串的长度不是 SIZE_MAX。)
for(j=i; j < SIZE_MAX ;j--){
printf("%c",str[j]);
}
另请注意,您的代码打印了空字符。所以起始索引应该是 j=i-1
,这与包装行为很好地配合,因为如果字符串的长度是 0,for 循环将不会打印任何东西,因为 i-1 == SIZE_MAX
.
for(j=i; j>0; j--) {
printf("%c", str[j-1]);
}
将是另一种选择。
对于初学者来说可能更容易理解。
但其他答案会更好。
编辑:我认为最好的是 for(j=i; j-- > 0;)
by l3x。
检查 j 是否大于 0 后递减 j。
使用 do{}while() 循环也可以。
j = i;
do {
j--;
printf("%c", str[j]);
} while (j > 0);
您可以将 j
从 size_t
更改为 long
,这可确保所有数据仍然适合,并且您可以达到 -1
值。
另一种选择是使用以下语句结束 for 循环:
for (j = i - 1;;--j)
{
// code
if (j == 0) break;
}
作为 side-note:您的第一个 while 循环与 string.h
中的 strlen()
相同。
递减计数循环往往会变得有点晦涩难懂。考虑改用此替代方法:
const size_t max = i-1; // maximum value that j can have
for(j=0; j<=max; j++)
{
... str[max-j];
}
无符号值环绕,所以当 j == 0
并且循环执行 j--
时,j >= 0
仍然为真。
一个基本且易于阅读的解决方案如下:
void reversePrint(char str[])
{
size_t j = strlen(str);
while (j-- > 0)
printf("%c", str[j]);
}
将以相反的顺序打印字符串:olleH
.
问题是 j >= 0
总是 true
因为 j
是 unsigned
。
当用 unsigned
倒数到零时,我通常使用后缀 --
:
while (j-- > 0)