• ベストアンサー

文字列の中に数値0が混入している場合の文字列出力法

C言語初心者です。 宜しくお願い致します。 char ss[10]; ss[0] = 'A'; ss[1] = 'B'; ss[2] = 'C'; ss[3] = 0; /* '0' ではなく、0 */ ss[4] = 'E'; ss[5] = '0'; ss[6] = 'G'; ss[7] = '\0'; printf("%s",ss); 上記の場合、出力されるのは、ABC までだと思いますが、 数値0 の所で、出力を終了させずに、Gの所まで出力させることは できますでしょうか。 (「そもそも、なぜそんなことをしたい?」という疑問は、とりあえず横に置いておいて下さい。) なお、文字'0'の所では出力は終了しない、ということは理解しております。 つまり、数値0ではなく、文字'0'の場合には、そのまま「0」が出力される、と理解しております。 数値0 と NULL文字¥0 の所で出力は終了する、という理解のもと、 質問をさせて頂いております。 宜しくお願い致します。

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

  • ベストアンサー
  • titokani
  • ベストアンサー率19% (341/1726)
回答No.5

数値0をそのまま0として出力したいなら、printfを使えばいいだけです。 つまり、ss[i]に数値が入っているのなら、 printf("%d",ss[i]); です。 一方、ss[i]に入っている値を文字として出力したいのなら、putcharを使います。 putchar(ss[i]); ということは何らかの条件でこの2つを切り替える必要があります。どんな条件で切り替えましょうか。

nbsp0606
質問者

お礼

>ss[i]に数値が入っているのなら、printf("%d",ss[i]); 文字'0'として出力しても、数値0として出力しても、 見た目に違いはないとは思いますが、 出力方法には様々なカタチがあることを勉強させて頂きました。 こちらの回答を受け、さらにモヤモヤが広がりました…。 printf("%d",ss[3]);  /* ss[3] = 0; ★ 0 が出力される。*/ printf("%s",ss[5]);  /* ss[5] = '0'; ★ 0 が出力される*/ printf("%s",ss[3]);  /* ss[3] = 0; ★ 何も表示されない?!*/ 文字列として 0 を見た場合には、それは終端文字として解釈されるため、 何も表示せずに終了となるのかな、と私は考えたわけです。 (実際にやってみれば分かることではありますが、 結果的にそうなったからと言って、それがそのまま、考え方の上でも正しかったとは 言い切れないので、こうして質問をさせて頂いております。) 何かおかしな所がありましたら、ご指摘下さい。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (7)

回答No.8

> 数値0 の所で、出力を終了させずに、Gの所まで出力させることは > できますでしょうか。 すでにやり方までご助言いただいているはずですが。 #include <stdio.h> int main( void ) { char ss[] = { 'A', 'B', 'C', 0, 'E', 0, 'G', 0 }; fwrite( ss, sizeof(char), sizeof(ss), stdout ); fwrite( "\n", sizeof(char), sizeof("\n"), stdout ); } 文字列として処理すれば、文字列の定義が'\0'までの連続した文字群ですからできません。 ※ printfの"%s"変換など が、文字列として処理しなければ(改行まで処理するだとか、文字数を指定して処理するだとかすれば)問題なくできます。 例えばUTF16ではASCIIの印字可能文字に'\0'が含まれますので、UTF16使う端末では実際出力されます。 ※ UTF16文字列処理に専用の関数作ったり大きさを指定するなどで別の方法で行ったり。fgetsの様な'\n'('\0'以外の文字)を終端に使う関数なども使えます。 http://homepage1.nifty.com/nomenclator/unicode/ucs_utf.htm ※ 上記ページに『UCS-2のU+0041の文字(すなわち 'A')を,UTF-16BEでは00 41という2バイトで, UTF-16LEでは41 00という2バイトで表します』と解説されている通り。

nbsp0606
質問者

お礼

より突っ込んだ回答を提示して頂き、ありがとうございます。 ぼんやりとではありますが、さらによく分かるようになった気がします。 参考にさせて頂きます。

全文を見る
すると、全ての回答が全文表示されます。
  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.7

ちょっと抜けがあったので、追加。 >printf("%s",ss[3]);  /* ss[3] = 0; ★ 何も表示されない?!*/ は、環境によっては落ちずに"(null)"など表示される場合があります。 # GNU libc ライブラリあたりでそんな動作したことがあったと…

nbsp0606
質問者

