ページ 1 / 1
複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム
Posted: 2015年6月25日(木) 22:45
by po_po
複数のアルファベット(大文字と小文字)からなる文字列を任意の数だけ入力し、その複数の文字列に含まれるアルファベットの使われた回数の合計をアルファベットの種類別ごとに表示するプログラムを作ったのですが、結果が帰ってきません。どこが間違っているのか教えてくれます¥せんか?
出したい結果は
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]);
}
}
}
Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム
Posted: 2015年6月25日(木) 22:55
by みけCAT
po_po さんが書きました:結果が帰ってきません。どこが間違っているのか教えてくれます¥せんか?
Wandboxで適当なテストケースで実行してみましたが、すぐに結果が帰ってきて、再現できませんでした。
実行環境と、テストに使用した入力を教えていただけますか?
http://melpon.org/wandbox/permlink/vlXESyrlmJPeSWyp
Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム
Posted: 2015年6月25日(木) 23:04
by po_po
コンパイルは学習用C言語開発環境で行いました。
入力は何回もAAA等同じ文字の連続やadsaha等ランダムなものまで試してみましたがいずれも結果が返ってきませんでした。
Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム
Posted: 2015年6月25日(木) 23:19
by みけCAT
po_po さんが書きました:コンパイルは学習用C言語開発環境で行いました。
入力は何回もAAA等同じ文字の連続やadsaha等ランダムなものまで試してみましたがいずれも結果が返ってきませんでした。
Windows 7 Home Premium SP1 64bitで試しましたが、結果が返ってきました。

- 実行結果
- fukusunomoziretu_20150625.png (53 KiB) 閲覧数: 5617 回
Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム
Posted: 2015年6月25日(木) 23:48
by ISLe()
scanfの読み込みを終了させる手段は、キーボード入力の場合Ctrl+Z(^Z)と入力することをご存じないのでは。
#^Zはウィンドウズの場合
仮にCtrl+C(^C)を入力すると、scanfの入力待ちでプログラム自体が中断するので、それ以降は実行されません。
Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム
Posted: 2015年6月26日(金) 00:04
by みけCAT
ISLe() さんが書きました:#^Zはウィンドウズの場合
LinuxやMacの場合はCtrl+Dを入力するといいかもしれません。
Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム
Posted: 2015年6月26日(金) 00:20
by 超初級者
コード:
// こういうこと?
#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;
}
Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム
Posted: 2015年6月26日(金) 00:53
by po_po
Ctrl+Zを使ったらコンパイルできました。
ありがとうございます。
あと質問なんですがこのようなループを終了させるコマンドなしでこの上記のプログラムの結果を表示させることは可能ですか?
Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム
Posted: 2015年6月26日(金) 00:54
by po_po
上の結果と同じ結果を、終了させるコマンドなしで表示させる、上記のものとは別のプログラムを作ることができるかという意味です。
Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム
Posted: 2015年6月26日(金) 01:21
by みけCAT
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);
}
Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム
Posted: 2015年6月26日(金) 22:40
by ISLe()
^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を入力しなくても良いコマンドプロンプトに変わるプログラムを開発し
それを通していまのプログラムを実行するようにするのが良いと思います。
Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム
Posted: 2015年6月26日(金) 22:45
by ISLe()
ISLe() さんが書きました:)[Enter]
echo abc[Enter]
echo def[Enter]
echo gh[Enter]
) | foo.exe[Enter]
とコマンドを打つと各文字列ごとに改行を入れることも可能です。
はじめの括弧の向きが逆でした。
試す際は直してください。
Re: 複数の文字列の入力から、その文字列に含まれるアルファベットの合計を返すプログラム
Posted: 2015年6月28日(日) 21:48
by po_po
単純に入力終わりに^Zを入力しなければならないことをしらなかったのが原因でした。
みけCAT様、ISLe()様
入力についてのコマンドプロンプトの仕様を教えていただきありがとうございました。
超初級者様
プログラムの例を書いてくださりありがとうございました。