アスキーコードの変換

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

アスキーコードの変換

#1

投稿記事 by カレー屋 » 15年前

vista でwin32コンソールアプリケションのC++です。
C言語ははじめたばかりです。

printfのscanfでデバッグのときに
abcABC123sDFgh#"x32YY=
っていう文字をうつと
ABCabc***SdfGH**X**yy*
と表示されるようにしたいんですけど(小文字は大文字に、大文字は小文字になるようにそれ以外は*と
表示される)
アスキーコードについてまだ良く分からないので、
教えていただける方よろしくおねがいします。

sizuma

Re:アスキーコードの変換

#2

投稿記事 by sizuma » 15年前

isalpha関数でアルファベットか判定
isupper関数で大文字かどうか判定し、判定が真ならばtolower関数で小文字に変換
それ以外は小文字なのでtoupper関数で大文字に変換。

というのはどうでしょうか?

アスキーコードを数字として扱って弄りたいならば、アスキーコード表を見ながら大文字アルファベットの範囲と小文字の範囲かどうかを判定して、それぞれ逆になるように数字を加減算すればいいと思います。
僕の記憶(へっぽこ)が正しければ、大文字と小文字の差は20だったと・・・

彼ー屋

Re:アスキーコードの変換

#3

投稿記事 by 彼ー屋 » 15年前

大文字アルファベットの範囲と小文字の範囲かどうかを判定して、
それぞれ逆になるように数字を加減算するっていうのはどうやって
やればいいですか?

sizuma

Re:アスキーコードの変換

#4

投稿記事 by sizuma » 15年前

http://e-words.jp/p/r-ascii.html
Cのchar型は、数字として扱えます。
アスキーコードっていうのは、
「0x0041は大文字のAにしよう」
みたいなのが決められてる文字を表現する規則みたいなものです。
これだけじゃ日本語とかを表現できないので、他にも文字コードはたくさんあります。

上の表をみて大文字アルファベットの数字としての範囲が分かりますよね?
そしたらいくつ足せばその文字の小文字になるかを考えてみましょう。


追記
やはりへっぽこ記憶力でしたね。
差は0x0020でした^^;
というか20ってアルファベットの総数を下回ってるという、それ以前の話・・・・
ここは上の投稿も16進数のつもりでした、ってことにしよう。
そうしよう。

たかぎ

Re:アスキーコードの変換

#5

投稿記事 by たかぎ » 15年前

C言語ははじめたばかりらしいですが、C++はどうなのでしょうか?

今回の中心となる処理だけ例を示してみます。
int c = static_cast<unsigned char>(s);
    if (std::isalpha(c))
      s = c ^ 0x20;
    else
      s = '*';

排他的論理和を使えば、大文字小文字の変換は非常に簡単に行うことができます
ただし、これはCロケールの場合だけですので、std::setlocaleでロケールを変更するなどしていた場合は通用しません。

non

Re:アスキーコードの変換

#6

投稿記事 by non » 15年前

>排他的論理和を使えば、大文字小文字の変換は非常に簡単に行うことができます

なるほど、そうですね。初めて気がつきました。

カリーやカレー

Re:アスキーコードの変換

#7

投稿記事 by カリーやカレー » 15年前

一応こんな感じでやってみたんですけど
#include <stdio.h>
int main(void)
{
char aa[100];
{
printf("99文字以下で文字列を入力してください。");
scanf("%s", aa);
printf("変換された文字列は");

}
for (aa = 0; aa <= 2; aa++)
{aa = aa + 32;
printf("%c", aa);
}
for (aa = 3; aa <= 5; aa++)
{aa = aa - 32;
printf("%c", aa);
}
for (aa = 6; aa <= 8; aa++)
{printf("*");}
for (aa = 9; aa <= 9; aa++)
{aa = aa - 32;
printf("%c", aa);
}
for (aa = 10; aa <= 11; aa++)
{aa = aa + 32;
printf("%c");
}
for (aa = 12; aa <= 13; aa++)
{aa = aa - 32;
printf("%c", aa);
}
for (aa = 14; aa <= 15; aa++)
{printf("*");
}
for (aa = 16; aa <= 16; aa++)
{
aa = aa - 32;
printf("%c", aa);
}
for (aa = 17; aa <= 18; aa++)
{printf("*");
}
for (aa = 19; aa <= 20; aa++)
{aa = aa + 32;
printf("%c", aa);
}
for (aa = 21; aa <= 21; aa++)
{
printf("*");
}
}
}
これで、デバッグなしで開始したらビルドエラーがでたんですけどそれを無視してやったらできました。
ですけど正直もっと効率のいい方法があると思うのでぜひ良かったら教えてください。
お願いします。 長くてすみません。

Mist

Re:アスキーコードの変換

#8

投稿記事 by Mist » 15年前

> for (aa = 0; aa <= 2; aa++)

この辺とかaaを配列としてまともに扱えていないので効率化以前の問題。

たかぎ

Re:アスキーコードの変換

#9

投稿記事 by たかぎ » 15年前

よく考えてみると、ASCIIに決まっているのだからロケールに依存しないようにできますね。
int c = static_cast<unsigned char>(s);
int c2 = c | 0x20;
if ('a' <= c2 && c2 <= 'z')
  s = c ^ 0x20;
else
  s = '*';

ほとんど答えそのままなので、これでできるでしょう。
# またスルーされるかもしれませんが...

