質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

3回答

6931閲覧

文字列を逆に並べるには?

senbe

総合スコア27

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2015/03/04 21:51

編集2015/03/04 21:53

**問題は「文字列sを逆に並べる関数reverse(s)をかけ」
というものです。

私が考えたのは、文字列sをよみこみ、それを配列s[]にいれる。
そして関数reverse(s)をつかって並べかえる
というものなのですが、結果が出力されません…

めちゃくちゃなコードだと思いますが、間違っているところ、
また、もっとかんたんな考え方などがあれば教えてください!

lang

1#include <stdio.h> 2#define MAXLINE 1000 /* 入力行の最大長 */ 3 4 5int getline(char line[], int maxline); 6void reverse(char line[]); 7 8main() 9{ 10 char line[MAXLINE]; 11 12 while ((getline(line,MAXLINE)) > 0) 13 reverse(line); 14 printf("%s",line); 15} 16 17/*getline : sに行を入れ、長さを返す*/ 18int getline(char s[], int lim) 19{ 20 int c,i; 21 22 for (i = 0; i < lim -1 && (c = getchar()) != EOF && c != '\n'; i++) 23 s[i] = c; 24 if (c == '\n'){ 25 s[i] = c; 26 i++; 27 } 28 s[i] = '\0'; 29 return i; 30} 31 32 33/* reverse : sを tにコピーして値をいれかえる */ 34void reverse(char s[]) 35{ 36 int i,j,k; 37 char t[MAXLINE]; 38 39 i = 0; 40 while((t[i] = s[i]) != '\0') 41 i++; 42 i--;/*iは\0の1個前*/ 43 i--;/*iは改行コードの1個前*/ 44 i = k; 45 46 for (j = 0; j <= k; j++) { 47 s[j] = t[i]; 48 i--; 49 } 50 s[j] = '\n'; 51 j++; 52 s[j] = '\0'; 53}

関数 reverse(s) では
例えば
hello\n
と入力されたとき
s[0] にt[4] の値を代入 (s[0]に oをいれる)
...
s[4] にt[0] (s[4]に hを入れる)

というふうに考えてみました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

argius

2015/03/05 00:23

開発環境は何をお使いでしょうか。 UNIX系だと、`stdio.h`に`getline`があるので関数の名前が被ってしまいます。
senbe

2015/03/05 01:11

Windows機です。
senbe

2015/03/05 01:12

gccでコンパイルしています。
guest

回答3

0

日本語のことは 今の段階では考慮しなくてよいとおもいます。
問題を出した側は、配列の順番を変更する ということをコーデイング
できるかを求めていると思います。
この段階で 1 文字 = 1 バイト = 表示幅 1 といった前提を満たす英語圏
とは異なる言語圏のことまでは求めていないはず と私も思います。
(ただ、日本語の場合は文字列処理はいろいろ面倒な事が存在するということを知って欲しいです。
英語のことしか考えていないエディタプログラムを日本語対応するときはいろいろ大変なのです。)

あえて revese 処理をコードにするなら 次のようなコードが考えられます。
C++ で書いてるし、まだまだ問題があるコードですが。
文字を後ろからなめていって、答えに側には末尾に追加していく...)

lang

1#include <string> 2#include <iostream> 3using namespace std; 4 5std::wstring reverse(std::wstring str) { 6 std::wstring ans = L""; 7 const int len = str.length(); 8 for (int i = len - 1; i >= 0; i--) { 9 ans.append(1, str.at(i)); 10 } 11 return ans; 12} 13 14int main() { 15 std::wcout.imbue(std::locale("")); 16 17 std::wstring str = L"あいうえおabc"; 18 std::wcout << str << endl; 19 std::wcout << reverse(str) << endl; 20 std::wcout << reverse(reverse(str)) << endl; // 2回 reverse すれば、元に戻る 21}

実行させると、次のようになります。(MacOSX で g++をつかって実行)

