質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.90%

「C言語」特定の英単語の出現回数を求めたい

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 382

kota.work

score -3

問題

ファイル .txt から文字を読み込み、文章中で単語の "the" が何回出現しているのかをカウントする。ただし、大文字と小文字は区別しない。また、単語中に出現する the、例えば "gather" に含まれる "the" はカウントしない。

会話内容は「"」で囲んで表記される( "The United States ~" など)。発言内容の先頭に出現する "the" はカウントの対象に含めることとする。

自分で考えた方針

  1. まず、fpとしてファイルを読み込む。
  2. 大文字のTをtに統一する。一文字ずつ読み込むことにする。
  3. 次に、アルファベット以外(a,A~z,Z)の「,」「"」「.」などを消すため、NULLとして上書きする。

そうしてできたのをfp2として、theを検知する。

これ以降わからないです。

自分としては、fscanfで文字列をとってくるにしても、長さがバラバラでとれない?ような感じがします。

ぜひとも、解答のヒントや解答をご教授ください。

#include<stdio.h>
#include<string.h>
int main(void){
  FILE *fp,*fp2;
  fp = fopen("un.txt","r");
  if(fp == NULL){
    printf("error\n");
    return -1;
  }
  else{
    puts("file opened");
  }
  //以下が大切
  char c;
  while(fscanf(fp,"%c",&c) != EOF){
    //小文字に揃える
    if('A' <= c && c <= 'Z'){
      c = c - ('A' - 'a');
    }
    else if('a' <= c && c <= 'z'){
      continue;
    }
    //a~z以外をNULL
    else {
      c = 0;
    }
    fprintf(fp2, "%c", c);
  }
  int count = 0;
  //英単語を文字列に割り当てたい
  char s[];
  while(fscanf(fp2,"%s",s) != EOF){
    if(s[0] = 't' && s[1] == 'h' && s[2] == 'e'){
      count++;
    }
  }
  printf("%d",count);
  return 0;
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+1

1行読んで、記号は空白に、英字は小文字にしてから、両端に空白のある" the "strstrで検索。見つかったらcountを1増やして、さらにstrstrで検索。
先頭の"the "と末尾の" the"(ファイル末尾にあるかも)は別途調べる。

#include <stdio.h>
#include <string.h>
#include <ctype.h>

void preprocess(char *ptr);

int main(void)
{
    FILE *fp;
    char line[4096];
    int count = 0;

    fp = fopen("file.txt", "r");
    if (fp == NULL) {
        puts("file not found.");
        return 1;
    }
    while (fgets(line, sizeof(line), fp) != NULL) {
        preprocess(line);

        char *ptr = strstr(line, " the ");
        while (ptr != NULL) {
            count++;
            ptr = strstr(ptr + 5, " the ");
        }
    }

    if (strncmp(line, "the ", 4) == 0) {
        count++;
    }
    if (strncmp(line + strlen(line) - 4, " the", 4) == 0) {
        count++;
    }
    fclose(fp);

    printf("%d\n", count);

    return 0;
}

void preprocess(char *ptr)
{
    while (*ptr != '\0') {
        switch (*ptr) {
        case '"':
        case ',':
        case '\'':
        case '.':
        case '\n':
            *ptr = ' ';
            break;
        default:
            *ptr = tolower(*ptr);
        }
        ptr++;
    }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/21 08:52

    回答ありがとうございます。
    2つほど知らない関数があったので調べつつ理解していきます。
    正直、関数を分けたり、" the "と空白をつけて考えるのは自分にとって大きな収穫です。

    キャンセル

+1

  • fgetsで1行読み込む
  • その1行を大文字変換
  • スペースで分割する
  • 分割した各文字列をTHEと合致するかチェック
  • ファイルが尽きるまで繰り返し

これでコードを組んでいけばいいです

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/20 22:44

    ヒントありがとうございます、やってみます!

    文章中において、"The~となるときの対処法は、
    分割し終えた文字列の0番目が"(ASCIIで34)かどうかで、場合分けしておけばいけそうでしょうか...

    キャンセル

  • 2020/07/20 22:45

    標準関数で、文字列を比較する関数もあります

    キャンセル

0

こんなんでどうでしょう。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(void) {
  FILE *fp;
  char buf[4];
  int len, count;
  char c;

  fp = fopen("un.txt","r");
  if (fp == NULL) {
    printf("error\n");
    return -1;
  }

  len = 0;
  while (!feof(fp)) {
    c = fgetc(fp);
    if ('A' <= c && c <= 'Z') {
      c += ('a' - 'A');
      if (len <= 3) buf[len] = c;
      ++len;
    } else if ('a' <= c && c <= 'z') {
      if (len <= 3) buf[len] = c;
      ++len;
    } else {
      if (len == 3 && memcmp(buf, "the", 3) == 0)
        ++count;
      len = 0;
    }
    fprintf(fp2, "%c", c);
  }

  printf("%d", count);
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

scanf の "%[a-zA-Z]" で単語を読み込むというのはいかがでしょうか?

#include <stdio.h>   // fopen, fclose, fscanf, printf, perror
#include <string.h>  // strcmp
#include <ctype.h>   // tolower

int main(void)
{
    FILE *fp = fopen("un.txt", "r");
    if (!fp) { perror("un.txt"); return 1; }
    char word[51];
    int count = 0;
    while (1) {
        fscanf(fp, "%*[^a-zA-Z]");  // 英字以外を読み飛ばす
        if (fscanf(fp, "%50[a-zA-Z]", word) != 1) break;  // 単語を読む
        for (int i = 0; word[i]; i++) word[i] = tolower(word[i]);
        if (strcmp(word, "the") == 0) count++;
    }
    fclose(fp);
    printf("%d\n", count);
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/20 22:47

    回答ありがとうございます。
    "%[a-zA-Z]"  という表記を初めてみました。
    まだ基礎学習の段階なので、チートに感じる部分はパスしつつやっていこうとしています。

    ひとまず完成したら、回答者様の内容から勉強します。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.90%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る