数一数;“特殊词语”;在C中
我的代码如下:数一数;“特殊词语”;在C中,c,C,我的代码如下: #include <stdio.h> #define SIZE 10000000 int main() { char c, word[SIZE]; int len = 0, i, count = 0, w = 0; while ((c = getc(stdin)) != EOF) { if (c != ' ') { word[len] = c; len++; }
#include <stdio.h>
#define SIZE 10000000
int main() {
char c, word[SIZE];
int len = 0, i, count = 0, w = 0;
while ((c = getc(stdin)) != EOF) {
if (c != ' ') {
word[len] = c;
len++;
} else {
for (i = 0; i < len; i++) {
if ((word[i] >= 48 && word[i] <= 57) || (word[i] >= 65 && word[i]<= 90) || (word[i] >= 97 && word[i] <= 122))
count++;
if (count == len)
w++;
}
count = 0;
len = 0;
}
}
printf("%d", w);
return 0;
}
输出:
3
2
我该怎么做?
关于第一个问题,我想在循环中编写
if(c==EOF)
,但它不起作用。我只想使用fgets
,但是每个单词最多可以有10000000个字符,所以如果在一行中有几个单词有这么多字符,那么一个数组怎么能容纳这么多内存呢?您根本不需要存储任何单词。当一行开始或一个单词开始时,以及当发现超出范围的字符时,您可以通过保留一些状态来获得答案。您可以在找到空格或换行符时递增答案,并仅在找到换行符时打印答案。
这里
#包括
#包括
int main()
{
字符c;
int f=0;
int ans=0;
while(scanf(“%c”,&c)!=EOF)
{
如果(c='')
{
如果(f==1)
ans++;
f=0;
}
else如果(c=='\n')
{
如果(f==1)
ans++;
printf(“%d\n”,ans);
ans=0;
f=0;
}
其他的
{
如果(!((c>=48&&c=65&&c=97&&c您根本不需要存储任何单词。您可以通过在行开始或单词开始时以及在找到范围外字符时保留一些状态来获得答案。您可以在找到空格或换行符时递增答案,并仅在找到换行符时打印答案。
这里
#包括
#包括
int main()
{
字符c;
int f=0;
int ans=0;
while(scanf(“%c”,&c)!=EOF)
{
如果(c='')
{
如果(f==1)
ans++;
f=0;
}
else如果(c=='\n')
{
如果(f==1)
ans++;
printf(“%d\n”,ans);
ans=0;
f=0;
}
其他的
{
如果(!((c>=48&&c=65&&c=97&&c这里写的是非常快的坏代码(它可以写得更好,但今天我的大脑还在睡觉),但它显示了这个想法
typedef enum
{
WHITESPACE,
INSIDEWORD,
ENDOFTHELINE,
}STATES;
int main()
{
STATES state = WHITESPACE;
unsigned nwords = 0;
int wordvalid = 0;
int ch;
int readnext = 0;
ch = getc(stdin);
do
{
while(!readnext)
{
if(ch == '\n' || ch == EOF)
{
state = ENDOFTHELINE;
}
switch(state)
{
case WHITESPACE:
if(!isspace(ch))
{
state = INSIDEWORD;
wordvalid = 1;
}
else
{
readnext = 1;
}
break;
case INSIDEWORD:
if(isspace(ch))
{
nwords += wordvalid;
state = WHITESPACE;
wordvalid = 0;
}
else
{
if(wordvalid)
{
if(!isalnum(ch))
{
wordvalid = 0;
}
}
}
readnext = 1;
break;
case ENDOFTHELINE:
nwords += wordvalid;
printf("valid words: %d\n", nwords);
nwords = 0;
readnext = 1;
wordvalid = 0;
if(ch != EOF) state = WHITESPACE;
break;
}
}
ch = getc(stdin);
readnext = 0;
}while(ch != EOF || state != ENDOFTHELINE);
}
你可以在这里测试:这里写的是非常快的错误代码(它可以写得更好,但今天我的大脑还在睡觉),但它显示了这个想法
typedef enum
{
WHITESPACE,
INSIDEWORD,
ENDOFTHELINE,
}STATES;
int main()
{
STATES state = WHITESPACE;
unsigned nwords = 0;
int wordvalid = 0;
int ch;
int readnext = 0;
ch = getc(stdin);
do
{
while(!readnext)
{
if(ch == '\n' || ch == EOF)
{
state = ENDOFTHELINE;
}
switch(state)
{
case WHITESPACE:
if(!isspace(ch))
{
state = INSIDEWORD;
wordvalid = 1;
}
else
{
readnext = 1;
}
break;
case INSIDEWORD:
if(isspace(ch))
{
nwords += wordvalid;
state = WHITESPACE;
wordvalid = 0;
}
else
{
if(wordvalid)
{
if(!isalnum(ch))
{
wordvalid = 0;
}
}
}
readnext = 1;
break;
case ENDOFTHELINE:
nwords += wordvalid;
printf("valid words: %d\n", nwords);
nwords = 0;
readnext = 1;
wordvalid = 0;
if(ch != EOF) state = WHITESPACE;
break;
}
}
ch = getc(stdin);
readnext = 0;
}while(ch != EOF || state != ENDOFTHELINE);
}
您可以在这里进行测试:您有许多问题/事情无法解决
- 您不检查换行符(或空格以外的任何空格),因此它们将被视为单词的一部分(使行中的第一个或最后一个单词不特殊)
- 您只在末尾输出,而不是在每个换行后,连接到上面的
- 您不需要处理多个空格,因此两个连续的空格将被视为它们之间有一个零长度的特殊单词
- 您可以使用“神奇”常量来检查字母/数字——最好使用
isalnum
和isspace
来检查内容
- 您不需要将单词复制到堆栈缓冲区(不检查溢出),然后第二次迭代该单词以检查特殊/非特殊。您最好在读取单词的字符时进行检查
综上所述,您只需要在输入上运行一次简单的循环,跟踪当前正在查看的内容(单词之间的空格、特殊单词或非特殊单词),并适当地更新和输出计数:
#include <ctype.h>
#include <stdio.h>
int main() {
enum { SPACE, SPECIAL, NONSPECIAL } state = SPACE;
int special_count = 0, ch;
do {
ch = getchar();
if (ch == EOF || isspace(ch)) {
if (state == SPECIAL)
special_count++;
state = SPACE;
} else if (isalnum(ch)) {
if (state == SPACE)
state = SPECIAL;
} else {
state = NONSPECIAL; }
if (ch == EOF || ch == '\n') {
if (special_count > 0);
printf("%d\n", special_count);
special_count = 0; }
} while(ch != EOF);
}
#包括
#包括
int main(){
枚举{空间,特殊,非特殊}状态=空间;
int特殊_计数=0,ch;
做{
ch=getchar();
if(ch==EOF | | isspace(ch)){
如果(状态==特殊)
特殊_计数++;
状态=空间;
}else if(isalnum(ch)){
if(state==空格)
国家=特殊;
}否则{
状态=非特殊;}
如果(ch==EOF | | ch=='\n'){
如果(特殊计数>0);
printf(“%d\n”,特殊计数);
特殊计数=0;}
}while(ch!=EOF);
}
这里有几点:
- 我们使用
state
变量来跟踪到最后一个字符时我们正在查看的内容
- 我们使用do-while循环(而不是while),因为我们实际上想要用EOF做一些事情
- 我们只打印出至少有一个特殊单词的行的计数,以避免为空行打印0(如果最后一行以换行结束,这通常会发生)。如果我们要为至少有一个非特殊单词的行打印0,我们需要额外的标志或计数器来跟踪非特殊单词的存在
你有很多问题/事情没有解决
- 您不检查换行符(或空格以外的任何空格),因此它们将被视为单词的一部分(使行中的第一个或最后一个单词不特殊)
- 您只在末尾输出,而不是在每个换行后,连接到上面的
- 您不需要处理多个空格,因此两个连续的空格将被视为它们之间有一个零长度的特殊单词
- 您可以使用“神奇”常量来检查字母/数字——最好使用
isalnum
和isspace
来检查内容
- 您不需要将单词复制到堆栈缓冲区(不检查溢出),然后第二次迭代该单词以检查特殊/非特殊。您最好在读取单词的字符时进行检查
综上所述,您只需要在输入上运行一次简单的循环,跟踪当前正在查看的内容(单词之间的空格、特殊单词或非特殊单词),并适当地更新和输出计数:
#include <ctype.h>
#include <stdio.h>
int main() {
enum { SPACE, SPECIAL, NONSPECIAL } state = SPACE;
int special_count = 0, ch;
do {
ch = getchar();
if (ch == EOF || isspace(ch)) {
if (state == SPECIAL)
special_count++;
state = SPACE;
} else if (isalnum(ch)) {
if (state == SPACE)
state = SPECIAL;
} else {
state = NONSPECIAL; }
if (ch == EOF || ch == '\n') {
if (special_count > 0);
printf("%d\n", special_count);
special_count = 0; }
} while(ch != EOF);
}
#包括
#包括
int main(){
枚举{空间,特殊,非特殊}状态=空间;
int特殊_计数=0,ch;
做{
ch=getchar();
if(ch==EOF | | isspace(ch)){
如果(状态==特殊)
特别的_