C言語で文字列配列から姓と名を表示する方法

このQ&Aのポイント
  • C言語の入門で文字列配列から姓と名を表示する方法についての質問です。
  • 質問者はアンダースコアを使って姓と名を区切り、3つの表示方法を試みています。
  • しかし、名の後ろに変な漢字が入ってしまう問題が発生しています。
回答を見る
  • ベストアンサー

文字表示の問

 学校でC言語の入門をやっています。今回の問題は、30文字分の配列を用意してから、「Suzuki_Ichiro」のように、ローマ字で姓と名の間にアンダースコアを入れた文字列を入力し、(1)そのまま表示、(2)アンダースコアなしで姓と名の間は空白で表示 「Suzuki Ichiro」、(3)姓と名を逆順に(姓と名の間は空白)表示 「Ichiro Suzuki」 というものです。  下は自分が考えたプログラムです。(左の番号は行番号で実際は入力していません) #include<stdio.h> 3 void main() 4 { 5 char x[30],a;   //30文字分の配列を用意 6 int i,p,q; 7 8 gets(x);     //文字列の入力指示 9 10 puts(x);     //文字列の表示(上の(1)) 11 12 for(i=0;i<30;i++) 13 { 14 15 if(x[i]=='_') p=i;  //アンダースコアの検出 16 if(x[i]=='\0') q=i;  //ヌルコードの検出 17 18 } 19 20 for(i=0;i<p;i++) 21 { 22 putchar(x[i]);  //最初の文字からアンダースコ                   アの1文字前まで表示 23 24 } 25 26 printf(" ");     //空白の表示 27 28 for(i=p+1;i<q;i++) 29 { 30 putchar(x[i]);  //アンダースコアの1文字後か                   らヌルコードの前まで表示 31                (上の(2)) 32 } 33 34 printf("\n"); 35 36 for(i=p+1;i<q;i++) 37 { 38 putchar(x[i]);  //同様に「名」の表示 39 } 40 41 printf(" ");     //空白の表示 42 43 for(i=0;i<p;i++) 44 { 45 putchar(x[i]);  //「姓」の表示(上の(3)) 46 } 47 48 printf("\n"); 49 50 }  以上です。このプログラムで実行すると、下のようになります。 Suzuki_Ichiro →(1) Suzuki Ichiro崇    →(2) Ichiro崇 Suzuki    →(3)  名の後ろに変な漢字が入ってしまうのです。原因は、  if(x[i]=='\0') q=i;  //ヌルコードの検出 のところでヌルコードの位置がちゃんと読み込めてないと考えています。本来なら、ヌルコード(\0)はIchiroの「o」の1文字後につくはずですが、ヌルコードが「o」のずっと後ろになってしまっているような気がします。  どうすれば、うまくいくでしょうか。よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Werner
  • ベストアンサー率53% (395/735)
回答No.2

そのコードではx[30]の一番後ろにある'\0'の位置(index)がqに入ってしまいます。 (最初の'\0'より後ろはゴミが入っているのでqの値も無意味。) 最初の'\0'を検出した時点でループをbreakを使うなどして抜けてください。 なお、'\0'終端の文字列が入っているとわかっているならループの終了条件自体を'\0'の検出にすることが多いと思います。 あと、うまくいってないと思うのならその部分にprintfを入れるなどして 自分の期待通りの動作をしているか確認してみましょう。 > if(x[i]=='\0') q=i;  //ヌルコードの検出 の部分でqの値を出力するだけでもかなりの手がかりが得られるはずです。

houdentaro
質問者

お礼

 ご回答ありがとうございます。教えていただいたように、最初の'\0'をみつけたらループを抜けるようにしたら解決しました。  わかりやすい解説ありがとうございました。  たすかりました。

その他の回答 (2)

noname#88356
noname#88356
回答No.3

とりあえず char x[30], a; は char x[30] = {0}, a; //={0}で配列の内部を全部0で初期化 としてみるとある程度答えに近づけるかもしれません。

noname#88356
noname#88356
回答No.1

#include <stdio.h> int main(){ char str[ 80 ] = {0}; scanf("%s", str ); puts("\n出力結果:"); // そのままで表示 puts( str ); // _を空白に変えて表示 for ( int i = 0; str[ i ]; i++ ) { if ( str[ i ] == '_' ) printf(" "); else putchar( str[ i ] ); } puts(""); // 逆順で表示 int Start = 0; for ( int i = 0; str[ i ]; i++ ) //アンダーバーの位置を得る { if ( str[ i ] == '_' ) Start = i; } for ( int i = Start + 1; str[ i ]; i++ ) //アンダーバーの位置から描画 { putchar( str[i] ); } printf(" "); for ( int i = 0; i < Start; i++ ) //アンダーバーの位置まで描画 { putchar( str[i] ); } } コードが読みにくかったので自分で考えてみましたがこんな感じでどうでしょう?

