imadedede のブログ

今出川潤の出張所。

続・C言語で文字列を逆にする

昨日の記事の続き。
寝る前にふと、文字列長を取得する部分を改善できるのではないか、と思いついた。
しかしそれなら長さ0の文字列にどう対応するべきか。
しかたないので関数にして括り出して対応することにした。
以下、改善版のコード。

// 文字列を逆にする
// どうせなら string.h なしで
#include <stdio.h>

// 文字列のポインタを受け取って、その文字列の並びを逆にする
void strrev(char s[]){
	char temp = '\0';
	char *head = s;
	char *tail = s;
	
	// 長さ0の文字列なら操作せず返す
	if(*head == '\0'){ return; }

	// 文字列の最期の文字のポインタを取得する
	while( *(tail+1) != '\0'){ tail++; }

	// 逆にする
	while(head != tail){
		temp = *head;
		*head = *tail;
		*tail = temp;
		
		head++;
		if(head == tail){ break; }
		tail--;
	}
	return;
}

// a.out の後に続く文字列を逆順にする
int main(int argc, char* argv[]){
	char *s = argv[1];
	// 引数が足りないなら比較しない
	if(argc <= 1){ return 0; }

	// 操作前
	printf("Input: %s\n", s);
	// 文字列を逆にする
	strrev(s);
	// 操作後
	printf("Output: %s\n", s);
	return 0;
}

主な変更点は、文字列の長さを測らなくなったこと。
これによって int 型1つ分のメモリ消費がなくなった(その分文字列ポインタが2つ増えた)のと、入れ替えられる文字列の長さが int 型最大値に依存しなくなった。後者は明確な利点ではなかろうか。
計算量は特に変わらず O(n) のオーダのまま。
実行結果はこちら。

imadedede$ ./a.out a
Input: a
Output: a
imadedede$ ./a.out ab
Input: ab
Output: ba
imadedede$ ./a.out abc
Input: abc
Output: cba
imadedede$ ./a.out abcd
Input: abcd
Output: dcba

問題ない。これでよし。

追記:最新版はこちら