文字列とビット演算子について教えてください。

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

文字列とビット演算子について教えてください。

#1

投稿記事 by かごめ » 9年前

ビット演算子を使って顔文字を以下のように出力させたいのですか、このコードで出力させると何も出ず、エラーが出ていまい終わるだけです。
どうすれば一文字ずつ消えるように出力させるでしょうか?
<結果>
Σ(・ω・ノ)ノ!
(・ω・ノ)ノ!
・ω・ノ)ノ!
ω・ノ)ノ!
・ノ)ノ!
ノ)ノ!
)ノ!
ノ!

コード:

#include<stdio.h>

int main(void){
	int i, j;

	char kaomozi[] = "Σ(・ω・ノ)ノ!";
	
	for (i = 0; i < 9; i++){
		printf("%s", kaomozi[]<<1);
		printf("\n");
	}

	return 0;
}

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

Re: 文字列とビット演算子について教えてください。

#2

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

一文字ずつ消すように出力の開始位置をずらしていくといいでしょう。

コード:

#include<stdio.h>

int main(void){
	int i, j;

	char kaomozi[] = "Σ(・ω・ノ)ノ!";
	
	for (i = 0; kaomozi[i]; i++){
		printf("%s", kaomozi + i);
		printf("\n");
#if 1
		/* Shift-JISの場合 */
		j = (unsigned char)kaomozi[i];
		if (((0x81 <= j && j <= 0x9f) || (0xe0 <= j && j <= 0xef))){
			j = (unsigned char)kaomozi[i + 1];
			if (0x40 <= j && j != 0x7f && j <= 0xfc) i++;
		}
#else
		/* UTF-8の場合 (不正チェックは省略) */
		j = (unsigned char)kaomozi[i];
		if (0xfe <= j) ; /* 不正なので進めない */
		else if (0xfc <= j) i += 5;
		else if (0xf8 <= j) i += 4;
		else if (0xf0 <= j) i += 3;
		else if (0xe0 <= j) i += 2;
		else if (0xc0 <= j) i++;
#endif
	}

	return 0;
}
…あっ、これだとビット演算子を使っていませんね。どこか適当にねじ込んでください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かごめ

Re: 文字列とビット演算子について教えてください。

#3

投稿記事 by かごめ » 9年前

どこに入れればいいのかわからいないので質問しているのですが・・・

box
記事: 2002
登録日時: 14年前

Re: 文字列とビット演算子について教えてください。

#4

投稿記事 by box » 9年前

そもそも、今回の問題をビット演算子で解決しようとするもくろみそのものが適切ではないのではないか、という気がします。
そんなことはないかな?
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

かごめ

Re: 文字列とビット演算子について教えてください。

#5

投稿記事 by かごめ » 9年前

そういう課題なんで必要です。

かずま

Re: 文字列とビット演算子について教えてください。

#6

投稿記事 by かずま » 9年前

かごめ さんが書きました:そういう課題なんで必要です。
文字列はマルチバイトです。バイト列です。ビット演算子は不要です。
課題を一字一句変えずに書いてください。

とりあえず、プログラムを作ってみました。
VC++ では、このままいけると思います。
cygwin だと、set LANG=ja_JP.cp932 を実行した後だと大丈夫だと思います。
Linux では、環境変数 LANG=ja_JP.UTF-8 だと思うので、OK でしょう。
コンパイル時の警告は無視してください。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
 
int main(void)
{
    int i, n;
    wchar_t k[16];
    char *p = (char *)k;
    char kaomozi[] = "Σ(・ω・ノ)ノ!";
    setlocale(LC_ALL, "");
    n = mbstowcs(k, kaomozi, 16);
    for (i = 0; i < n; i++)
        printf("%ls\n", p + (i << (sizeof(wchar_t)>>1)));
    return 0;
}
理解できない場合、どこが分からないのかを質問してください。
それと、あなたの環境(OS やコンパイラ)が何かを書いてください。

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

Re: 文字列とビット演算子について教えてください。

#7

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

かごめ さんが書きました:どこに入れればいいのかわからいないので質問しているのですが・・・
例えば、整数の足し算をビット演算子を用いて行うことができます。

コード:

#include<stdio.h>

/* 全加算器をシミュレートする */
unsigned int add(unsigned int a, unsigned int b) {
	unsigned int pos = 1;
	unsigned int carry = 0;
	unsigned int answer = 0;
	while (pos) {
		unsigned int abit = a & pos;
		unsigned int bbit = b & pos;
		unsigned int digit = abit ^ bbit ^ carry;
		unsigned int next_carry = (abit & bbit) | (bbit & carry) | (carry & abit);

		answer |= digit;
		carry = next_carry << 1;
		pos <<= 1;
	}
	return answer;
}

