以下のプログラムは(A|B)&(A|B|C)&(B|C)→(B)|(A&C)というような論理演算ができるのですが、アルファベット大文字の26文字限定です。大文字と小文字を別のものと区別して52文字判別するにはどこを変更すれば良いでしょうか。getExp内のelse if('A' <= *c && *c <= 'Z')をif('A' <= *c && *c <= 'z')のようにしても上手くいきませんでした
#include <stdio.h>
#define BUFSIZE_STR 1024 //バッファ(適当なサイズ)
#define BUFSIZE_EXP 1024 //バッファ(適当なサイズ)
#define BUFSIZE_ANS 1024 //バッファ(適当なサイズ)
char str[BUFSIZE_STR]; //入力された数式を格納
long exp[BUFSIZE_EXP]; //ビット配列化した数式を格納
long ans[BUFSIZE_ANS]; //ビット配列化した答えを格納
int expCount = 0; //ビット配列化した数式の数
int ansCount = 0; //ビット配列化した答えの数
int maxAlpha = 0; //使用されているアルファベットの最大
void getExp(void);
int checkExp(long x);
int addAnswer(long x);
void printAnswer(void);
void main(void)
{
long x;
getExp();
for(x = 1; x < (1<<maxAlpha); x++) if(checkExp(x)) if(addAnswer(x)) return;
printAnswer();
}
//標準入力から数式を入力しビット配列化する
void getExp(void)
{
int i, j, flg;
char *c;
puts("数式を入力して下さい 例 (A|B)&(A|C)");
fgets(str,BUFSIZE_STR,stdin);
for(c = str, flg = 0; *c != '\0'; c++){
if(!flg) exp[expCount] = 0;
if(*c == '&' && flg){
expCount++;
flg = 0;
}else if('A' <= *c && *c <= 'Z'){
if((*c - 'A' + 1) > maxAlpha) maxAlpha = *c - 'A' + 1;
exp[expCount] |= (1 << (int)(*c - 'A'));
flg = 1;
}
}
if(flg) expCount++;
}
//数式を評価する
int checkExp(long x)
{
int i;
for(i = 0; i < expCount; i++) if(!(exp[i] & x)) return 0;
return 1;
}
//吸収則で不要な答えを排除しながら、答えを登録
int addAnswer(long x)
{
int i;
for(i = 0; i < ansCount; i++){
if((ans[i] & x) == ans[i]) return 0; //吸収則により排除
if((ans[i] & x) == x){ ans[i] = x; return 0; } //吸収則により排除
}
//答えの登録
ans[ansCount++] = x;
if(ansCount >= BUFSIZE_ANS){ puts("バッファが足りません。"); return -1; }
return 0;
}
//ビット配列化されている答えを、アルファベットで表示
void printAnswer(void)
{
int i, j, flg;
for(j = 0; j < ansCount; j++){
putchar('(');
for(i = 0, flg = 0; i < maxAlpha; i++){
if(ans[j] & (1 << i)){
if(flg) putchar('&');
putchar('A'+i);
flg = 1;
}
}
putchar(')');
if(j < ansCount -1) putchar('|');
}
putchar('\n');
}
A 回答 (10件)
- 最新から表示
- 回答順に表示
No.9
- 回答日時:
No6です。
>ご回答ありがとうございます。8が表示され64bitということが確認出来ました。実際に使えるようにしていただいたとのことなのですが拝見させていただいてもよろしいでしょうか
こちらで修正したソースです。
64ビット環境が必須です。
No6でも書きましたが、使えるのはa,b,c程度で、e,f,g,..zは使えないと思います。使用するアルファベットのコードが大きくなるごとに処理時間が劇的に長くなります。
main()内の
for (x = 1; x < ((long)1 << maxAlpha); x++){
が原因です。
-----------------------------------------
#include <stdio.h>
#define BUFSIZE_STR 1024 //バッファ(適当なサイズ)
#define BUFSIZE_EXP 1024 //バッファ(適当なサイズ)
#define BUFSIZE_ANS 1024 //バッファ(適当なサイズ)
char str[BUFSIZE_STR]; //入力された数式を格納
long exp[BUFSIZE_EXP]; //ビット配列化した数式を格納
long ans[BUFSIZE_ANS]; //ビット配列化した答えを格納
int expCount = 0; //ビット配列化した数式の数
int ansCount = 0; //ビット配列化した答えの数
int maxAlpha = 0; //使用されているアルファベットの最大
void getExp(void);
int checkExp(long x);
int addAnswer(long x);
void printAnswer(void);
void main(void)
{
long x;
getExp();
for (x = 1; x < ((long)1 << maxAlpha); x++){
if (checkExp(x)){
if (addAnswer(x)){
return;
}
}
}
int i;
printAnswer();
}
//標準入力から数式を入力しビット配列化する
void getExp(void)
{
int i, j, flg,ax;
char *c;
puts("数式を入力して下さい 例 (A|B)&(A|C)");
fgets(str, BUFSIZE_STR, stdin);
for (c = str, flg = 0; *c != '\0'; c++) {
if (!flg)
exp[expCount] = 0;
if (*c == '&' && flg) {
expCount++;
flg = 0;
} else if (('A' <= *c && *c <= 'Z') || ('a' <= *c && *c <= 'z')) {
if (*c <= 'Z'){
ax = *c - 'A';
}else{
ax = *c - 'a' + 26;
}
if (ax + 1> maxAlpha)
maxAlpha = ax + 1;
exp[expCount] |= ((long)1 << ax);
flg = 1;
}
}
if (flg)
expCount++;
}
//数式を評価する
int checkExp(long x)
{
int i;
for (i = 0; i < expCount; i++)
if (!(exp[i] & x))
return 0;
return 1;
}
//吸収則で不要な答えを排除しながら、答えを登録
int addAnswer(long x)
{
int i;
for (i = 0; i < ansCount; i++) {
if ((ans[i] & x) == ans[i])
return 0; //吸収則により排除
if ((ans[i] & x) == x) {
ans[i] = x;
return 0;
} //吸収則により排除
}
//答えの登録
ans[ansCount++] = x;
if (ansCount >= BUFSIZE_ANS) {
puts("バッファが足りません。");
return -1;
}
return 0;
}
//ビット配列化されている答えを、アルファベットで表示
void printAnswer(void)
{
int i, j, flg;
for (j = 0; j < ansCount; j++) {
putchar('(');
for (i = 0, flg = 0; i < maxAlpha; i++) {
if (ans[j] & ((long)1 << i)) {
if (flg)
putchar('&');
if (i < 26){
putchar('A' + i);
}else{
putchar('a' - 26 + i);
}
flg = 1;
}
}
putchar(')');
if (j < ansCount - 1)
putchar('|');
}
putchar('\n');
}
No.8
- 回答日時:
ご提示の処理のままでは、あまり綺麗に実装できそうにないので、
以下のような拡張をお勧めします。
--
英字以外や単語への対応も視野に入れて、
アルファベットではなく変数名を扱うと考える
使用する変数名の一覧配列を用意する
例) char varNames[52];
exp と ans のビット配列を、
下位ビットから A,B,C ... のアルファベットと見なさずに、
一覧配列の 0,1,2 ... 番目の変数名と見なす
getExp で解析中に、
A-Z (U+0041 - U+005A) と、
a-z (U+0061 - U+007A) の文字を、変数名と見なす
未知の変数名を見つけたら、一覧配列に追加する
以下の関数を用意するとソースが読みやすくなり便利です
* 一覧配列を探し、変数名 から 番号 に変換する (exp へ代入用)
* 一覧配列を探し、番号 から 変数名 に変換する (ans を表示用)
No.7
- 回答日時:
>if('A' <= *c && *c <= 'Z')をif('A' <= *c && *c <= 'z')のようにしても上手くいきませんでした
私なら、*c が大文字と小文字なら番号0から51を返す、そうでなければ -1 を返す関数、例えば isAlpha() を定義して、
if( isAlpha(*c) >=0 )
に置き換え、
putchar('A'+i);のように番号から大文字と小文字に変換する部分も、例えば num2Alpha(int i) のような関数を定義して、
putchar(num2Alpha(i) );
に置き換えるかな。
No.6
- 回答日時:
前提条件として、64ビットの整数型が扱える環境が必要になります。
64ビットのLinux環境であれば、long型は64ビット整数型になるので
A-Z,a-zの文字をビットとして保持することが可能です。
まず、あなたの環境でlong型が4バイトなのか8バイトなのかを調査してください。
以下のプログラムを実行し、8が表示されればlong型は64ビット整数型になりますのでa-zの文字列を追加することは可能です。
しかしながら、実際にこちらでa-zの文字列を使えるように改修してみましたが、実質的に使用可能なのはa~dの文字のようです。e~zの文字を使用した場合は、結果がでるまでに非常に時間がかかり、使いものにならないかと思います。
まずは、あなたの環境でlong型のサイズを確認してください。
#include <stdio.h>
int main(void)
{
long a;
printf ("size of a=%d\n",sizeof(a));
return 0;
}
ご回答ありがとうございます。8が表示され64bitということが確認出来ました。実際に使えるようにしていただいたとのことなのですが拝見させていただいてもよろしいでしょうか
No.5
- 回答日時:
No.1、3です。
文字コードの調整をしないと、
小文字の時のmaxAlphaは正常値よりも大きくなり、メインのループ数は正常回数ではなくなるでしょう。
exp配列に入る値も実際の文字コードとは異なるものが入るので、多分checkExpの結果も狂ってくると思います。
そうすると、addAnswerが走るタイミングもおかしくなると思います。
ans配列には正しくないアルファベットを、正しいコードで格納しますが、putchar('A'+i);で格納された文字とは別の文字を出力しているような気がします。
格納時と出力時のズレが同じなので、一見すると文字的には正しく出力しているように見えそうです。
私の頭では、紙にでも書きながら考えないと何が起きているか判断できませんが、この修正は、1箇所2箇所の修正で済むレベルのものでは無いと思いますよ。
No.2
- 回答日時:
「上手くいかない」というのは, 具体的にはどう「上手くいかない」んだろう.
アルファベットは文字コードが連続しているという保証がないので
'A' <= *c && *c <= 'Z'
ではうまく判定できない可能性があるんだけど, 理解できているのかなぁ....
No.1
- 回答日時:
ざっとしか読んでいませんが、
}else if('A' <= *c && *c <= 'z'){ とした場合、
ここでおかしくなっていませんか?
if((*c - 'A' + 1) > maxAlpha)
アスキーコードのアルファベット大文字Zと小文字aの間には幾つか記号が入っています。
アスキーコード表
http://www3.nit.ac.jp/~tamura/ex2/ascii.html
例えば、'Z'-'A'は25ですが、'a'-'A'は32です。
一例ですが、大文字の時と小文字の時は処理を分けるのが良いと思います。
以下適当なので、調整して下さい。
if (*c<='Z'){
tmp_c=*c - 'A' + 1
}else{
tmp_c=*c - 'a' + 27
}
if(tmp_c > maxAlpha)
〜
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- Visual Basic(VBA) InputBoxでキャンセルボタンを押したらファイル自体を閉じたい 3 2022/07/23 17:52
- C言語・C++・C# C 言語の Gauss Jordan 法について 2 2022/12/28 11:16
- C言語・C++・C# 10人分の生徒の英語の点数{32,34,41,38,40,26,14,46,42,50} と数学の点 2 2022/05/26 21:31
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
関数から配列を返すには?
-
構造体のextern方法
-
配列の要素数に変数を入れたい...
-
[C++]const int と配列
-
define で 配列
-
コンボボックスでデフォルト値...
-
構造体の配列 char *' 型は 'ch...
-
C#で構造体の配列を持った構造...
-
C言語において、 配列要素をひ...
-
C言語の配列のコピーについて
-
C言語で質問です
-
c言語の自分で数字を入力してサ...
-
AfxBeginThread の引数について
-
.NET C++で、構造体の配列をnew...
-
C#でのフィボナッチ数列
-
構造体の動的確保について
-
C言語で重複組合せを全列挙
-
配列のアドレス部
-
構造体をポインターに入れたい
-
int i, int i[1];
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
関数から配列を返すには?
-
C言語において、 配列要素をひ...
-
配列の要素数に変数を入れたい...
-
構造体のextern方法
-
define で 配列
-
c言語
-
C#で構造体の配列を持った構造...
-
C言語の2次元配列 容量が大き...
-
c言語 構造体
-
C言語 ファイルの指定された行...
-
C言語についてです 5人のテスト...
-
int i, int i[1];
-
fclose()でセグメンテーション違反
-
char型配列をint型に代入するには
-
C言語から質問です。
-
Cのエラー
-
コンボボックスでデフォルト値...
-
C言語の課題が出たのですが自力...
-
MFCのCArrayを使った二次元配列
-
[C++]const int と配列
おすすめ情報
大文字だけでなく小文字も扱いたいため具体的に上手くいかないとは、本文と同じ内容で大文字小文字を入れ替えて(a|b)&(a|b|c)&(b|c)→(b)|(a&c)となるようにしたいのですが(B&b)|(A&C&a&c)となってしまい、また(a|B)&(a|B|C)&(b|c)のようにしても同様に(B&b)|(A&C&a&c)となってしまいます。