関連するQ&A

  • ‘*’をツリー状に表示しろという問題なんですが・・・。

    ‘*’をツリー状に表示しろという問題なんですが・・・。 #include<stdio.h> int main(void){ int x,i; for(x=1;x<=5;x+=2){ for(i=1;i<=x;i+=1){ putchar('*'); } putchar('\n'); } for(x=5;x<=10;x+=2){ for(i=1;i<=x;i+=1){ putchar('*'); } putchar('\n'); } for(x=7;x<=13;x+=2){ for(i=1;i<=x;i+=1){ putchar('*'); } putchar('\n'); } for(x=9;x<=17;x+=2){ for(i=1;i<=x;i+=1){ putchar('*'); } putchar('\n'); } return 0; } ツリーの数的にはこれでいいんですが、問題には「ツリー状」って書いてあるんですが これでは左詰めになってしまいます。 しかし教科書をみても右詰めや左詰めしか書いてなく、 どうやって中央でそろえるのかわかりません。 お願いします。

  • 文字化けして表示される。

    本プログラムは、8色の色(白、黒、赤、青、黄、緑、橙、茶)から四文字を選択して重複なく表示させるプログラムです。 ところが、表示させるときに文字化けして「菌数」などと文字化けして表示されてしまいます。 これはなぜなのでしょうか? #include<stdio.h> #include<stdlib.h> #include<time.h> int main(void) { char *iro[8]={"白","黒","赤","青","黄","緑","橙","茶"}; int x,i,j; char atesase[4]; srand(time(NULL)); /*重複をなくすための処理*/ for(i=0;i<4;i++) { do{ x=rand()%8; for(j=0;j<i;j++) { if(atesase[j]==x) { break; } } }while(j<i); atesase[i]=x; } /*表示させるための処理*/ for(i=0;i<4;i++) { printf("%c",iro[atesase[i]][0]); } return 0; }

  • ダンププログラムの結果表示で2バイトの場合

    ダンププログラムを作っています。 右のファイルの中身を表示する際に、16個目のデータが2バイト(漢字、全角文字など)だった場合、正しく表示されません。 改行前に2バイト目を表示したいのですがどうしたらよろしいでしょうか。 実行結果 /*----------------------- ..printf("ダンプ 表示するファイル 名を入力してくだ さい(ESC.キーで I了)\n");....... .printf("\n");.. ......scanf_s("% s",.fname);..... .if(error.=.fope n_s(&fp,.fname,. "rb").!=..0).{.. ...printf("ファ Cルがオープンで ォません\n");.... -----------------------*/ #include <stdio.h> #include <string.h> void DispData(void); FILE *fp; int main(void) { errno_t error; // エラーコード char fname[64] = { 0 }; // ファイル名 while(1) { printf("ダンプ表示するファイル名を入力してください(ESC キーで終了)\n"); printf("\n"); scanf_s("%s", fname); if(error = fopen_s(&fp, fname, "rb") != 0) { printf("ファイルがオープンできません\n"); } else { DispData(); break; } } printf("\n"); return 0; } void DispData(void) { int i = 0; int n; long addr = 0; unsigned char buf[16]; printf("ADRESS "); for(i=0; i<16; i++) { printf(" %02X", i); } printf(" DATA\n\n"); // ファイルの終了までファイルの内容をbufに1バイトサイズ、16要素で読み込む while( (n = fread(buf,sizeof(unsigned char),16,fp)) > 0) { //アドレスの表示 printf("%08lX ",addr); //読み込んだファイルの内容を16進数で表示 for(i = 0;i < n;i++){ printf("%02X ",buf[i]); } //16個に満たない分はスペースを表示 if(n < 16) { buf[i] = '\0'; for(;i < 16;i++){ printf(" "); } } printf(" "); for(i = 0;i < n; i++) { if((buf[i] >= 0x00) && (buf[i] <= 0x20) ) { putchar('.'); } else { putchar(buf[i]); } } printf("\n"); addr += 16; } }

  • 困っています

    これを三段で実行してみたのですが、うまく表示できません。下のようになります。どこが間違っているか教えてください。お願いします。          *         *        * #include <stdio.h> int main(void) { int i, j, ln; printf("何段を表示しますか?"); scanf("%d", &ln); for(i=1; i<=ln; i++){ for(j=1; j<=ln-i; j++) putchar(' '); for(j=1; j<=i * 2 - 1; j++); putchar('*'); putchar('\n'); } return(0); }

  • 文字の表示なのですが

    int i; int len = length[n]; for( i = 0; i <= len; i++ ){ printf("%c ", path[n][i] + 'A' ); } printf("%c\n", goal + 'A' ); } このままだと、 ABCDEFGHIJ・・・の順に表示されてしまいます。 SABCDEFGHI・・・と表示したいのですがどのようにすればいいのでしょうか。

  • 直角三角形を表示するプログラム

    下記のプログラムを実行するとコマンドプロントになにも表示されず、強制終了しなければならなくなってしまいます。 whileのところがおかしいのはわかったのですが、この書き方の何がいけないのかが分かりません。 初歩的な質問で申し訳ありませんが、回答していただけると有難いです。 #include <stdio.h> int main(void){ int count, i; printf("何段ですか?"); scanf("%d", &count); for(i = 1; i <= count; i++){ while(i-- > 0){ putchar('*'); } putchar('\n'); } return 0; }

  • C++ の多次元配列なんですが

    int i,j; int (*p)[2][3]; int *x; int a[2][3] = {{1,2,3},{4,5,6}}; p = &a; x = &a[0][0]; for ( i = 0; i < 2; i++ ) { for ( j = 0; j < 3; j++) { printf (" %d", (*p)[i][j]); } } printf (" | "); for ( i = 0; i < 2; i++ ) { for ( j = 0; j < 3; j++) { printf (" %d", *(x + ( i * 3 + j )) ); } } printf (" | "); for ( i = 0; i < 6; i++ ) { printf (" %d", *(x + i) ); } これで大丈夫でしょか?

  • 文字列を大文字にするプログラムがわかりません。

    小文字を大文字に、大文字はそのまま、それ以外は表示しないプログラムなんですが、 「それ以外を表示しない」というところが書けません。 #include <stdio.h> int main(void) { char x; char *p; puts("文字列を入力"); scanf("%s", &n); for(p = &n; *p != '\0'; p++){ if(*p >= 'a' && *p <= 'z'){ *p = *p - 'a' + 'A'; } } printf("%s\n", &n); return 0; } これではもちろん数字などはそのまま表示されてしまいます。 しかも、4文字までは普通に大文字で表示されるんですが 6文字だとcoredumpedしてしまいます。 すいませんが、ソース書いて教えていただけると嬉しいです。

  • for文

    以下のプログラムのforの条件文がなぜこれで動くのかよくわからないので 教えていただけないでしょうか? #include<stdio.h> int main(void) { int i; char str[] = "ABC"; char *ptr = "123"; for(i=0;str[i];i++) putchar(str[i]); putchar('\n'); for(i=0;ptr[i];i++) putchar(ptr[i]); putchar('\n'); printf("str = \"%s\"\n",str); printf("ptr = \"%s\"\n",ptr); return(0); }

  • strtokでの空文字への置き換え

    大したことじゃないと言えばそうかもしれませんが、ちょっと氣になるんで質問させてください。 C言語でstrtokという函數ありますよね。 第1引數の文字列を、第2引數の文字列を構成する文字で區切る。 第2引數の文字を見つけたら、それを空文字('¥0')に置き換える。 字句の最初の文字へのポインタを返す。 このようなものだと理解しています。 次のプログラムを實行してみました。 #include <stdio.h> #include <string.h> int main(void) { char string[]="XYZ1231ABC"; int i; printf("%s\n", string); putchar('\n'); printf("%s\n", strtok(string, "1A")); printf("%s\n", strtok(NULL, "1A")); printf("%s\n", strtok(NULL, "1A")); printf("%s\n", strtok(NULL, "1A")); putchar('\n'); for(i=0; i<=10; i++) printf("string[%d]=%c\n", i, string[i]); return 0; } 結果 XYZ1231ABC XYZ 23 BC (null) string[0]=X string[1]=Y string[2]=Z string[3]= string[4]=2 string[5]=3 string[6]= string[7]=A string[8]=B string[9]=C string[10]= 私が思うには、string[7]は空文字に置き換わってしまうはずだと思うんですが、 結果は'A'のままです。 ここが '¥0'に置き換わるかどうかは しょり系によって異なるのでしょうか。

専門家に質問してみよう