int main(void){
	unsigned int i, j;

	char kaomozi[] = "Σ(・ω・ノ)ノ!";
	
	for (i = 0; kaomozi[i]; i = add(i, 1)){
		printf("%s", kaomozi + i); /* ここの加算はポインタ演算なので置き換えられない */
		printf("\n");
#if 1
		/* Shift-JISの場合 */
		j = (unsigned char)kaomozi[i];
		if (((0x81 <= j && j <= 0x9f) || (0xe0 <= j && j <= 0xef))){
			j = (unsigned char)kaomozi[add(i, 1)];
			if (0x40 <= j && j != 0x7f && j <= 0xfc) i = add(i, 1);
		}
#else
		/* UTF-8の場合 (不正チェックは省略) */
		j = (unsigned char)kaomozi[i];
		if (0xfe <= j) ; /* 不正なので進めない */
		else if (0xfc <= j) i = add(i, 5);
		else if (0xf8 <= j) i = add(i, 4);
		else if (0xf0 <= j) i = add(i, 3);
		else if (0xe0 <= j) i = add(i, 2);
		else if (0xc0 <= j) i = add(i, 1);
#endif
	}

	return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: 文字列とビット演算子について教えてください。

#8

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

C++を使ってよければ、演算子をオーバーロードすればいいでしょう。

コード:

#include <stdio.h>
#include <string.h>

class moziretu {
	char* data;

public:
	moziretu(const char* str) {
		data = new char[strlen(str) + 1];
		strcpy(data, str);
	}
	~moziretu() {
		delete[] data;
	}
	// コピーコンストラクタ (The Rule of Three)
	moziretu(const moziretu& m) {
		data = new char[strlen(m.data) + 1];
		strcpy(data, m.data);
	}
	// 代入演算子 (The Rule of Three)
	moziretu& operator=(const moziretu& m) {
		delete[] data;
		data = new char[strlen(m.data) + 1];
		strcpy(data, m.data);
		return *this;
	}

	const char* operator<<(int index) const {
		char* pos = data;
		int c;
		for (; index-- && *pos; pos++) {
#if 1
			// Shift-JISの場合
			c = (unsigned char)*pos;
			if (((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xef))){
				c = (unsigned char)pos[1];
				if (0x40 <= c && c != 0x7f && c <= 0xfc) pos++;
			}
#else
			// UTF-8の場合 (不正チェックは省略)
			c = (unsigned char)*pos;
			if (0xfe <= c) ; // 不正なので進めない
			else if (0xfc <= c) pos += 5;
			else if (0xf8 <= c) pos += 4;
			else if (0xf0 <= c) pos += 3;
			else if (0xe0 <= c) pos += 2;
			else if (0xc0 <= c) pos++;
#endif
		}
		return pos;
	}
};

int main(void){
	int i;

	moziretu kaomozi = "Σ(・ω・ノ)ノ!";

	for (i = 0; i < 9; i++){
		printf("%s", kaomozi<<i);
		printf("\n");
	}

	return 0;
}
もしくは、<<1を使うなら

コード:

#include <stdio.h>
#include <string.h>

class moziretu {
	char* data;
	char* pos;

public:
	moziretu(const char* str) {
		data = new char[strlen(str) + 1];
		strcpy(data, str);
		pos = data;
	}
	~moziretu() {
		delete[] data;
	}
	// コピーコンストラクタ (The Rule of Three)
	moziretu(const moziretu& m) {
		data = new char[strlen(m.data) + 1];
		strcpy(data, m.data);
		pos = data;
	}
	// 代入演算子 (The Rule of Three)
	moziretu& operator=(const moziretu& m) {
		delete[] data;
		data = new char[strlen(m.data) + 1];
		strcpy(data, m.data);
		pos = data;
		return *this;
	}

	const char* operator<<(int index) {
		int c;
		char* ret = pos; // 演算前の値を返すようにする
		for (; index-- && *pos; pos++) {
#if 1
			// Shift-JISの場合
			c = (unsigned char)*pos;
			if (((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xef))){
				c = (unsigned char)pos[1];
				if (0x40 <= c && c != 0x7f && c <= 0xfc) pos++;
			}
#else
			// UTF-8の場合 (不正チェックは省略)
			c = (unsigned char)*pos;
			if (0xfe <= c) ; // 不正なので進めない
			else if (0xfc <= c) pos += 5;
			else if (0xf8 <= c) pos += 4;
			else if (0xf0 <= c) pos += 3;
			else if (0xe0 <= c) pos += 2;
			else if (0xc0 <= c) pos++;
#endif
		}
		return ret;
	}
};

int main(void){
	int i;

	moziretu kaomozi = "Σ(・ω・ノ)ノ!";

	for (i = 0; i < 9; i++){
		printf("%s", kaomozi<<1);
		printf("\n");
	}

	return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: 文字列とビット演算子について教えてください。

#9

投稿記事 by かずま » 9年前

かごめ さんが書きました:どこに入れればいいのかわからいないので質問しているのですが・・・
j = (unsigned char)kaomoz; を j = kaomozi & 0xff; とすれば、
ビット演算子 & を使ったことになります。

int le(int a, int b) { return ~(b-a >> 8); }
という関数を用意して
if ((le(081, j) & le(j, 0x9f)) | (le(0xe0, j) & le(j, 0xef))) {
と書けば、& | ~ >> の 4種類のビット演算子を使ったことになります。

閉鎖

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