这段代码中的 for 循环有什么问题?
What's wrong with the for loops in this code?
我正在阅读 The C Programming Language 一书,我无法弄清楚我的代码在这个练习中有什么问题。
该练习要求您实现 squeeze()
函数的一个版本,删除 s1 中与字符串 s2 中的任何字符匹配的每个字符。
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
int main ()
{
char s1[100];
char s2[100];
int c;
int i;
int j;
int flag=0;
char s3[100];
printf("TYPE THE FIRST STRING\n");
for(i=0;s1[i-1]!='\n';i++)
{
scanf("%c", &s1[i]);
}
printf("\n\nTYPE THE SECOND STRING\n");
for(i=0;s2[i-1]!='\n';i++)
{
scanf("%c", &s2[i]);
}
for(i=0;s1[i]!='\n';i++)/*sets the "i" character of s1 to be compared*/
{
for(j=0;s2[j]!='\n';j++)/*compares the "i" character in s1 with
{ every character on s2*/
if(s1[i]==s2[j])
{
flag=1;/*sets the flag variable to one if it finds 2 equal
break; characters and stops the loop*/
}
}
if(flag!=1)/*if it have not found a matching pair of chacters,
{ this part copies the s1 char to s3*/
s3[i]=s1[i];
}
flag=0;
printf("\n");
}
printf("\n\n%s",s3);
return 0;
}
问题是,如果我在 s1 中输入“test”,在 s2 中输入“second”,它只会打印“t”。一旦找到匹配对,它就会停止。 flag
没有正常工作?我在这个练习中花费了 2 小时以上,无法解决它。
for (i = 0; s1[i-1] != '\n'; i++)
此循环第一次迭代的谓词将访问超出范围的 s1[-1]
,然后调用 undefined behavior。涉及 s2
的循环有同样的问题。
此外,您的字符串永远不会以 NUL 终止,并且它们的缓冲区很容易通过 scanf
.
溢出。
您有多个跨越多行的 /* */
注释实例,这会注释掉您的代码部分:两个开头 {
和 break
.
即使在通过评论解决问题后
if (flag != 1) {
s3[i] = s1[i];
}
将在您的最终字符串中留下漏洞。 s3
需要一个单独的索引计数器,它只会随着字符串长度的增加而增加。
一个简单的例子,我们初始化我们的缓冲区(特别是这个 NUL 终止 s3
),并使用 fgets
来限制我们的输入。
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char s1[100] = { 0 },
s2[100] = { 0 },
s3[100] = { 0 };
int flag = 0;
size_t k = 0;
if (
!fgets(s1, sizeof s1, stdin) ||
!fgets(s2, sizeof s2, stdin)
) {
fprintf(stderr, "Could not read input.\n");
return EXIT_FAILURE;
}
for (size_t i = 0; s1[i] && s1[i] != '\n'; i++) {
for (size_t j = 0; s2[j] && s2[j] != '\n'; j++) {
if (s1[i] == s2[j]) {
flag = 1;
break;
}
}
if (flag == 0)
s3[k++] = s1[i];
flag = 0;
}
printf("%s\n", s3);
}
或者,使用 strchr
,我们可以编写一个整洁的函数:
#include <string.h>
void squeeze(char *dest, const char *source, const char *filter) {
for (; *source; source++)
if (!strchr(filter, *source))
*dest++ = *source;
*dest = '[=13=]';
}
我正在阅读 The C Programming Language 一书,我无法弄清楚我的代码在这个练习中有什么问题。
该练习要求您实现 squeeze()
函数的一个版本,删除 s1 中与字符串 s2 中的任何字符匹配的每个字符。
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
int main ()
{
char s1[100];
char s2[100];
int c;
int i;
int j;
int flag=0;
char s3[100];
printf("TYPE THE FIRST STRING\n");
for(i=0;s1[i-1]!='\n';i++)
{
scanf("%c", &s1[i]);
}
printf("\n\nTYPE THE SECOND STRING\n");
for(i=0;s2[i-1]!='\n';i++)
{
scanf("%c", &s2[i]);
}
for(i=0;s1[i]!='\n';i++)/*sets the "i" character of s1 to be compared*/
{
for(j=0;s2[j]!='\n';j++)/*compares the "i" character in s1 with
{ every character on s2*/
if(s1[i]==s2[j])
{
flag=1;/*sets the flag variable to one if it finds 2 equal
break; characters and stops the loop*/
}
}
if(flag!=1)/*if it have not found a matching pair of chacters,
{ this part copies the s1 char to s3*/
s3[i]=s1[i];
}
flag=0;
printf("\n");
}
printf("\n\n%s",s3);
return 0;
}
问题是,如果我在 s1 中输入“test”,在 s2 中输入“second”,它只会打印“t”。一旦找到匹配对,它就会停止。 flag
没有正常工作?我在这个练习中花费了 2 小时以上,无法解决它。
for (i = 0; s1[i-1] != '\n'; i++)
此循环第一次迭代的谓词将访问超出范围的 s1[-1]
,然后调用 undefined behavior。涉及 s2
的循环有同样的问题。
此外,您的字符串永远不会以 NUL 终止,并且它们的缓冲区很容易通过 scanf
.
您有多个跨越多行的 /* */
注释实例,这会注释掉您的代码部分:两个开头 {
和 break
.
即使在通过评论解决问题后
if (flag != 1) {
s3[i] = s1[i];
}
将在您的最终字符串中留下漏洞。 s3
需要一个单独的索引计数器,它只会随着字符串长度的增加而增加。
一个简单的例子,我们初始化我们的缓冲区(特别是这个 NUL 终止 s3
),并使用 fgets
来限制我们的输入。
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char s1[100] = { 0 },
s2[100] = { 0 },
s3[100] = { 0 };
int flag = 0;
size_t k = 0;
if (
!fgets(s1, sizeof s1, stdin) ||
!fgets(s2, sizeof s2, stdin)
) {
fprintf(stderr, "Could not read input.\n");
return EXIT_FAILURE;
}
for (size_t i = 0; s1[i] && s1[i] != '\n'; i++) {
for (size_t j = 0; s2[j] && s2[j] != '\n'; j++) {
if (s1[i] == s2[j]) {
flag = 1;
break;
}
}
if (flag == 0)
s3[k++] = s1[i];
flag = 0;
}
printf("%s\n", s3);
}
或者,使用 strchr
,我们可以编写一个整洁的函数:
#include <string.h>
void squeeze(char *dest, const char *source, const char *filter) {
for (; *source; source++)
if (!strchr(filter, *source))
*dest++ = *source;
*dest = '[=13=]';
}