🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

Q&A

解決済

4回答

3146閲覧

C言語でポインタにファイルから読み込んだ文字列を代入する方法

josterjonathan

総合スコア24

C

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

0グッド

0クリップ

投稿2019/11/15 08:40

前提・実現したいこと

C言語で、char型のポインタに文字列を代入したい。
ファイルからfgetcで文字を一文字ずつ読み込み、空白か改行までの文字列を単語として認識した後、それをポインタに代入したい。
どうしても配列ではなくポインタを使いたい。

試して成功したこと

一度配列を作り、それをポインタに渡した。

C

1 char str[40], *w; 2 int ch, n; 3 4 n = 0; 5 while ((ch = fgetc(fp)) != EOF) { 6 if (ch != ' ' && ch != '\n') { 7 str[n++] = ch; 8 } else { 9 str[n] = '\0'; 10 w = str; 11 printf("%s\n", w); 12 n = 0; 13 } 14 }

実行結果(成功)

$ ./a.out it is a wonderful idea!

試したが失敗したこと

直接ポインタに渡す。//が付いている行でSegmentation fault: 11が発生。

C

1 n = 0; 2 while ((ch = fgetc(fp)) != EOF) { 3 if (ch != ' ' && ch != '\n') { 4 *w = ch; // Segmentation fault: 11 5 w++; 6 } else { 7 *w = '\0'; // Segmentation fault: 11 8 printf("[%s]\n", w); // Segmentation fault: 11 9 n = 0; 10 } 11 }

実行結果(失敗)

$ ./a.out Segmentation fault: 11

なぜ後者の実装方法ではいけないのか教えていただきたいです。
よろしくお願い致します。

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

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

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

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

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

guest

回答4

0

ポインタというのは、変数の位置を指し示す変数です。
指し示しているだけなので、そこに文字列を入れようとしても入りません。
まず、入れようとする文字列以上のメモリ領域を作って、そこの位置をポインタに代入し(これでポインタはメモリ領域を指し示す)、そこで改めてポインタ先に文字列をコピー、代入する必要があります

投稿2019/11/15 08:53

y_waiwai

総合スコア88038

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

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

0

ベストアンサー

C言語に於いては、文字列という基本型はなく、文字型の配列で終端にナル文字('\0')が配置されたものを文字列として扱う、ということになっているだけです。
つまり文字列は文字の配列なので、「配列」無しに文字列を扱うことは出来ません。

char型のポインタに文字列を代入したい

どこかにすでに「文字列」すなわちcharの配列が存在していて、それをポインタが指すようにすることは「文字列の代入」と言えるでしょう。また、質問文には

空白か改行までの文字列を単語として認識した後、それをポインタに代入したい。

とあります。つまり、文字列=charの配列を先に生成してあって、それをポインタに代入することはあり、と読み取れます...いや、そう読まないと、C言語としては処理が不可能になります。

どこかに「配列を使ってはいけない」という明示的な条件があるのでしょうか。先に書いたように、文字列そのものが配列であり、また一般にポインタを使うということと配列を使うということは排他条件ではありません(なにしろ、配列は配列の先頭要素へのポインタとして扱われることも普通だったりするのですから)。

一度配列を作り、それをポインタに渡した。

それで十分じゃないですか?

投稿2019/11/16 07:15

thkana

総合スコア7703

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

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

0

ポインタ変数は変数のアドレスを代入するものです。
以下ならわかりますが、アドレスを代入してもいないのにいきなりアドレス先の値を参照しようとしては駄目です。

C

1char str[40], *w; 2char ch; 3w = &ch; 4str[n++] = *w;

投稿2019/11/15 09:00

LineOfLightning

総合スコア253

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

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

0

実体を設定されていないポインタは、何処を指しているかわからないです。
必ず、データの格納領域を確保して、そのアドレスを設定しましょう。

text

1usr ~/Project/test % ./a.out 2str=0x7fff977d40f0 w=0x7fff977d4218 3str=0x7fff977d40f0 w=0x7fff977d40f0 4usr ~/Project/test % cat t2.c 5#include <stdio.h> 6 7int main(void) 8{ 9 char str[40], *w; 10 // 11 printf("str=%p w=%p\n",str,w); 12 w= str; 13 printf("str=%p w=%p\n",str,w); 14 // 15 return 0; 16}

投稿2019/11/15 08:55

編集2019/11/15 09:05
cateye

総合スコア6851

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

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

cateye

2019/11/15 09:34

通常は「"warning: variable 'w' is uninitialized when used"」(使用時にwは初期化されていない)のようなワーニングが出ると思います。
pepperleaf

2019/11/15 12:08

> のようなワーニングが出ると思います。 コンパイラが明記されていないので、不明ですね。
cateye

2019/11/15 14:58 編集

失礼、こちらの環境は・・・clang version 10.0ですが、 警告を抑止してない限り、初期化漏れはワーニングが出るのでは?
cateye

2019/11/15 14:58 編集

問題が出てるわけですから、コンパイラの警告オプションは可能な限り入れて、その上で、納得の行く警告は外す(抑止、あるいは無視する)・・・・・と、思っていましたが?
pepperleaf

2019/11/16 01:08

コンパイラの警告チェックは有意義ではあると思いますが、初期設定で全てがでるものではないですね。特に初期設定漏れは、古いコンパイラで見た記憶が無いですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問