ページ 11

反転させて文字を表示することが出来ません。

Posted: 2008年8月06日(水) 16:36
by ヨセフ
I like sports.を.strops ekil Iになるようにしたいのですが、出来ませんでした。
メイン関数の中がおかしいようなきがするのですが、どうでしょうか?

#include <stdio.h>

/* length関数の宣言 */
int length(char *str);

int main(void)
{
char str1[100], str2[100];
int i, j = 0, len_num;

printf("文字列を入力してください。");
gets(str1);

len_num = length(str1);
printf("%d",len_num);

printf("文字列 %s を反転させると %s になります。\n", str1, str2);

return 0;
}

/* length関数の定義 */
int length(char *str)
{
int c = 0;

while(*str){
c++;
str++;
}

return c;
}

Re:反転させて文字を表示することが出来ません。

Posted: 2008年8月06日(水) 16:41
by YuO
反転させるコードがないようですが。

str2には反転させた結果を入れたいのだと思いますが,
結果として,str2は内容が不定な状態のままprintfに渡されています。

Re:反転させて文字を表示することが出来ません。

Posted: 2008年8月06日(水) 16:52
by ヨセフ
len_num = length(str1);
printf("%d",len_num);
これで反転できるつもりだったのですが・・・。

Re:反転させて文字を表示することが出来ません。

Posted: 2008年8月06日(水) 16:56
by box
length関数は、引数として与えた文字列の「長さ」を求めています。
「逆転させた文字列」を求めてはいません。

ところで、今回は、length関数も自作の対象なのですか?
文字列長を求めるには、strlenという標準関数があるのですけれど。

Re:反転させて文字を表示することが出来ません。

Posted: 2008年8月06日(水) 17:08
by ヨセフ
この問題は、足りないところをたして、結果をだすというものでした。
最初は以下のような感じでした。
 
#include <stdio.h> 

/* length関数の宣言 */ 
int length(char *str); 

int main(void) 
{ 
char str1[100], str2[100]; 
int i, j = 0, len_num; 

printf("文字列を入力してください。"); 

printf("文字列 %s を反転させると %s になります。\n", str1, str2); 

return 0; 
} 

/* length関数の定義 */ 
int length(char *str) 
{ 
return c; 
} 
<//pre> 
実行結果は前に説明した通りです。
反転の方法はfor文が必要ですか?

Re:反転させて文字を表示することが出来ません。

Posted: 2008年8月06日(水) 17:46
by KEV
for文はきっと使います。多分こんな感じ
for(i = 0; i <  len_num; i++){ /* 処理 */}
あと、実行結果って見せてくれましたっけ?

> int i, j = 0, len_num;
これ、よく見ると i に0が入ってるようで入ってません。
jだけに0を入れたかった って理由があるならこれで正解でしょうけど、
多分違うと思うので。
まあ i と j は多分あとでfor文で使うのだろうから、
そこで初期化するだろうしバグにはならないような気がします。
けど、あまりよくない書き方だとは思います。

穴埋め問題っぽいから、問題作成者が間違ってるのかも。
にしても、main関数内に i と j があるってことは
回答ではmainの中で反転処理させるつもりだったんでしょうか…。
関数作ったほうがスマートなのになぁ。

無題

Posted: 2008年8月06日(水) 18:31
by 通りすがり
コードはきちんとプレタグで囲みましょう。
何故最初だけタグを書いたり一文字違ったりして一度もきちんと書けないのでしょう?
しっかり確認して投稿しましょう。
一回できちんと投稿出来る自信がないならプレビューをしてから投稿しましょう。
それでなくても削除キーを設定しておけば投稿後も修正出来ます。
きちんと誤字やタグミスの無い文章で投稿して下さい。

Re:無題

Posted: 2008年8月06日(水) 22:04
by ヨセフ
実行する前初期化されていないとにエラーが出ます。
どうすればよいでしょう?

Re:無題

Posted: 2008年8月06日(水) 22:11
by box
最新のコードをpre, /preの両タグで挟んで、見せてください。

Re:無題

Posted: 2008年8月06日(水) 22:17
by ヨセフ
こんな感じになっています。
#include <stdio.h>

/* length関数の宣言 */
int length(char *str);

