首先,您可以替换:
int k = 1;
for (k; k < argc; k++)
更“标准”:
int k;
for (k = 1; k < argc; k++)
然后,在该else
部分内部,一个简单的循环和状态机将只输出第一个单词中的字符。基于字符的状态机的优点是不管行多长,并且没有缓冲区溢出的机会。
使用 30 个字符的缓冲区,如果您尝试一次处理(例如)60 个字符的文件,您可能会遇到问题。
以下伪代码可能会有所帮助:
state = before_word
get character from input stream (see fgetc)
while character is not end-of-file:
if character is newline:
echo character (see putchar)
state = before_word
else
if state is before_word:
if character is not white space (see isblank/isspace):
echo character
state = in_word
endif
else
if state is in_word:
if character is white space:
state = past_word
else
echo character
endif
endif
endif
endif
get character from input stream (see fgetc)
endwhile
它通过维护一个状态来工作(你的状态取决于通过输入流进入的东西)。
初始状态是before_word
因为它紧接在文件第一行之前的假想换行符之后。在该状态下,所有空白字符都被丢弃,第一个非空白字符in_word
在回显该字符后导致状态更改为 。
当状态为in_word
时,输出每个字符。到达该状态的第一个空白字符不输出,并导致状态转移到past_word
。
在past_word
状态下,所有字符都被丢弃。
在任何状态下(此if
语句是第一个),换行符都会强制状态变为before_word
.
将伪代码转换为 C 代码对您来说是一个很好的练习,特别是如果这是家庭作业。
如果它不是家庭作业,下面是一个解决方案。由于 SO 是一个公共网站,因此请小心不要将其作为自己的工作,而且我相信教育工作者会检查此类网站是否存在抄袭行为。一个简单的谷歌搜索echoAndChange
几乎肯定会给你一个失败的分数。
所以,假设这不是家庭作业,或者你只是想要一些东西来检查你自己的解决方案,我们开始吧:
#include <stdio.h>
#include <ctype.h>
// States and utility function for echo and change state.
typedef enum {ST_PRE, ST_IN, ST_POST} tState;
tState echoAndChange (int chr, tState newState) {
if (chr != EOF) putchar (chr);
return newState;
}
int main (int argc, char *argv[]) {
FILE *fp;
int k, chr;
tState state;
// Process each file.
for (k = 1; k < argc; k++) {
fp = fopen (argv[1], "r");
if (fp == NULL) {
printf ("Error with file: %s\n", argv[1]);
} else {
// Initial state pre-word, then process every character.
state = ST_PRE;
while (1) {
chr = fgetc (fp); if (chr == EOF) break;
// Newline: output it and change to pre-word.
if (chr == '\n') {
state = echoAndChange (chr, ST_PRE);
continue;
}
// Pre-word and nonspace: echo and change to in-word.
if (state == ST_PRE) {
if (!isblank (chr))
state = echoAndChange (chr, ST_IN);
continue;
}
// In-word: change to post word if space, otherwise echo.
if (state == ST_IN)
if (isblank (chr))
state = echoAndChange (EOF, ST_POST);
else
state = echoAndChange (chr, ST_IN);
}
fclose (fp);
}
}
return 0;
}
在著名的“Lorem ipsum”文本上运行该程序时:
Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit
esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
你可以看到它的实际效果:
Lorem
sed
aliqua.
ullamco
Duis
esse
occaecat
deserunt
如果您想要一个更短的程序,您可以将一些状态机吸收到您的语句执行顺序中(而不用担心前导空格),例如:
#include <stdio.h>
#include <ctype.h>
int main (int argc, char *argv[]) {
FILE *fp;
int echo, chr;
if (argc < 2) {
puts ("Usage: firstword <input-file>");
return -1;
}
fp = fopen (argv[1], "r");
if (fp == NULL) {
printf ("Error with file: %s\n", argv[1]);
return -1;
}
echo = 1;
chr = fgetc (fp);
while (chr != EOF) {
if (chr == '\n') echo = 1;
if (isblank (chr)) echo = 0;
if (echo ) putchar (chr);
chr = fgetc (fp);
}
fclose (fp);
return 0;
}
这里的基本规则是:
- 初始状态是回声。
- 然后,对于每个字符:
- 换行强制回显(换行回显两行向下)。
- 任何空白都会关闭回声。
- 如果回显打开,则回显字符。