お礼

こちらも参考になりました、ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。
  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.6

>printf("%s",ss[5]);  /* ss[5] = '0'; ★ 0 が出力される*/ >printf("%s",ss[3]);  /* ss[3] = 0; ★ 何も表示されない?!*/ こちらは、期待する動作はしないでしょう。 一般保護違反などで落ちると思われます。 書式%sが要求するのは、const char *(またはchar *)です。 渡したものはchar配列中の1要素なのでcharです。 printf()はcharで渡された'0'を「文字列が格納されている先頭アドレス」として解釈し、参照しようとしますので… 結果として一般保護違反(アクセス違反)となります。 printf("%c",ss[5]);  /* ss[5] = '0'; ★ 0 が出力される*/ printf("%s",&ss[3]);  /* ss[3] = 0; ★ 何も表示されない?!*/ ならば問題ありませんが… >printf("%d",ss[3]);  /* ss[3] = 0; ★ 0 が出力される。*/ こちらは想定している通りです。 # "%d"の方は、printf()内部で数値=>数字変換し、その結果を出力しています。

nbsp0606
質問者

お礼

>一般保護違反などで落ちる >printf()はcharで渡された'0'を「文字列が格納されている先頭アドレス」として解釈 初心者である私には、このあたりはまだ難しかったです。 たぶん、もう少しC言語の学習が進めば、理解できることなんだろうと思います。 その時まで、温存しておきます。笑 きっと、「型(あるいは、書式)の問題」なんでしょうね。

全文を見る
すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

JIS C の規格に従っている限り, いかなる処理系においても「整数リテラル 0」と「文字リテラル '\0'」は等しくなります (int の 0 として扱われる). つまり, ほかの回答でも言われているのですが「同じく 0 であるのに ss[3] では止まらず ss[7] で終了する」ためには, ss 以外の「何か」を必要とします.

nbsp0606
質問者

お礼

>「整数リテラル 0」と「文字リテラル '\0'」は等しくなります (int の 0 として扱われる). ありがとうございます、とてもよく分かりました。

全文を見る
すると、全ての回答が全文表示されます。
  • jjk65536
  • ベストアンサー率59% (66/111)
回答No.3

まず、一般的な処理系では「数値0 と NULL文字¥0」は等しく0であることは ご存知でしょうか? つまり、ss[3]とss[7]の区別がつかないことを意味します。 ss[7]で文字列が終了することは、別の方法で明らかにする必要が発生します。 それを踏まえて関数をつくると以下のような感じでしょうか。 #include <stdio.h> void myprint(char *src, int len) { int i; for(i=0; i<len; i++) { if( (src[i] >= 'A' && src[i] <= 'Z') || (src[i] >= 'a' && src[i] <= 'z') || (src[i] >= '0' && src[i] <= '9') ) putchar(src[i]); } } int main(int argc, const char *argv[]) { char ss[10]; ss[0] = 'A'; ss[1] = 'B'; ss[2] = 'C'; ss[3] = 0; /* '0' ではなく、0 */ ss[4] = 'E'; ss[5] = '0'; ss[6] = 'G'; ss[7] = '\0'; myprint(ss, 10); return 0; } 数値0は表示しないように作ってありますが、もし数値0を文字列0として 表示したいのでしたら、if()文追加して拾ってあげればいいと思います。 ちなみにC99環境でしたら、isgraph()等で判定するとエレガントです。

nbsp0606
質問者

お礼

>まず、一般的な処理系では「数値0 と NULL文字¥0」は等しく0であることは ご存知でしょうか? はい、参考書には、そのような記述がありましたが、 その記述に対し、私は自分の読解に自信が持てず、半信半疑でおりました。 (しかし、今、おかげさまで、確実な理解へと変わりました。) >それを踏まえて関数をつくると以下のような感じでしょうか。 わざわざ、私のためにありがとうございます。 私にはまだ難しいコード例でしたので、 もう少し力を付けてから改めて解読してみたいと思います。

全文を見る
すると、全ての回答が全文表示されます。
  • titokani
  • ベストアンサー率19% (341/1726)
回答No.2