int main(void)
{
  char str1[100], str2[100];
  int i, j = 0, len_num;
  
  printf("文字列を入力してください。");
  gets(str1);
  
	for(i = 0; i <  len_num; i++){
 hen_num=>i}

  printf("文字列 %s を反転させると %s になります。\n", str1, str2);
  
  return 0;
}

/* length関数の定義 */
int length(char *str)
{
  int c = 0;
  
  while(*str){
    c++;
    str++;
  }
  
  return c;
}

Re:無題

Posted: 2008年8月06日(水) 22:26
by box
hen_num=>i}

この行は、何をしたいのでしょうか。

Re:無題

Posted: 2008年8月06日(水) 22:34
by box
【例】"abcd"を与えて、逆順の"dcba"を得る

与えた文字列"abcd"の長さは4である。
このとき、str1[/url]の中身は次のとおりである。
str1[0]:'a'
str1[1]:'b'
str1[2]:'c'
str1[3]:'d'
str1[4]:'\0'(文字列終端を表わす)

さて、逆順の文字列を得る、ということは、
str2[0]:'d'
str2[1]:'c'
str2[2]:'b'
str2[3]:'a'
str2[4]:'\0'(きちんと終端させる)
の状態にすることである。

終端の'\0'は最後にセットするとして、さて、str1[/url]の各文字(例:'a')が入っている添字番号と
str2[/url]中の同じ文字('a')が入っている添字番号との間には、どういった関係式が成り立つだろうか。
考えてみよう。

Re:無題

Posted: 2008年8月06日(水) 22:34
by ヨセフ
forでまわしたものを反転していくという考えでやってみました。

Re:無題

Posted: 2008年8月06日(水) 22:37
by box
> forでまわしたものを反転していくという考えでやってみました。

コンパイルできませんよね。

Re:無題

Posted: 2008年8月06日(水) 22:49
by ヨセフ
str[1]とstr[2]の関係をかかなくてはいけないということですか?
str[1]=aのときはstr[2]に何かがくる、という感じにするということでしょうか?

Re:無題

Posted: 2008年8月06日(水) 23:15
by box
元の文字列str1で、'a'は[0]にありますね。
同じ'a'という文字が、逆順文字列str2では[3]にありますね。

このように、同じ'a'という文字が、str1[/url]とstr2[/url]のどこに入っているかには
法則があります。その法則を見つけてください、ということです。
'b'でも'c'でも'd'でも、共通の法則です。

Re:反転させて文字を表示することが出来ません。

Posted: 2008年8月07日(木) 00:19
by ヨセフ
法則ですかぁ…。
1の箱の一番目にaが入ったら、2の箱の最後にaがくる。
という考え方ですよね?

Re:反転させて文字を表示することが出来ません。

Posted: 2008年8月07日(木) 08:47
by box
'a'という文字は、
反転前のstr1[0]と反転後のstr2[3]にあります。

'b'という文字は、
反転前のstr1[1]と反転後のstr2[2]にあります。

'c'という文字は、
反転前のstr1[2]と反転後のstr2[1]にあります。

'd'という文字は、
反転前のstr1[3]と反転後のstr2[0]にあります。

さて、上記のことから、同じ文字を格納しているstr1[/url]の添字番号と
str2[/url]の添字番号との間に、どういう関係があるでしょうか。

その仕様のコードです。

Posted: 2008年8月07日(木) 19:37
by BIOS
#include <stdio.h>
#define MAZ 15
#define ZERO 0
static char ap[MAZ]={"I speak English"};
int main(void){
char wk;
int ia,ib;
for(ia=ZERO;ap[ia+1]='\n';ia++) printf("%c",ap[ia]);
printf("\n");
for(ia=ZERO;ib=MAZ-1;ia<ib;ia++,ib--){
wk=ap[ib];
ap[ib]=ap[ia];
ap[ia]=wk;
}
for(ia=ZERO;ap[ia+1]='\n';ia++) printf("%c",ap[ia]);
printf("\n");
return ZERO;
}
以上です。APIの技術情報を交換し合いませんか?もよろしくお願いいたします。

無題

Posted: 2008年8月07日(木) 21:14
by 通りすがり
>BIOSさん

答えのコードを投稿する事はboxさんや他の閲覧者の方々もすぐ出来ますが、それはしないでいるのです。
これではboxさんが今まで答えを提示することなく丁寧に答えに導いていらっしゃった努力が無意味になってしまいます。
場合によっては正解例を示しながら解説するほうがいい場合もあるかと思います。
ただし、今回の場合そのように感じられません。
しかも何故勝手にトピを解決にしてしまっているのでしょう。

