【问题标题】:Word length frequency in C ProgramC程序中的字长频率
【发布时间】:2015-10-21 05:52:51
【问题描述】:

我正在尝试编写一个简单的 C 程序来输出单词的长度并输出它们的频率。例如,如果用户输入“嘿”,我的程序将输出 Length of word: 3 Occurrences 1,依此类推,输入更大的字符串。我似乎无法正确循环它。当看到分隔符同时计算单词当时的长度及其出现时,我想设置两个计数器,但我还没有找到一种工作方式。如何修复我的循环?我的代码如下。我会很感激任何帮助。我应该包括我的程序只对输入的一个单词正确运行,而不是整个句子或多个句子。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
const char delim[] = ", . - !*()&^%$#@<> ? []{}\\ / \"";
const int n_delim = 31;
#define SIZE 1000

int is_delim(int c);
int main(){
    char string[SIZE];
    int wordlength = 0, wl[SIZE];
    int word = 0, i;


    printf("Enter your input string:");
    fgets(string, SIZE, stdin);
    string[strlen(string) - 1] = '\0';

printf("Word Length\tCount\n");
    int seen = 0;
    int l;
    for (i = 0; i < strlen(string); i++){
        if (is_delim(string[i])){
            wl[word++] = wordlength;
            l = wordlength;
            seen++;
            printf("%d\t\t%d\n", l, seen);
            wordlength = 0;
        }
        wordlength++;

    }
    return 0;
}

int is_delim(int c){
    register int i;
    for (i = 0; i < n_delim; i++)
        if (c == delim[i]) return 1;
    return 0;
}

【问题讨论】:

  • 这段代码甚至不能编译,你永远不会在任何地方声明i
  • 抱歉,我的错误会立即解决。
  • 另外你永远不会在任何地方使用wl,如果你用Wall编译你会看到这些东西。
  • wl 不与 wl[word++] @Linus 一起使用吗?
  • @Benny 你故意在delim 中留下空间?如果不是同时比较它也会被比较。

标签: c string loops


【解决方案1】:

诀窍在于 wl[n] 保存字数 长度为 n。此外,您无需继续调用 strlen() 在每次迭代中,只需检查最后的零字节。 如果您启用它,优化器将为您执行此操作。 奇怪的 for(;1;) 是这样循环计数的 最后一个字,以零字节结束。

memset(wl,0,sizeof(wl));
for(wordStart=maxLength=i=0;1;i++) {
  if(is_delim(string[i]) || string[i]==0) {
    int wordLength= i-wordStart;
    if(wordLength>0)
      wl[wordLength]++;
    if(wordLength>maxLength)
      maxLength= wordLength;
    wordStart= i+1;
  }
  if(string[i]==0)
    break;
}

for(i=1;i<=maxLength;i++) {
  if(wl[i]>0) {
    printf("%d words of length %d.\n",wl[i],i);
  }
}

【讨论】:

  • memset 在我没有包含的某个库中吗?因为我通过用这段代码替换我的循环来编译程序,所以没有输出?我将 wordStart 和 maxLength 都设置为 int,因为这里没有包含它。@TeasingDart
  • if(is_delim...) 语句中有一个错误的括号。我已经更正了。
  • 是的,它现在完美编译@TeasingDart。也感谢您的帮助!
  • 最后几点注意事项:C 字符串以零字节终止,因此如果您遍历每个字符,您只需检查零并避免调用 strlen()。如果字符为零,您的 is_delim() 也应该返回 true。 n_delim 变量是多余的,应该删除。不要使用“寄存器”属性,让编译器决定如何使用寄存器。
【解决方案2】:

你真的应该为此使用strtok。现在,您永远不会将最后一个字符串与当前字符串进行比较,因此您无法区分它们。您可以为此使用strcmp。最后,您应该使用strlen,而不是手动测试字符串的长度。这是你的循环的样子

int seen = 0;

pch = strtok(string, delim);
last = pch;
while(pch != NULL) {
  if(strcmp(last, pch) != 0) {
    printf("%s:\t%d\t\t%d\n", last, (int)strlen(last), seen);
    seen = 1;
  }else {
    seen++;
  }
  last = pch;
  pch = strtok(NULL, delim);
}
printf("%s:\t%d\t\t%d\n", last, (int)strlen(last), seen);

注意,你应该在循环之前将变量seen设置为0。

【讨论】:

  • 非常感谢您抽出宝贵的时间@Linus。我在我的编译器上用这个循环替换了我的循环,除了输入的第一个单词之外它可以工作。它显示它的长度但计数输出垃圾为什么会这样?
  • wl[] 分配在栈上,会包含栈垃圾,需要使用 memset(wl,0,sizeof(wl)) 清除它
  • 我意识到是什么在输出垃圾。第一个看到的声明没有分配给它。
  • @Benny 这就是为什么我将编辑我的答案以澄清这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-16
  • 2021-12-04
  • 2016-04-22
  • 2013-01-11
  • 2021-10-03
  • 2014-02-14
  • 2020-08-08
相关资源
最近更新 更多