どんな出力結果を望むのかによります。 また、 ss[0] = 'A'; ss[1] = 'B'; ss[2] = 'C'; ss[3] = 0; /* '0' ではなく、0 */ ss[4] = 'E'; ss[5] = 0; ss[6] = 'G'; ss[7] = '\0'; とか、 ss[0] = 'A'; ss[1] = 'B'; ss[2] = 'C'; ss[3] = 0; /* '0' ではなく、0 */ ss[4] = 'E'; ss[5] = 0; ss[6] = 'G'; ss[7] = 0; ss[8] = 'I'; ss[9] = '\0'; などの場合にはどうなってほしいのでしょうか?

nbsp0606
質問者

お礼

数値0を、そのまま 0 として出力させられるのか、について考えてみたかったんです。 つまり、「~がしたい」という質問ではなく、 「~はできるのか?」といった主旨の質問になります。 分かりにくくて、すみません。 単純に 0 という文字を出力したいのであれば、 '0'として考えれば、希望は叶いますよね。 ということで、 私が知りたいことは以下のようなことになります。 '0'ではなく、0 として配列に格納したデータを、 0 として出力することは可能なのか、 もし、可能な場合、その方法はどうなるのか、ということです。 と、ここまで書いてみて、 不毛な質問をしている気がしてきました…。 回答を頂いておきながら、こんなことを言って、すみません。 もし何かアドバイスを頂けましたら、とても嬉しく思います。 宜しくお願い致します。

全文を見る
すると、全ての回答が全文表示されます。
  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.1

ss[3]をどう出力させたいですか。 例えば int i; for(i=0;i<7;i++) {  putchar(ss[i]); } でできると思いますが、ss[3]はコントロール・コードになるのでどう表示されるかはコンソール依存でしょう。

nbsp0606
質問者

お礼

