因此,我正在尝试编写一个程序,该程序需要一个句子并将其从第三个单词中打印出来。前one two three four
应打印出three four
。
现在此代码有效,但我不知道为什么else
语句下的逻辑使它看起来不应该如此。
如果有人能解释为什么会这样,将不胜感激。
代码如下:
#include <stdio.h>
#include <string.h>
#define SIZE 100
int main(void) {
char arr[SIZE];
char *point;
char again = 'n';
do {
int count = 0;
for (int i = 0; i < SIZE; i++) {
arr[i] = '\0';
}
printf("Enter a sentence:");
gets(arr);
for (int i = 0; i < SIZE; i++) {
if (arr[i] == ' ') {
count++;
}
}
if (count < 2) {
printf("The sentence is to short!\n");
} else {
count = 1; //shouldn't this be count = 0?
for (int i = 0; i < SIZE; i++) {
if (arr[i] == ' ') {
count++;
}
if (count == 2) {
point = &arr[i + 2]; //shouldn't this be [i+1]?
}
}
printf("%s\n", point);
}
printf("Do you want to try again? (y/n)");
scanf("%c", &again);
while (getchar() != '\n');
} while (again == 'y' || again == 'Y');
return 0;
}
答案 0 :(得分:1)
您的代码有多个问题:
gets()
。此功能已从C标准中删除,因为无法给它提供最大数量的字符以写入目标缓冲区,因此输入流中足够长的行将导致未定义的行为。这是一个经典的安全漏洞。请改用fgets()
。如果文件末尾没有换行,循环while (getchar() != '\n');
将导致无限循环,如果您重定向输入一个空文件,则会发生无限循环。您还应该检查EOF
:
while ((c = getchar()) != EOF && c != '\n')
continue;
fgets()
和NULL
的返回值来检查输入操作是否成功。point = &arr[i+2];
应该是point = &arr[i+1]
。以下是使用字符串函数strspn
和strcspn
跳过空格和非空格的更正版本:
#include <stdio.h>
#include <string.h>
#define SIZE 100
#define WS " \t\n\r\v\f" /* white space characters */
int main(void) {
char arr[SIZE];
char *p;
for (;;) {
printf("Enter a sentence:");
if (fgets(arr, sizeof arr, stdin) == NULL)
break;
p = arr;
p += strspn(p, WS); /* skip initial spaces */
p += strcspn(p, WS); /* skip first word */
p += strspn(p, WS); /* skip spaces */
p += strcspn(p, WS); /* skip second word */
p += strspn(p, WS); /* skip spaces */
if (*p == '\0') {
printf("The sentence is too short!\n");
} else {
printf("%s", p);
}
printf("Do you want to try again? (y/n)");
if (fgets(arr, sizeof arr, stdin) == NULL)
break;
if (*arr != 'y' && *arr != 'Y')
break;
}
return 0;
}
答案 1 :(得分:1)
处理字数统计的另一种简单方法是在状态循环中沿字符串走指针 ,以跟踪您是否in
一个单词(如果增加单词数的话),否则您不是in
一个单词,而只是保持沿着前进(即遍历每个字符)直到找到下一个单词(或字符串的结尾)。
在填充缓冲区并设置指向其的指针后,逻辑很简单
#define MAXC 1024 /* buffer size (don't skimp) */
#define NWORD 3 /* output beginning with NWORD word */
...
char buf[MAXC] = "", /* buffer to hold line */
*p = buf; /* pointer to walk down buffer */
int n = 0, /* word counter */
in = 0; /* flag - in a word */
只需循环使用isspace()
检查每个字符,然后处理将in
标志设置为1
(字)或0
(字前或字之间的空格)递增每次您in
输入一个新单词时,计数器就会计数,计数达到3
时退出循环,例如
for (; *p; p++) { /* loop over each char */
if (!in && !isspace(*p)) { /* if not in word and not space */
in = 1, n++; /* set in flag, increment words */
if (n == NWORD) /* if 3rd word, break */
break;
}
else if (isspace(*p)) /* if space */
in = 0; /* unset in flag */
}
在一个简短的示例中将其全部放入,您可以执行与以下操作类似的操作:接受输入,直到在空行上单独按下 Enter 键,然后输出从第三行开始输入的每个句子-word,如果输入的单词少于三个单词,则显示错误"too few words."
,例如
#include <stdio.h>
#include <ctype.h>
#define MAXC 1024 /* buffer size (don't skimp) */
#define NWORD 3 /* output beginning with NWORD word */
int main (void) {
for (;;) { /* loop continually until empy-line */
char buf[MAXC] = "", /* buffer to hold line */
*p = buf; /* pointer to walk down buffer */
int n = 0, /* word counter */
in = 0; /* flag - in a word */
fputs ("\nenter sentence: ", stdout); /* prompt */
if (!fgets (buf, MAXC, stdin) || *buf == '\n') { /* read line */
puts ("all done!");
break;
}
for (; *p; p++) { /* loop over each char */
if (!in && !isspace(*p)) { /* if not in word and not space */
in = 1, n++; /* set in flag, increment words */
if (n == NWORD) /* if 3rd word, break */
break;
}
else if (isspace(*p)) /* if space */
in = 0; /* unset in flag */
}
if (n == NWORD) /* if 3 or more words */
fputs (p, stdout);
else /* other wise handle error */
fputs ("too few words.\n", stderr);
}
return 0;
}
使用/输出示例
$ ./bin/thirdword
enter sentence: one two three four five
three four five
enter sentence: one two
too few words.
enter sentence: one two three
three
enter sentence:
all done!
仔细检查一下,如果还有其他问题,请告诉我。
答案 2 :(得分:0)
count = 1;
//这不应该算为0吗?和point = &arr[i + 2];
//不应该是[i + 1]吗?
以下内容回答了两个问题。
count count count count
0 1 2 3
one two three four
i+0 i+1 i+2 i+3
point = &arr[i + 2];
和printf("%s\n", point);
一起表示从地址arr[i + 2]
直到看到\0
字符为止打印所有字符