アスキーコードの変換
アスキーコードの変換
vista でwin32コンソールアプリケションのC++です。
C言語ははじめたばかりです。
printfのscanfでデバッグのときに
abcABC123sDFgh#"x32YY=
っていう文字をうつと
ABCabc***SdfGH**X**yy*
と表示されるようにしたいんですけど(小文字は大文字に、大文字は小文字になるようにそれ以外は*と
表示される)
アスキーコードについてまだ良く分からないので、
教えていただける方よろしくおねがいします。
C言語ははじめたばかりです。
printfのscanfでデバッグのときに
abcABC123sDFgh#"x32YY=
っていう文字をうつと
ABCabc***SdfGH**X**yy*
と表示されるようにしたいんですけど(小文字は大文字に、大文字は小文字になるようにそれ以外は*と
表示される)
アスキーコードについてまだ良く分からないので、
教えていただける方よろしくおねがいします。
Re:アスキーコードの変換
isalpha関数でアルファベットか判定
isupper関数で大文字かどうか判定し、判定が真ならばtolower関数で小文字に変換
それ以外は小文字なのでtoupper関数で大文字に変換。
というのはどうでしょうか?
アスキーコードを数字として扱って弄りたいならば、アスキーコード表を見ながら大文字アルファベットの範囲と小文字の範囲かどうかを判定して、それぞれ逆になるように数字を加減算すればいいと思います。
僕の記憶(へっぽこ)が正しければ、大文字と小文字の差は20だったと・・・
isupper関数で大文字かどうか判定し、判定が真ならばtolower関数で小文字に変換
それ以外は小文字なのでtoupper関数で大文字に変換。
というのはどうでしょうか?
アスキーコードを数字として扱って弄りたいならば、アスキーコード表を見ながら大文字アルファベットの範囲と小文字の範囲かどうかを判定して、それぞれ逆になるように数字を加減算すればいいと思います。
僕の記憶(へっぽこ)が正しければ、大文字と小文字の差は20だったと・・・
Re:アスキーコードの変換
http://e-words.jp/p/r-ascii.html
Cのchar型は、数字として扱えます。
アスキーコードっていうのは、
「0x0041は大文字のAにしよう」
みたいなのが決められてる文字を表現する規則みたいなものです。
これだけじゃ日本語とかを表現できないので、他にも文字コードはたくさんあります。
上の表をみて大文字アルファベットの数字としての範囲が分かりますよね?
そしたらいくつ足せばその文字の小文字になるかを考えてみましょう。
追記
やはりへっぽこ記憶力でしたね。
差は0x0020でした^^;
というか20ってアルファベットの総数を下回ってるという、それ以前の話・・・・
ここは上の投稿も16進数のつもりでした、ってことにしよう。
そうしよう。
Cのchar型は、数字として扱えます。
アスキーコードっていうのは、
「0x0041は大文字のAにしよう」
みたいなのが決められてる文字を表現する規則みたいなものです。
これだけじゃ日本語とかを表現できないので、他にも文字コードはたくさんあります。
上の表をみて大文字アルファベットの数字としての範囲が分かりますよね?
そしたらいくつ足せばその文字の小文字になるかを考えてみましょう。
追記
やはりへっぽこ記憶力でしたね。
差は0x0020でした^^;
というか20ってアルファベットの総数を下回ってるという、それ以前の話・・・・
ここは上の投稿も16進数のつもりでした、ってことにしよう。
そうしよう。
Re:アスキーコードの変換
C言語ははじめたばかりらしいですが、C++はどうなのでしょうか?
今回の中心となる処理だけ例を示してみます。
排他的論理和を使えば、大文字小文字の変換は非常に簡単に行うことができます
ただし、これはCロケールの場合だけですので、std::setlocaleでロケールを変更するなどしていた場合は通用しません。
今回の中心となる処理だけ例を示してみます。
int c = static_cast<unsigned char>(s); if (std::isalpha(c)) s = c ^ 0x20; else s = '*';
排他的論理和を使えば、大文字小文字の変換は非常に簡単に行うことができます
ただし、これはCロケールの場合だけですので、std::setlocaleでロケールを変更するなどしていた場合は通用しません。
Re:アスキーコードの変換
一応こんな感じでやってみたんですけど
#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("*");
}
}
}
これで、デバッグなしで開始したらビルドエラーがでたんですけどそれを無視してやったらできました。
ですけど正直もっと効率のいい方法があると思うのでぜひ良かったら教えてください。
お願いします。 長くてすみません。
#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("*");
}
}
}
これで、デバッグなしで開始したらビルドエラーがでたんですけどそれを無視してやったらできました。
ですけど正直もっと効率のいい方法があると思うのでぜひ良かったら教えてください。
お願いします。 長くてすみません。
Re:アスキーコードの変換
よく考えてみると、ASCIIに決まっているのだからロケールに依存しないようにできますね。
ほとんど答えそのままなので、これでできるでしょう。
# またスルーされるかもしれませんが...
int c = static_cast<unsigned char>(s); int c2 = c | 0x20; if ('a' <= c2 && c2 <= 'z') s = c ^ 0x20; else s = '*';
ほとんど答えそのままなので、これでできるでしょう。
# またスルーされるかもしれませんが...
Re:アスキーコードの変換
>これで、デバッグなしで開始したらビルドエラーがでたんですけどそれを無視してやったらできました。
何が、どうできたんでしょ?
># またスルーされるかもしれませんが...
私は、見てますよー。質問者だけが、見てるわけではありません。いつも勉強になります。
何が、どうできたんでしょ?
># またスルーされるかもしれませんが...
私は、見てますよー。質問者だけが、見てるわけではありません。いつも勉強になります。
Re:アスキーコードの変換
僕も見てますー
自分で書くよりずっとスマートなコードなので勉強になります。
判定一個しかない
キャストでちゃんとstatic_castしてる
排他的論理和、かっこいい。
おそらく加減算よりもビット演算の方が早いんですよね?
たかぎさんのコードは僕が使わせていただきました。
ほとんどコピペですけど^^
自分で書くよりずっとスマートなコードなので勉強になります。
判定一個しかない
キャストでちゃんとstatic_castしてる
排他的論理和、かっこいい。
おそらく加減算よりもビット演算の方が早いんですよね?
たかぎさんのコードは僕が使わせていただきました。
ほとんどコピペですけど^^
Re:アスキーコードの変換
> パッと見て何をしているかがすぐわかるのは、
> is何とか系を使っているコードだと思います。
それは何ともいえませんよ。
見ている箇所より前で、setlocaleを呼ばれているかもしれませんからね。
> is何とか系を使っているコードだと思います。
それは何ともいえませんよ。
見ている箇所より前で、setlocaleを呼ばれているかもしれませんからね。
Re:アスキーコードの変換
> 見ている箇所より前で、setlocaleを呼ばれているかもしれませんからね。
呼んでいてもいなくても、is何とかは「関数の名前から何をしているかが
多くの人にすぐわかる」という利点があることには変わりないと思います。
呼んでいてもいなくても、is何とかは「関数の名前から何をしているかが
多くの人にすぐわかる」という利点があることには変わりないと思います。
Re:アスキーコードの変換
効率といってもさまざまな効率があります。実行速度、省メモリ、ソースコードの短さ、ソースコードの簡潔さ、そのほかにも有りますが、どの点で効率を求めるのかによってもスマートな解法は違ってきます。
たとえば、
//テーブル
const char *table="*****************************************************************"
"abcdefghijklmnopqrstuvwxyz******ABCDEFGHIJKLMNOPQRSTUVWXYZ**************************"
"************************************************************************************"
"**********************";
//変換作業
ch2=table[(unsigned char)ch1];
という風に書くこともできます、
けれども、これは実行速度の点からはスマート(とは限らないけど)でしょうけれども、メモリ使用量、ソースの短さ簡潔さの点から言ったら、全くスマートではないですよね。
逆に、
たとえば、
//テーブル
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:アスキーコードの変換
boxさん、さっきの内容書き換えました?
> 呼んでいてもいなくても、is何とかは「関数の名前から何をしているかが
> 多くの人にすぐわかる」という利点があることには変わりないと思います。
それは間違いありません。
適切な関数を呼ぶことで、コードの意図が明確になります。
ただ、厳密な動作を把握する上では必ずしも楽ではないということです。
実際の開発では頻繁にロケールを切り替えることはしませんし、今回はC++なので、仮にロケールを切り替えるとしてもsetlocaleではなくstd::localeを使うでしょうね。
自分で開発するコードはそれでよいのですが、第三者がそれを読む場合は事情が変わってきます。
> 呼んでいてもいなくても、is何とかは「関数の名前から何をしているかが
> 多くの人にすぐわかる」という利点があることには変わりないと思います。
それは間違いありません。
適切な関数を呼ぶことで、コードの意図が明確になります。
ただ、厳密な動作を把握する上では必ずしも楽ではないということです。
実際の開発では頻繁にロケールを切り替えることはしませんし、今回はC++なので、仮にロケールを切り替えるとしてもsetlocaleではなくstd::localeを使うでしょうね。
自分で開発するコードはそれでよいのですが、第三者がそれを読む場合は事情が変わってきます。
Re:アスキーコードの変換
tkmakwins15さん
> けれども、これは実行速度の点からはスマート(とは限らないけど)でしょうけれども、メモリ使用量、ソースの短さ簡潔さの点から言ったら、全くスマートではないですよね。
スマートかどうかはともかく、tolowerやtoupperは、それと同じ方法で実装されているケースが多々あります。
is系関数も多くは表引きです。
> けれども、これは実行速度の点からはスマート(とは限らないけど)でしょうけれども、メモリ使用量、ソースの短さ簡潔さの点から言ったら、全くスマートではないですよね。
スマートかどうかはともかく、tolowerやtoupperは、それと同じ方法で実装されているケースが多々あります。
is系関数も多くは表引きです。
Re:アスキーコードの変換
>たかぎさん
>tolowerやtoupperは、それと同じ方法で実装されているケースが多々あります。
はい、そのことは分かっていましたが、カレー屋さんのいう効率がどのケースに当てはまるものなのか?
ということが明確にされていないので、ここではあえて例として車輪の再発明を実行させていただきました。
それと、to系関数もロケールに依存してしまうので…
>カレー屋さん
お願いです、掲示板規約に則って
・ソースコードを<pre></pre>(<>は半角)で囲む
・同一HNを使う
の二点を守ってください。
>tolowerやtoupperは、それと同じ方法で実装されているケースが多々あります。
はい、そのことは分かっていましたが、カレー屋さんのいう効率がどのケースに当てはまるものなのか?
ということが明確にされていないので、ここではあえて例として車輪の再発明を実行させていただきました。
それと、to系関数もロケールに依存してしまうので…
>カレー屋さん
お願いです、掲示板規約に則って
・ソースコードを<pre></pre>(<>は半角)で囲む
・同一HNを使う
の二点を守ってください。
Re:アスキーコードの変換
可読性とロケールを両立させるのであれば...
こんな風にもできますが、実行効率、空間効率ともに最悪ですね。
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 = '*';
こんな風にもできますが、実行効率、空間効率ともに最悪ですね。