リストについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
あいう

リストについて

#1

投稿記事 by あいう » 8年前

英文テキストファイルを読み込み、単語の出現回数を数えて、多いものから順に表示するプログラムを作りたいです。
現状、それぞれの単語が何回出現しているかは、ハッシュ表に登録するところまではできています。
ただ、ソートをすることができていません。実行してもエラーは出ないのですが、結果が表示されません。
どこまでプログラムが動いているのか確認したところ、ソート処理を行う前までは正常に動いているようです。

コード:

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

#define WORDLEN 50
#define MAXCOUNT 2500
#define SIZE 32

struct wd {
  struct wd *next;
  char *str;
  int count;
};
typedef struct wd WORD;

WORD *word[SIZE];
WORD *s_word[MAXCOUNT];

void init_word();
void init_s_word();
WORD *add_word(char *);
char *getword(char *, int);


int main()
{
  char w[WORDLEN];
  WORD *p,*q;
  int i,j;
  init_word();
  init_s_word();
  while (getword(w, WORDLEN) != NULL) {
    p = add_word(w);
    if (p == NULL) {
      fprintf(stderr, "Too many words\n");
      exit(1);
    }
    p->count++;
  }
    printf("\n");
//ここから下の部分でソートしようとしている
  for(j=0;j<SIZE;j++){
    for(q=word[j];q!=NULL;q=q->next){
      s_word[q->count]=q;
      s_word[q->count]->next = (WORD *)malloc(sizeof(WORD));
      s_word[q->count]=s_word[q->count]->next;  
    }
  }
  printf("\n");
  for (i = 1; i < MAXCOUNT; i++) {
    for (p = s_word[i]; p != NULL; p = p->next) {
      printf("%d %s\n", p->count, p->str);
    }
  }
  return 0;
}


void init_word()
{
  int i;

  for (i = 0; i < SIZE; i++)
    word[i] = NULL;
}
void init_s_word(){
  int i;
  for(i=0;i<MAXCOUNT;i++)
    s_word[i]=NULL;
}


int hash(char *w){
  int i;
  unsigned int h=0;
  for(i=0;w[i]!='\0';i++)h=65599*h+w[i];
  return h % SIZE;
}

WORD *add_word(char *w)
{
  char *s;
  WORD *p;
  int i;

  i = hash(w); 
  for (p = word[i]; p != NULL; p = p->next) {
    if (strcmp(w, p->str) == 0)
      return p;
  }
  s = (char *)malloc(strlen(w) + 1);
  if (s == NULL)
    return NULL;
  strcpy(s, w);
  p = (WORD *)malloc(sizeof(WORD));
  if (p == NULL)
    return NULL;
  p->str = s;
  p->count = 0;
  p->next = word[i];
  word[i] = p;
  return p;
}


char *getword(char *w, int n)
{
  int c;
  int i = 0;

  if (n <= 0 || feof(stdin))
    return NULL;
  c = getchar();
  while (c != EOF && ! isalpha(c)) {
    c = getchar();
  }
  if (c == EOF)
    return NULL;
  while (isalpha(c)) {
    if (i < n - 1)
      w[i++] = toupper(c);
    c = getchar();
  }
  if (i < n)
    w[i++] = '\0';
  return w;
}

可能であれば、出現回数を添え字としたリスト配列を用いてソートしたいです。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: リストについて

#2

投稿記事 by みけCAT » 8年前

あいう さんが書きました:

コード:

    for(q=word[j];q!=NULL;q=q->next){
      s_word[q->count]=q;
      s_word[q->count]->next = (WORD *)malloc(sizeof(WORD));
      s_word[q->count]=s_word[q->count]->next;  
    }
s_word[q->count]=q;があるので、s_word[q->count]にqに入っているアドレスが入ります。
次の行で、s_word[q->count]->next、すなわちq->nextにmallocで確保した領域のアドレスが入ります。
その次の行は、qには影響を与えません。
そしてforの行に戻ります。
q=q->nextにより、qにmallocで確保した領域のアドレスが入ります。
q!=NULLは、mallocが失敗していなければ真になります。
そして、s_word[q->count]=q;が実行され、q->countはmallocで確保され、初期化されていない領域の値なのでこれを使用したことで未定義動作になります。
オフトピック
識別子や配列の要素数が違うものの、このコードは本質的にはバケットソートについて質問です。と同じだ…。
同一人物ではないとすれば、どういうことだろうか…?
同じ人またはサイトなどから(間違った)アドバイスをもらったのだろうか…?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

