複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
po_po
記事: 38
登録日時: 8年前

複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム

#1

投稿記事 by po_po » 8年前

複数のアルファベット(大文字と小文字)からなる文字列を任意の数だけ入力し、その複数の文字列に含まれるアルファベットの使われた回数の合計をアルファベットの種類別ごとに表示するプログラムを作ったのですが、結果が帰ってきません。どこが間違っているのか教えてくれます¥せんか?
出したい結果は 
a: 2
b: 3
c: 5



z: 4
といったような感じです。

コード:

#include<stdio.h>


int count(char s[], char ch){// 文字列に含まれる文字chの数を返す
  int i;
  int a = 0;
  for(i = 0; s[i]!= '\0'; i++){
    if(s[i] == ch){
      a = a + 1;
    }
    else{ a = a;}
  }
  return a;
}

void to_lower_string(char s[]){// 文字列に含まれる大文字をすべて小文字にする
  int i;
  for(i = 0; s[i]!= '\0'; i++){
    if('A' <= s[i] && s[i] <= 'Z'){
      s[i] = s[i] + 32;
    }
    else{ s[i] = s[i];}
  }
}

char ith_char(int i){ // 0番目をaとし、アルファベット順でi番目の小文字のアルファベットを返す
  char a;
  a = 'a';
  char r;
  if(i == 0){
    r = a;
  }
    else{
     r = a + i;
    }
  return r;
}

main(){
  int cnt[26];
  int a;
  int i = 0;
  for(a = 0; a <= 25 ; a++){
    cnt[a] = 0;
  }
  
  char str[256+1];
    while (scanf("%256s", str) == 1) { /* 読み込めるあいだ繰り返す */
        
        int j ;
        char m;
        for(j = 0; j <=25; j++){
        	m = ith_char(j);
        	to_lower_string(str);
        	cnt[j] =cnt[j] + count(str,m);
        	
        }
    }
    
      	
      	for(i = 0; i <= 25; i++){// 出てきた回数が0のアルファベットは表示しない
      	if(cnt[i] == 0){
      	}
      	else{
      		printf("%c: %d\n",ith_char(i),cnt[i]);
      
      	}
    }
}
      	



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

Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム

#2

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

po_po さんが書きました:結果が帰ってきません。どこが間違っているのか教えてくれます¥せんか?
Wandboxで適当なテストケースで実行してみましたが、すぐに結果が帰ってきて、再現できませんでした。
実行環境と、テストに使用した入力を教えていただけますか?
http://melpon.org/wandbox/permlink/vlXESyrlmJPeSWyp
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

po_po
記事: 38
登録日時: 8年前

Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム

#3

投稿記事 by po_po » 8年前

コンパイルは学習用C言語開発環境で行いました。
入力は何回もAAA等同じ文字の連続やadsaha等ランダムなものまで試してみましたがいずれも結果が返ってきませんでした。

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

Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム

#4

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

po_po さんが書きました:コンパイルは学習用C言語開発環境で行いました。
入力は何回もAAA等同じ文字の連続やadsaha等ランダムなものまで試してみましたがいずれも結果が返ってきませんでした。
Windows 7 Home Premium SP1 64bitで試しましたが、結果が返ってきました。
fukusunomoziretu_20150625.png
実行結果
fukusunomoziretu_20150625.png (53 KiB) 閲覧数: 4681 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ISLe()

Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム

#5

投稿記事 by ISLe() » 8年前

scanfの読み込みを終了させる手段は、キーボード入力の場合Ctrl+Z(^Z)と入力することをご存じないのでは。
#^Zはウィンドウズの場合

仮にCtrl+C(^C)を入力すると、scanfの入力待ちでプログラム自体が中断するので、それ以降は実行されません。

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

Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム

#6

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

ISLe() さんが書きました:#^Zはウィンドウズの場合
LinuxやMacの場合はCtrl+Dを入力するといいかもしれません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

超初級者
記事: 56
登録日時: 9年前

Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム

#7

投稿記事 by 超初級者 » 8年前

コード:

// こういうこと?
#include <stdio.h>
#include <ctype.h>

#define N (26)

void input(int *a)
{
   int c;

   while ((c = getchar()) != EOF) {
       if (isalpha(c)) {
           a[tolower(c) - 'a']++;
       }
   }
}

void print(int *a)
{
   int i;

   for (i = 0; i < N; i++) {
       printf("%c:%d\n", i + 'a', a[i]);
   }
}

int main(void)
{
   int a[N] = { 0 };

   input(a);
   print(a);
   return 0;
}

po_po
記事: 38
登録日時: 8年前

Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム

#8

投稿記事 by po_po » 8年前

Ctrl+Zを使ったらコンパイルできました。
ありがとうございます。
あと質問なんですがこのようなループを終了させるコマンドなしでこの上記のプログラムの結果を表示させることは可能ですか?

po_po
記事: 38
登録日時: 8年前

Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム

#9

投稿記事 by po_po » 8年前

