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

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

ただいまの
回答率

90.48%

  • C

    3831questions

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

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

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 3,115

senbe

score 28

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

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

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

#include <stdio.h>
#define MAXLINE    1000    /* 入力行の最大長 */


int getline(char line[], int maxline);
void reverse(char line[]);

main()
{
    char line[MAXLINE];
    
    while ((getline(line,MAXLINE)) > 0)
        reverse(line);
    printf("%s",line);
}

/*getline : sに行を入れ、長さを返す*/
int getline(char s[], int lim)
{
    int c,i;
    
    for (i = 0; i < lim -1 && (c = getchar()) != EOF && c != '\n'; i++)
        s[i] = c;
    if (c == '\n'){
        s[i] = c;
        i++;
    }
    s[i] = '\0';
    return i;
}


/* reverse : sを tにコピーして値をいれかえる */
void reverse(char s[])
{
    int i,j,k;
    char t[MAXLINE];
    
    i = 0;
    while((t[i] = s[i]) != '\0')
        i++;
    i--;/*iは\0の1個前*/
    i--;/*iは改行コードの1個前*/
    i = k;
    
    for (j = 0; j <= k; j++) {
        s[j] = t[i];
        i--;
    }
    s[j] = '\n';
    j++;
    s[j] = '\0';
}
関数 reverse(s) では
例えば
 hello\n
と入力されたとき
s[0] にt[4] の値を代入 (s[0]に oをいれる)
...
s[4] にt[0] (s[4]に hを入れる)

というふうに考えてみました。
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • argius

    2015/03/05 09:23

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

    キャンセル

  • senbe

    2015/03/05 10:11

    Windows機です。

    キャンセル

  • senbe

    2015/03/05 10:12

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

    キャンセル

回答 3

checkベストアンサー

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 10:27

    ありがとうございます!
    rubato6809さんにご指摘いただいたバグをなおすと
    結果がちゃんと表示されました。

    Visual Studioについて知らないので、質問の答えになっているかはわかりませんが
    私はWindows機で、GCCをインストールして使っています。
    Visual Studioは使っていなくて、サクラエディタを使っています。

    キャンセル

  • 2015/03/05 10:38

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

    変更してみました。
    読みやすいですし、使う変数が少なくて、きれいですね!
    ありがとうございます。

    キャンセル

  • 2015/03/16 07:16

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

    キャンセル

  • 2015/03/16 15:55

    動作しませんでした。

    キャンセル

  • 2015/03/16 19:48

    こちらに返事を書けばよかったんですね^^;

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

    キャンセル

  • 2015/03/17 05:25

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

    キャンセル

0

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

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

std::wstring reverse(std::wstring str) {
  std::wstring ans = L"";
  const int len = str.length();
  for (int i = len - 1; i >= 0; i--) {
    ans.append(1, str.at(i));
  }
  return ans;
}

int main() {
  std::wcout.imbue(std::locale(""));

  std::wstring str = L"あいうえおabc";
  std::wcout << str << endl;
  std::wcout << reverse(str) << endl;
  std::wcout << reverse(reverse(str)) << endl; // 2回 reverse すれば、元に戻る
}
実行させると、次のようになります。(MacOSX で g++をつかって実行)
$ g++ str.cpp
$ ./a.out
あいうえおabc
cbaおえういあ
あいうえおabc

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/03/17 05:29

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

    キャンセル

関連した質問

同じタグがついた質問を見る

  • C

    3831questions

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