ちょっと場の空気を読まない投稿が多すぎるのじゃないでしょうか。
また、コードはタグで囲みましょう。

Re:その仕様のコードです。

Posted: 2008年8月07日(木) 21:59
by YuO
at 2008-08-07T19:37+09:00
[19944] その仕様のコードです。
BIOS wrote (No. 19820) :
(ざっくり省略)

色々とだめ。
・ZEROなんてマクロあるだけ無駄 (ZEROという単語に数値0以上の意味がないから)
・MAZは定義する必要がない。必要ならstrlenを使う
・一つ目と三つ目のfor文の条件式が明らかに間違っている
・そもそもそれらのfor文を用意する意味がない (%15sとかで十分。本来ならナル文字で終端しておくべき)
・二つ目のfor文は構文が間違っている (;が多すぎる)
API云々の前に,Cの勉強をちゃんとすべきだと思います。

Re:無題

Posted: 2008年8月07日(木) 22:07
by kaiten
>BIOSさん

>「マーク」はトピ主が選択する物です(トピ主は最後に「解決!」を選択)
>(つまりトピ主は最初質問か雑談のどちらかを選択する。返信者は選択の必要無し)

利用規約の一文です。言いたいことは通りすがりさんと同じなので言わないでおきますが。
答えを書くにしてもヨセフさんの書き方に合わせた方が親切だと思います。せめてコメント付けるとか。


本題と全く関係ないですけどなんかヒーロー戦機思い出した…やったことないのに……

Re:無題

Posted: 2008年8月07日(木) 22:18
by box
コンパイルエラー満載のコードで「解決!」って言われてもね…。

Re:無題

Posted: 2008年8月07日(木) 23:35
by ヨセフ
すいません。
分けあって投稿が出来ませんでした。
解決はまだしていません。

同じ文字を格納しているstr1[/url]の添字番号と
str2[/url]の添字番号との間にある関係は、
aが最初に出ていて、反転した後は最後に出てるということですか?
ってなると前の考えと同じになってしまいすよね・・・。
逆に動いているって事ですか?

Re:無題

Posted: 2008年8月07日(木) 23:53
by ヨセフ
文字を回して、回し終えたら、最後の文字から最初の文字までまた回すっていう考えもしてみたのですが?

あっすみません!「分けあって」ではなく、訳あってです。
ちゃんと編集が出来るように努力します。

Re:無題

Posted: 2008年8月08日(金) 01:36
by YuO
> 同じ文字を格納しているstr1[/url]の添字番号と
> str2[/url]の添字番号との間にある関係は、
> aが最初に出ていて、反転した後は最後に出てるということですか?

それを式で表して,はじめてプログラムが書けます。
まぁ,ポインタ使えば式は不要,という考え方もありますが。


> ってなると前の考えと同じになってしまいすよね・・・。
> 逆に動いているって事ですか?

やり方はひとつではないのですが,私の考えているやり方を。

今回の場合は別の配列へのコピーが入るので,
str1の添字番号からstr2の添字番号を計算で出してしまった方が楽だろう,と思います。

まずは,str1の中身が"abcde"だった場合の,
各文字のstr1における添字番号i1とstr2における添字番号i2を書き出してみてください。
表にすると分かり易くなると思います。
# これは紙と鉛筆で十分できると思います。

次に,各文字について,i1とi2の間にはどういう関係があるのか,数式化して下さい。
最後に,文字列の長さがlenの時に,str1の添字番号nにある文字はstr2の添字番号になるかを数式化して下さい。

あとは,str1の全ての文字について,上記の式を使ってstr2にコピーしていけばできあがりです。

Re:無題

Posted: 2008年8月08日(金) 21:59
by ヨセフ
返事が遅くなってすみません。最近、パソコンの調子がよくないみたいで…。
今回の反転の方法をなんとなくは理解できたのですが、プログラムとしてかくと、
よくわからなくなってしまいます。

Re:無題

Posted: 2008年8月08日(金) 22:25
by box
下表の?部を埋めてみてください。


【"abcd"を"dcba"に反転させる場合】

文字列の長さ=4
反転前:str1
反転後:str2