上の結果と同じ結果を、終了させるコマンドなしで表示させる、上記のものとは別のプログラムを作ることができるかという意味です。

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

Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム

#10

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

po_po さんが書きました:あと質問なんですがこのようなループを終了させるコマンドなしでこの上記のプログラムの結果を表示させることは可能ですか?
例えば、スレッドを使用して3秒入力が無かったら終了する、とかでしょうか?

コード:

#include<stdio.h>
#include <windows.h>


int count(char s[], char ch){// 文字列に含まれる文字chの数を返す
	int i;
	int a = 0;
	for(i = 0; s[i]!= '\0'; i++){
		if(s[i] == ch){
			a = a + 1;
		}
		else{ a = a;}
	}
	return a;
}

void to_lower_string(char s[]){// 文字列に含まれる大文字をすべて小文字にする
	int i;
	for(i = 0; s[i]!= '\0'; i++){
		if('A' <= s[i] && s[i] <= 'Z'){
			s[i] = s[i] + 32;
		}
		else{ s[i] = s[i];}
	}
}

char ith_char(int i){ // 0番目をaとし、アルファベット順でi番目の小文字のアルファベットを返す
	char a;
	a = 'a';
	char r;
	if(i == 0){
		r = a;
	}
	else{
		r = a + i;
	}
	return r;
}

HANDLE mutex;
DWORD lastWriteTime;

DWORD WINAPI kansi(LPVOID data) {
	int* cnt = (int*)data;
	int i;
	for(;;) {
		WaitForSingleObject(mutex,INFINITE);
		if(GetTickCount()-lastWriteTime>3000) {
			for(i = 0; i <= 25; i++){// 出てきた回数が0のアルファベットは表示しない
				if(cnt[i] == 0){
				}
				else{
					printf("%c: %d\n",ith_char(i),cnt[i]);

				}
			}
			CloseHandle(mutex);
			ExitProcess(0);
		}
		ReleaseMutex(mutex);
		Sleep(100);
	}
}

int main(void){
	int cnt[26];
	int a;
	int i = 0;
	DWORD tid;
	for(a = 0; a <= 25 ; a++){
		cnt[a] = 0;
	}
	mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,NULL);
	lastWriteTime=GetTickCount();
	CloseHandle(CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)kansi,(LPVOID)cnt,0,&tid));
	char str[256+1];
	while (scanf("%256s", str) == 1) { /* 読み込めるあいだ繰り返す */
		WaitForSingleObject(mutex,INFINITE);
		int j ;
		char m;
		for(j = 0; j <=25; j++){
			m = ith_char(j);
			to_lower_string(str);
			cnt[j] =cnt[j] + count(str,m);

		}
		lastWriteTime=GetTickCount();
		ReleaseMutex(mutex);
	}

	
	WaitForSingleObject(mutex,INFINITE);
	lastWriteTime=GetTickCount()-3000;
	ReleaseMutex(mutex);
	for(;;)Sleep(1000);
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ISLe()

Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム

#11

投稿記事 by ISLe() » 8年前

^Zの入力が必要なのは、プログラムのせいではなくて、コマンドプロンプトの仕様です。

プログラムで手入力操作に依存する何かを加えると、常に手入力が必要なプログラムになってしまいます。
常に手作業が必要なプログラムはデバッグなどの効率を激しく低下させます。

標準入力には標準入力の良いところがあります。
リダイレクトが使えます。
あらかじめプログラムに与える文字列を記述したテキストファイルをキーボード入力の代わりに使えます。
コマンドプロンプトで
(プログラムの実行ファイル名がfoo.exeとした場合、[Enter]はエンターキー押下)
echo abc def gh | foo.exe[Enter]
とコマンドを打つと、
abc,def,ghの各文字列を入力したのと同じ効果があります。
)[Enter]
echo abc[Enter]
echo def[Enter]
echo gh[Enter]
) | foo.exe[Enter]
とコマンドを打つと各文字列ごとに改行を入れることも可能です。

リダイレクトを使ってさまざまな入力方法に対応でき、それは手作業に限りません。
テストやデバッグの自動化が可能になります。

いまのプログラムはそのままに、リダイレクトを利用し、
^Zを入力しなくても良いコマンドプロンプトに変わるプログラムを開発し
それを通していまのプログラムを実行するようにするのが良いと思います。

ISLe()

Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム

#12

投稿記事 by ISLe() » 8年前

ISLe() さんが書きました:)[Enter]
echo abc[Enter]
echo def[Enter]
echo gh[Enter]
) | foo.exe[Enter]
とコマンドを打つと各文字列ごとに改行を入れることも可能です。
はじめの括弧の向きが逆でした。
試す際は直してください。

po_po
記事: 38
登録日時: 8年前

Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム

#13

投稿記事 by po_po » 8年前

単純に入力終わりに^Zを入力しなければならないことをしらなかったのが原因でした。
みけCAT様、ISLe()様 
入力についてのコマンドプロンプトの仕様を教えていただきありがとうございました。
超初級者様
プログラムの例を書いてくださりありがとうございました。

閉鎖

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