>ss[3]をどう出力させたいですか。 ABC0E0G と出力させたいと考えております。 それであれば、 "ABC0E0G" として出力させればいいじゃないか、と言われてしまいそうですが。笑 数値0を「0」として、つまり、文字として、出力したい場合には、 素直に'0'として考えて出力すればいい、ということなのでしょう。 だから、配列の1要素として、数値0 を入れる場合には、 それは終端文字として解釈される、と考えるべきなのでしょうね。 >ss[3]はコントロール・コードになるのでどう表示されるかはコンソール依存でしょう なるほど、参考にさせて頂きます。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 文字列の途中に「0」がある場合の文字出力について

    C言語初心者です。宜しくお願い致します。 char ss[10]; /*【1】0ナシの文字列*/ strcpy(ss,"abcdefg"); printf("%s\n",ss); /*【2】0アリの文字列*/ strcpy(ss,"abc0efg"); printf("%s\n",ss); /*【3】0アリ(NULL文字アリ)の文字列*/ strcpy(ss,"abc\0efg"); printf("%s\n",ss); 【2】、【3】の文字列を最後(~fg)まで出力させるには、 どうしたら良いのでしょうか。 (0や¥0を、文字情報の一部として扱いたい場合、という意味です。) 宜しくお願い致します。

  • Cでは文字列をどのように認識するのでしょうか?

    C言語には文字列型というものは存在しないと教わりました。 文字列の終わりはヌル文字で認識できますが、 文字列型というものが存在しないのに何故次のバイトを読もうとするのですか? たとえばchar str[] = "abc";、あるいはchar *p = "abc";とあったとして printf(str);あるいはprintf(p); でなぜabcが出力されるのでしょうか?なぜaの次にbがbの次にcがあるとわかるのでしょうか? char型で先頭アドレスが渡された場合、ヌル文字を見つけるまでアドレスをインクリメントし続けるという決まりでもあるのでしょうか? それに文字列型というものが存在しないなら''と""を分ける意味もないのでは??

  • 文字列の中から必要なデータを抜き出す

    VC++6.0 です。 計測機器から受信したデータ(文字列)の中から、必要なデータだけを抜き出したいのですが、 うまく抜き出すことが出来ません。アドバイスいただけませんでしょうか? 受信する文字列は 伝送制御キャラクタSTX(0x02) "文字列" 伝送制御キャラクタETX(0x03) のように受信します。 抜き出すための目印?がキーボードで入力できるような文字列の場合は過去ログにありました以下のコードで 抜き出すことが可能でした。 抜き出すための目印を 0x02 や 0x03 にする為にはどうしたら良いでしょうか?   //文字列版 #include <stdio.h> #include <string.h> #include <stdlib.h> char *cut(const char *str, const char *ss, const char *es, char *buff){ /* str の ss の次から es の前までの文字列をbuff に切り出す */ char *wk, *s, *e, *c; wk=strdup(str); if(wk==NULL)return NULL; s=strstr(wk, ss); if(s==NULL){ free(wk); return NULL;} c=s+strlen(ss); e=strstr(c, es); if(e==NULL){ free(wk); return NULL; } *e='\0'; strcpy(buff, c); free(wk); return buff; } int main(void){ const char url[]="?http://www.sample.ne.jp/";? char buff[32]; printf("//~/:%s\n", cut(url , "//", "/", buff)); return 0; }

  • printfの引数指定でなぜ文字列ポインタがOK?

    C言語初心者です。現在入門的書籍の1冊目を読んで勉強中です。VBAは経験あります。 printf関数について質問です。 引数の指定で通常  printf("書式文字列", 変数で値) のようにしていしますよね。  char a = 'A';  printf("%c", a); ←ここで変数aの値の「A」を渡している と理解しています。 上の例で、書式文字列を省略し、  printf(a); だとエラーがでます。 しかし、文字列の場合  char a[] = "ABC";  printf(a); はエラーにならず、「ABC」と出力されます。 さらに、ポインタを使用して  char a[] = "ABC";  char *b = a;  printf(b); もエラーにならず、上と同様に「ABC」と出力されます。 まず、この2つの例で、エラーとならず、書式文字列が省略できているのが不思議です。 これが書式文字列を省略しているわけではないとするならば、 「printf(a)」=「printf(b)」=「printf("ABC")」ということになりますが、 「printf(a)」のaも「printf(b)」のbも"ABC"の先頭のアドレスを示しているんですよね。 ということは、printf関数の引数の指定方法は  printf(書式文字列 または 文字列の先頭アドレス, 変数) というように考えられるのですが、認識があっているでしょうか? そもそも文字列について、VBAでは文字と文字列の区別はなにも意識せずに扱えたのでやや戸惑っているのですが、C言語では文字列の場合は宣言時に  char a[] のように宣言し、あとは先頭のアドレスで文字列を使っていくという感じなのでしょうか? 初心者なもので何が理解できていないのかもよくわからない状況で、質問がわかりづらいかもわかりませんが、よろしくお願いします。

  • 配列やポインタに文字列を設定することについて

    ◎1------------------------- #include<stdio.h> int main(void) { char ss[80]; scanf("%s",ss); printf("%s\n",ss); return 0; } ---------------------------- ◎2--------------------------- #include<stdio.h> int main(void) { char *ss="abcde"; printf("%s\n",ss); return 0; } ------------------------- ◎3---------------------- #include<stdio.h> int main(void) { char *ss; ss="abcde"; printf("%s\n",ss); return 0; } ------------------------- 以上3つプログラムで疑問をいだいたのですが、 まず◎1で、これは例えば、 cahr ss[80]="abc"; のように配列ssに文字列"abc"そのものを入れているのか、 char *ss="xyz"; のようにまず"xyz"という文字列をメモリ上のどこかに設定し、その先頭番地をssに代入しているのか、どちらの考えでいいのかわかりません。 次に、◎2、3ではどちらも正常に実行できたのですが、特に◎3で「ss="abcde";」と記述していますが、ssにはアドレスを代入するという認識かあるのですが、文字列定数を代入しても問題ないのか?という疑問があります。 教えていただけたら嬉しいです。

  • 文字列の検索

    先日同じ質問をして、プログラムの内容を修正したのですが、今度は2つ文字列を入力した後0が無限にでてきます… どなたか解説・指摘・模範解答などおねがいします。 内容は最初にある文字列を入力して、その後別の文字列を入力して、 後に入力した文字列が最初に入力した文字列に含まれていれば1、 含まれていなければ0と表示するプログラムです。 (使用するのは#include<stdio.h>のみ、ポインタ変数必須です) #include<stdio.h> char *mystrfin(char *a, char *b); int main(void) { char *c,*d; char str1[100],str2[100]; printf("1>>"); fgets(str1,100,stdin); printf("2>>"); fgets(str2,100,stdin); *mystrfin(c,d); } char *mystrfin(char *a,char *b){ char *c,*d; while(c!='\0'){ c=a; d=b; while(c!='\0' && d!='\0'){ if(c!=d) printf("0"); break; c++; d++; } } if(d='\0') printf("1"); a++; return a; return NULL; } 例 検索対象文字列:asdfghjkl 検索文字列:sdf 1と出力 検索対象文字列:asdfghjkl 検索文字列:qwer 0と出力

  • C言語

    以下のプログラミングについて。 #include<stdio.h> int main(void) { char ss[6]="ABCDE"; printf("ss[0]=%c\n",ss[0]); printf("ss[1]=%c\n",ss[1]); printf("ss[2]=%c\n",ss[2]); printf("ss[3]=%c\n",ss[3]); printf("ss[4]=%c\n",ss[4]); printf("ss[5]=%c\n",ss[5]); printf("ss=%c\n",ss); return 0; } 以上のプログラミングの出力は、 ss[0]=A ss[1]=B ss[2]=C ss[3]=D ss[4]=E ss=ABCDE となると思うのですが、あってますか? また、 printf("ss[5]=%c\n",ss[5]); は、char文でいうとヌル(ナル)文字の\0の部分に相当すると思うのですが、printf("ss[5]=%c\n",ss[5]);の出力制御はどうなるんですか? ご教授願います。

  • c言語の文字列出力

    プログラミング超初心者です サイトで文字列の出力について調べていたところ c言語は変数に文字列を代入することができないのでstrcpy関数を使い以下のようにするとあります char s[5]; strcpy(s, "ABCDE"); printf("%s\n", s); ところが他のサイトでは以下のように説明しています char s[5] = "ABCDE"; printf("%s\n", s); 明らかに後者の方が簡単で良いように見えるのですが違いはなんですか? あと、文字列の配列の指定?の[5]の部分なのですが 数字を記載しているところがほとんどですが省略しているところも有ります どんな文字列が入るかわからない場合もありますがここは省略しない方が良いのですか? よろしくお願いします

  • 指定した文字列を探して・・・

        第1引数の文字列中に第2引数で指定した文字がある場合に、その     文字のあるアドレス(ポインタ)を返す関数doko()作成し、     プログラムを完成させよ。     指定した文字がない場合はNULL(ヌルポインタ)を返すものとする。     配列の[](カギカッコ)を利用しないで作る事     main内は変えないこと いろいろと模索したのですが、strcpyなどは使うのでしょうか? 参考サイトを見たりしたり、ほかの質問などを見たのですが なかなか理解できずに現在にいたってます 以下のコードのdokoは沢山やりすぎたので一番シンプルな間違い方をしています 何かご指摘あればお願いします #include <stdio.h> #define MAX 128 char* doko(char *,char); int main() { char buf[MAX]; char *p = "abcdef12345"; char *r; r = doko(p, 'f'); if (r == NULL) { printf("mojiretsu ni f toiu moji ha arimasen\n"); return 0; } printf("%s (= f12345)\n", r); scanf("%s", buf); r = doko(buf, 'x'); if (r == NULL) { printf("mojiretsu ni x toiu moji ha arimasen\n"); return 0; } printf("%s\n", r); return 0; } char* doko(char *p,char a) { while(*p){ if(*p == a){ return p; } if(*p != a){ return NULL; } ++p; } }

  • 文字列の検索

    プログラミングの勉強の際に下のプログラムを作りました。 最初にある文字列を入力して、その後別の文字列を入力して、 後に入力した文字列が最初に入力した文字列に含まれていれば1、 含まれていなければ0と表示するプログラムです。 コンパイルは通るのですが、文字列を2つ入力すると 「セグメンテーション違反です」と表記されます… どこが悪いのでしょうか? どなたか解説・指摘・模範解答などおねがいします。 (使用するのは#include<stdio.h>のみ、ポインタ変数必須です) #include<stdio.h> char *mystrfin(char *a, char *b); int main(void) { char str1[100],str2[100]; printf("1>>"); fgets(str1,100,stdin); printf("2>>"); fgets(str2,100,stdin); *mystrfin(c,d); } char *mystrfin(char *a,char *b){ char *c,*d; while(*c!='\0'){ c=a; d=b; while(*c!='\0' && *d!='\0') if(*c!=*d) printf("0"); break; c++; d++; } if(*d='\0') printf("1"); a++; return a; return NULL; }

このQ&Aのポイント
  • 飯綱町のゴミの収集頻度、分別方法、指定ごみ袋について教えてください。
  • 飯綱町ではゴミの収集頻度はどのくらいで行われていますか?また、ゴミの分別方法についても教えてください。
  • 飯綱町のゴミの収集には指定ごみ袋が必要なのでしょうか?指定ごみ袋の色やサイズについても教えてください。
回答を見る