+--------+-----+-----+-----+-----+-----+
| ------ | 'a' | 'b' | 'c' | 'd' | '\0'|
+--------+-----+-----+-----+-----+-----+
| str1の |  ?  |  ?  |  ?  |  ?  |  ?  |
|添字No. |     |     |     |     |     |
+--------+-----+-----+-----+-----+-----+
| str2の |  ?  |  ?  |  ?  |  ?  |  ?  |
|添字No. |     |     |     |     |     |
+--------+-----+-----+-----+-----+-----+



【"abcde"を"edcba"に反転させる場合】

文字列の長さ=5
反転前:str3
反転後:str4

+--------+-----+-----+-----+-----+-----+-----+
| ------ | 'a' | 'b' | 'c' | 'd' | 'e' | '\0'|
+--------+-----+-----+-----+-----+-----+-----+
| str3の |  ?  |  ?  |  ?  |  ?  |  ?  |  ?  |
|添字No. |     |     |     |     |     |     |
+--------+-----+-----+-----+-----+-----+-----+
| str4の |  ?  |  ?  |  ?  |  ?  |  ?  |  ?  |
|添字No. |     |     |     |     |     |     |
+--------+-----+-----+-----+-----+-----+-----+

Re:無題

Posted: 2008年8月11日(月) 12:18
by ね~す
はじめまして。このスレを見ていてちょっとした思い付きがあったのですが、
このようなものはどうでしょうか。

| -4 | -3 | -2 | -1 |  0 | +1 | +2 | +3 | +4 |
|    |    |    |    |    | a  | b  | c  | d  |

ここで配列全体を文字数+1で引くと、

| -4 | -3 | -2 | -1 |  0 | +1 | +2 | +3 | +4 |   
| a  | b  | c  | d  |    |    |    |    |    |  ※ここの計算部分は配列に代入しません

そして、絶対値として計算すると、


| -4 | -3 | -2 | -1 |  0 | +1 | +2 | +3 | +4 |   
|    |    |    |    |    | d  | c  | b  | a  |

このようになる気がします。

Cは超初心者なので、ソースコードは書けませんが、この考え方が使えるのかな?と思います。
覚束ない日本語で申し訳ないです。

Re:無題

Posted: 2008年8月11日(月) 13:13
by 管理人
>ね~すさん

それでも出来ますね。
ただ、0番を最初にした方がいいかもしれません。
実際にやってみました。
答えを書いてしまうとよくないので、肝心な要素番号をさす部分だけ省略してあります。
#include <stdio.h>
#include <string.h>
#include <math.h>

int main(){
	int i,len;
	char str[10]="abcd",str2[10];
	len=(int)strlen(str);
	for(i=0;i<len;i++)
		str2=str[上記理論];
	str2='\0';
	printf("%s\n",str2);
	return 0;
}

実行結果

dcba

 
「str[上記理論]」の部分を仰っている理論の通りに番号を示す式を書けばこれでも出来ました。

Re:無題

Posted: 2008年8月11日(月) 15:22
by box
ね~すさんの考え方はすばらしいと思います。
ただ、管理人さんも書かれているとおり、
C言語の配列はゼロ始まりですので、
こんな風に考えるのがよいかもしれません。


| -4 | -3 | -2 | -1 |  0 | +1 | +2 | +3 | +4 |
|    |    |    |    | a  | b  | c  | d  |    |


ここで配列全体から「文字数-1」を引く

| -4 | -3 | -2 | -1 |  0 | +1 | +2 | +3 | +4 |
|    | a  | b  | c  | d  |    |    |    |    |


正負を反転させるとできあがり

| -4 | -3 | -2 | -1 |  0 | +1 | +2 | +3 | +4 |
|    |    |    |    | d  | c  | b  | a  |    |

Re:無題

Posted: 2008年8月11日(月) 16:03
by lbfuvab
文字列strと長さlenを渡すと逆に出力する
void PutStrReverse(char *str,int len);
を定義したとすると、
#include<stdio.h>
#include<string.h>

void PutStrReverse(char *str,int len);

void main(){
    char str[50];
    int len;
    
    puts("文字を入力してください");
    gets(str);
    puts("反転して出力します");
    PutStrReverse(str,strlen(str));
}
となりますよね。

後、PutStrReverseに関するヒントとしては
最初に出力するのはstr[len-1]で
最後に出力するのはstr[0]です。
後は上手くループを使ってやれば良いと思います。