metaphor

Re: リストについて

#3

投稿記事 by metaphor » 8年前

パケットソートhttps://ja.wikipedia.org/wiki/%E3%83%90 ... C%E3%83%88について私も知りたいのでコードに出来るだけ多くのコメントを書いてください。(コードよりコメントの方が大事です。とくに他人に誤解されるおそれのある場合は)

コード:


#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
 
#define WORDLEN 50
#define MAXCOUNT 2500
#define SIZE 32
 
struct wd {//自己参照構造体
  struct wd *next;//リスト構造
  char *str;//文字列
  int count;//カウント
};
typedef struct wd WORD;//WORDは自己参照構造体struct wdのエイリアス
 
WORD *word[SIZE];//自己参照構造体struct wdの容量
WORD *s_word[MAXCOUNT];//自己参照構造体struct wdの容量
/////////////////////////////関数 
void init_word();
void init_s_word();
WORD *add_word(char *);
char *getword(char *, int);
//////////////////////////// 
 
int main()
{
  char w[WORDLEN];
  WORD *p,*q;
  int i,j;
  init_word();
  init_s_word();
  while (getword(w, WORDLEN) != NULL) {
    p = add_word(w);
    if (p == NULL) {
      fprintf(stderr, "Too many words\n");
      exit(1);
    }
    p->count++;
  }
    printf("\n");
//ここから下の部分でソートしようとしている
  for(j=0;j<SIZE;j++){
    for(q=word[j];q!=NULL;q=q->next){
      s_word[q->count]=q;
      s_word[q->count]->next = (WORD *)malloc(sizeof(WORD));
      s_word[q->count]=s_word[q->count]->next;  
    }
  }
  printf("\n");
  for (i = 1; i < MAXCOUNT; i++) {
    for (p = s_word[i]; p != NULL; p = p->next) {
      printf("%d %s\n", p->count, p->str);
    }
  }
  return 0;
}
/////////////////////////////////////////////////////// 
void init_word()
{
  int i;
 
  for (i = 0; i < SIZE; i++)
    word[i] = NULL;
}
///////////////////////////////////////////////////////
void init_s_word(){
  int i;
  for(i=0;i<MAXCOUNT;i++)
    s_word[i]=NULL;
}
////////////////////////////////////////////////////// 
int hash(char *w){//ハッシュ生成
  int i;
  unsigned int h=0;
  for(i=0;w[i]!='\0';i++)h=65599*h+w[i];
  return h % SIZE;
}
////////////////////////////////////////////////////// 
WORD *add_word(char *w)
{
  char *s;
  WORD *p;
  int i;
 
  i = hash(w); 
  for (p = word[i]; p != NULL; p = p->next) {
    if (strcmp(w, p->str) == 0)
      return p;
  }
  s = (char *)malloc(strlen(w) + 1);
  if (s == NULL)
    return NULL;
  strcpy(s, w);
  p = (WORD *)malloc(sizeof(WORD));
  if (p == NULL)
    return NULL;
  p->str = s;
  p->count = 0;
  p->next = word[i];
  word[i] = p;
  return p;
}
///////////////////////////////////////////////////////////
char *getword(char *w, int n)
{
  int c;
  int i = 0;
 
  if (n <= 0 || feof(stdin))
    return NULL;
  c = getchar();
  while (c != EOF && ! isalpha(c)) {
    c = getchar();
  }
  if (c == EOF)
    return NULL;
  while (isalpha(c)) {
    if (i < n - 1)
      w[i++] = toupper(c);
    c = getchar();
  }
  if (i < n)
    w[i++] = '\0';
  return w;
}
///////////////////////////////////////////////////////////////// 

閉鎖

“C言語何でも質問掲示板” へ戻る