non

Re:アスキーコードの変換

#10

投稿記事 by non » 15年前

>これで、デバッグなしで開始したらビルドエラーがでたんですけどそれを無視してやったらできました。
何が、どうできたんでしょ?

># またスルーされるかもしれませんが...
私は、見てますよー。質問者だけが、見てるわけではありません。いつも勉強になります。

sizuma

Re:アスキーコードの変換

#11

投稿記事 by sizuma » 15年前

僕も見てますー
自分で書くよりずっとスマートなコードなので勉強になります。

判定一個しかない
キャストでちゃんとstatic_castしてる
排他的論理和、かっこいい。
おそらく加減算よりもビット演算の方が早いんですよね?

たかぎさんのコードは僕が使わせていただきました。
ほとんどコピペですけど^^

box

Re:アスキーコードの変換

#12

投稿記事 by box » 15年前

パッと見て何をしているかがすぐわかるのは、
is何とか系を使っているコードだと思います。

たかぎ

Re:アスキーコードの変換

#13

投稿記事 by たかぎ » 15年前

> パッと見て何をしているかがすぐわかるのは、
> is何とか系を使っているコードだと思います。

それは何ともいえませんよ。
見ている箇所より前で、setlocaleを呼ばれているかもしれませんからね。

box

Re:アスキーコードの変換

#14

投稿記事 by box » 15年前

> 見ている箇所より前で、setlocaleを呼ばれているかもしれませんからね。

呼んでいてもいなくても、is何とかは「関数の名前から何をしているかが
多くの人にすぐわかる」という利点があることには変わりないと思います。

たかぎ

Re:アスキーコードの変換

#15

投稿記事 by たかぎ » 15年前

> 呼んでいないかもしれません。

はい。
けれども、それを見極めるには、ほぼ全ソースに目を通す必要が出てきます。

tk-xleader

Re:アスキーコードの変換

#16

投稿記事 by tk-xleader » 15年前

効率といってもさまざまな効率があります。実行速度、省メモリ、ソースコードの短さ、ソースコードの簡潔さ、そのほかにも有りますが、どの点で効率を求めるのかによってもスマートな解法は違ってきます。
たとえば、

//テーブル
const char *table="*****************************************************************"
"abcdefghijklmnopqrstuvwxyz******ABCDEFGHIJKLMNOPQRSTUVWXYZ**************************"
"************************************************************************************"
"**********************";
//変換作業
ch2=table[(unsigned char)ch1];

という風に書くこともできます、
けれども、これは実行速度の点からはスマート(とは限らないけど)でしょうけれども、メモリ使用量、ソースの短さ簡潔さの点から言ったら、全くスマートではないですよね。
逆に、
if(islower((unsigned char)ch1))ch2=toupper((unsigned char)ch1);
else if(isupper((unsigned char)ch1))ch2=tolower((unsigned char)ch1);
else ch2='*';
と書けば、ソースコードの分かりやすさという面ではスマートでしょうけれども、たかぎさんのソースコードのほうが実行速度も上でしょうし、ソースコードも短いですよね。

たかぎ

Re:アスキーコードの変換

#17

投稿記事 by たかぎ » 15年前

boxさん、さっきの内容書き換えました?

> 呼んでいてもいなくても、is何とかは「関数の名前から何をしているかが
> 多くの人にすぐわかる」という利点があることには変わりないと思います。

それは間違いありません。
適切な関数を呼ぶことで、コードの意図が明確になります。
ただ、厳密な動作を把握する上では必ずしも楽ではないということです。

実際の開発では頻繁にロケールを切り替えることはしませんし、今回はC++なので、仮にロケールを切り替えるとしてもsetlocaleではなくstd::localeを使うでしょうね。
自分で開発するコードはそれでよいのですが、第三者がそれを読む場合は事情が変わってきます。

たかぎ

Re:アスキーコードの変換

#18

投稿記事 by たかぎ » 15年前

tkmakwins15さん
> けれども、これは実行速度の点からはスマート(とは限らないけど)でしょうけれども、メモリ使用量、ソースの短さ簡潔さの点から言ったら、全くスマートではないですよね。

スマートかどうかはともかく、tolowerやtoupperは、それと同じ方法で実装されているケースが多々あります。
is系関数も多くは表引きです。

tk-xleader

Re:アスキーコードの変換

#19

投稿記事 by tk-xleader » 15年前

>たかぎさん

>tolowerやtoupperは、それと同じ方法で実装されているケースが多々あります。

はい、そのことは分かっていましたが、カレー屋さんのいう効率がどのケースに当てはまるものなのか?
ということが明確にされていないので、ここではあえて例として車輪の再発明を実行させていただきました。
それと、to系関数もロケールに依存してしまうので…

>カレー屋さん

お願いです、掲示板規約に則って
・ソースコードを<pre></pre>(<>は半角)で囲む
・同一HNを使う
の二点を守ってください。

たかぎ

Re:アスキーコードの変換

#20

投稿記事 by たかぎ » 15年前

可読性とロケールを両立させるのであれば...
const std::locale& loc = std::locale::classic();
    char c = s;
    if (std::islower(c, loc))
      s = std::toupper(c, loc);
    else if (std::isupper(c, loc))
      s = std::tolower(c, loc);
    else
      s = '*';

こんな風にもできますが、実行効率、空間効率ともに最悪ですね。

閉鎖

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