$ g++ str.cpp $ ./a.out あいうえおabc cbaおえういあ あいうえおabc

投稿2015/03/16 13:31

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

senbe

2015/03/16 20:29

回答ありがとうございます! 日本語の処理についてわかったとき、またこのプログラム を振り返ってみたいとおもいます。
guest

0

文字列が 日本語文字を含んでいる場合は

まともな動作をしないはずです。
漢字は基本2バイトで一文字を表すので、1バイト目と2バイト目が逆順になれば文字化けするのは当然です。しかも漢字の文字コードは一種類ではないので、具体的な対策は漢字コードに合わせて考える事になると思います。
この段階でreverse()関数を書けという課題を出したのは、漢字を使わない、ASCIIコードだけで用が足りる人のはずです(笑)。

投稿2015/03/16 03:37

rubato6809

総合スコア1380

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

ソースコード拝見しました。決定的なバグが2つあります。

  1. reverse()の中の「i = k;」。これはもちろん k = i; ですね。
  2. main()関数の while ループが何をしてるか、です。

やりたい事は、getline()で一行入力して、reverse()で反転させ、結果をprintf()で表示する、これを繰返すことだと思いますが、このコードではprintf()がループの外にあります。つまり、反転させたら(表示せずに)次の行を入力しているので反転結果を表示しないのは当然です。

さらに、私のWindows機ではCygwin(GCC)とMicrosoftのVC/C++が使えるので気づいたのですが、コンパイラと、それを実行する画面の組合せが、それぞれ何かで表示されない可能性があります。VCでコンパイルしたものをコマンドプロンプト画面で実行させると正しく表示するのに、Cygwinのコンソール(mintty)で実行すると表示したはずの文字列が表示されません(対策は簡単だが)。一方、GCCでコンパイルすると、このままではコンパイルが通らなかったので、VC/C++をお使いなのかな?できればお使いになっている環境もお示しいただけると良いと思います。

それと、一旦 s[] から t[] にコピーして逆順にコピーし直してますが、s[] だけで処理は可能です。例えば"hello"なら、まず先頭と最後( h と o )を交換し、次は e と l を交換する…としていくのです。こうすれば t[] 配列は不要です。是非お試し下さい。

投稿2015/03/05 00:45

rubato6809

総合スコア1380

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

senbe

2015/03/05 01:27

ありがとうございます! rubato6809さんにご指摘いただいたバグをなおすと 結果がちゃんと表示されました。 Visual Studioについて知らないので、質問の答えになっているかはわかりませんが 私はWindows機で、GCCをインストールして使っています。 Visual Studioは使っていなくて、サクラエディタを使っています。
senbe

2015/03/05 01:38

>それと、一旦 s[] から t[] にコピーして逆順にコピーし直してますが、s[] だけで処理は可能です。例えば"hello"なら、まず先頭と最後( h と o )を交換し、次は e と l を交換する…としていくのです。こうすれば t[] 配列は不要です。 変更してみました。 読みやすいですし、使う変数が少なくて、きれいですね! ありがとうございます。
katoy

2015/03/15 22:16

文字列が 日本語文字を含んでいる場合は動作しますか?
senbe

2015/03/16 06:55

動作しませんでした。
rubato6809

2015/03/16 10:48

こちらに返事を書けばよかったんですね^^; シフトJISコードは漢字コードの一種で、まだ実際に使える場面があると思います。 ネットを検索すれば、シフトJISコードの漢字1バイト目であることを判定する「iskanji1()」と2バイト目であることを判定する「iskanji2()」という2つの関数(或いはマクロ)が見つかるはずです。それを使って、漢字なら2バイトの順序を変えずに文字列中の位置を変えるreverse()関数を作ってみて下さい。今のreverse()のように単純ではありませんから頑張りが必要ですが。
senbe

2015/03/16 20:25

rubato6809さん 回答ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問