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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C

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

Q&A

3回答

991閲覧

ファイル内のデータを格納

oshieroya

総合スコア0

C

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

0グッド

0クリップ

投稿2022/03/28 06:41

前提

ここに質問の内容を詳しく書いてください。
(例)
ファイル内(words.txt)にある二千数百個の単語(1行に1単語)を読み込んで配列に格納します。それを1列10個ずつ出力します。

ここに実現したいことを箇条書きで書いてください。

•読み込んだ単語を配列に格納したいです。

発生している問題・エラーメッセージ

Format specifies type 'char *' but the argument has type 'int'
Incompatible pointer types passing 'char [1]' to parameter of type 'FILE *' (aka 'struct __sFILE *')

該当のソースコード

c

1#include <stdio.h> 2 3int main() 4{ 5 6 char siny[] = {0}; 7 FILE *fp; 8 char words[10000] = {0}; 9 10 fp = fopen("words.txt","r"); 11 if(fp == NULL) { 12 printf("ファイルを開くことが出来ませんでした\n"); 13 return -1; 14 } 15 16 rewind(fp);//先頭にファイルポインタを戻す Return file pointer to beginning 17 18 int i = 0; 19 while(fgets(siny,3000,fp) != NULL) { 20 printf("%s",siny); 21 fscanf(siny,"%s",words[i]); 22 i++; 23 } 24 25 fclose(fp); 26 27 return 0; 28 29 30}

試したこと

1行ごとに読み込んでいるのでそれごとにi++して1単語ずつ入れているつもりです。
3000なのは二千数百個の単語なのでそれよりも多い適当な数字です
fscanfで格納を試みましたができませんでした。

*1列10個ずつ出力します。と書いていますが、このコードは途中なので、とりあえず単語を全て格納する所を解決したいです。

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

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

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

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

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

guest

回答3

0

コードみるに文字列がメモリ上でどのように扱われているのかをあまり理解できていないようなので、その辺をもう一度調べてみてはいかかでしょうか?

単語(文字列)自体が配列なので配列の一つの要素に単語を読み込むのは無理です。
単語一つで配列の要素を複数使用する事になります。
1次元配列に入れた数値のように複数の文字列を扱うには2次元配列にする必要があります。
↓サンプル

c

1#include <stdio.h> 2#define WMax 5000 // 単語の最大数 3#define WCMax 64 // 単語の最大文字数(バイト数) 4 5int main() 6{ 7 FILE* fp; 8 char words[WMax][WCMax] = { 0 }; 9 int wcnt; 10 11 fp = fopen("words.txt", "r"); 12 if (fp == NULL) { 13 printf("ファイルを開くことが出来ませんでした\n"); 14 return -1; 15 } 16 17 //2次元配列に単語(文字列)を読み込む 18 for (wcnt = 0; wcnt < WMax; wcnt++) { 19 if (fgets(words[wcnt], WCMax, fp) == NULL)break; //文字列を読み込む 20 //改行コードを探して消す(↑でfscanf使えば不要だがfscanfは改行以外も分割される) 21 for (int i = 0; i < WCMax; i++) { 22 if (words[wcnt][i] == '\n') { 23 words[wcnt][i] = NULL; 24 break; 25 } 26 } 27 } 28 29 fclose(fp); 30 31 //表示 32 for (int i = 0; i < wcnt; i++) { 33 printf("%s ", words[i]);//単語の後ろにタブをつけて表示 34 if (!((i + 1) % 10))printf("\n");//10単語ごとに改行 35 } 36 37 return 0; 38}

あと全部を1次元配列に読み込んで単語をNULL文字で区切りポインタ配列に単語の先頭のポインタを代入すると、2次元配列に入れたのと同じようにアクセスできます。
↓サンプル

c

1#include <stdio.h> 2#include <stdlib.h> 3 4int main() 5{ 6 FILE* fp; 7 char* data; 8 char** words; 9 fpos_t fsize = 0; 10 int cnt = 1; 11 12 fp = fopen("words.txt", "r"); 13 if (fp == NULL) { 14 printf("ファイルを開くことが出来ませんでした\n"); 15 return -1; 16 } 17 18 //ファイルサイズ取得 19 fseek(fp,0,SEEK_END); 20 fgetpos(fp, &fsize); 21 fseek(fp, 0, SEEK_SET); 22 23 //ファイルサイズ+1分メモリ確保 24 data = (char*)calloc(fsize+1, sizeof(char)); 25 if (data == NULL) { 26 printf("メモリの確保に失敗しました。\n"); 27 return -1; 28 } 29 30 //すべて読み込む 31 fread(data,fsize,1,fp); 32 //ファイルを閉じる 33 fclose(fp); 34 35 //単語数(改行)をカウント 36 for(int i = 0; i < fsize; i++) { 37 if (data[i] == '\n')cnt++; 38 } 39 40 //ポインタ配列を単語数分メモリ確保 41 words = (char**)calloc(cnt, sizeof(char*)); 42 if (words == NULL) { 43 printf("メモリの確保に失敗しました。\n"); 44 return -1; 45 } 46 47 //ポインタ配列に単語の先頭のポインタを代入 48 words[0] = &data[0]; 49 for (int i = 0, j = 1; j < cnt; i++) { 50 if (data[i] == '\n') {//もし改行コードなら 51 data[i] = NULL; //NULL文字に変換(単語で区切る) 52 words[j] = &data[i] + 1;//次の単語の頭のポインタを代入 53 j++; 54 } 55 } 56 57 //表示(ポインタ配列も2次元配列と同じようにアクセスできる) 58 for (int i = 0; i < cnt; i++) { 59 printf("%s ", words[i]); 60 if(!((i+1)%10))printf("\n"); 61 } 62 63 //メモリ開放 64 free(words); 65 free(data); 66 67 return 0; 68}

投稿2022/03/29 14:37

編集2022/04/05 15:17
kousatu

総合スコア225

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

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

0

そのエラーメッセージは fscanf(siny, "%s", words[i]); に、型の不一致が2つあることを指摘しています。

まず fscanf() の引数はどうあるべきか確認します。
C言語 fscanf 使い方
書式  int fscanf(FILE *fp, 書式指定文字列, 格納可変個引数); となってます。

(1) Format specifies type 'char *' but the argument has type 'int'

は「 char * 型(charへのポインタ型)を渡すべきなのに、 int 型の値を渡しているよ」ということらしい。第2引数が "%s" なので char へのポインタでなければならない、ということではないかと。

fscanf(siny, "%s", words[i]); の第三引数が words[i] では型が合わないのです。
words[i] だと words というの配列の、i 番目の値です。文字配列の中の、ある一要素の値です。その値はポインタではありませんから。

char words[10000] ; と変数定義されているので、その一要素の型は char です。その char 型の値は、自動的に int 型に拡張されて、関数(この場合は fscanf())に渡ります。なのでエラーメッセージに 'int' という型名が現れたのです。

(2) Incompatible pointer types passing 'char [1]' to parameter of type 'FILE *' (aka 'struct __sFILE *')

これは fscanf(siny, "%s", words[i]); の第一引数 siny の型が違うと言ってます。
「fscanf() の第一引数は FILE * 型 なのに siny は char 型の配列だ。それでは互換性のないポインタを渡してしまう」といった意味です。

ちなみに, 'char [1]' とは、「char型の要素が1個だけある(要素数が1の)配列」という意味です。
char siny[] = {0}; と変数定義したので、そうなります。つまり、この変数定義に誤りがあります。


fscanf(fp, "%s", &words[i]); とでもすればエラーメッセージは出なくなりますが、これだけでは済まないでしょう。

私は、 fscanf() ではなく sscanf() を使って

C

1 while(fgets(siny, 3000, fp) != NULL) { 2 printf("%s", siny); 3 sscanf(siny, "%s", &words[i]);

とするか

C

1 while(fscanf(fp, "%s", &words[i]) != EOF) { 2 printf("%s", &words[i]); 3 i++;

とすることを考えましたが、これでもまともに動くとは思えません。一見動いたように見えても、質問者が期待したようには動いていないでしょう。
siny[], words[] 等の データ構造を見直し、その使い方も見直す必要があると思います。目的に合ったデータ構造を用意しないとまともな結果を出せません。


追加。
rewind() する必要はありません。fopen()直後はファイル先頭から読み出せます。

1行ごとに読み込んでいるのでそれごとにi++して1単語ずつ入れているつもり

一行に一単語、それを words[i] に格納する「つもり」が、実際はどうなのか。
エラーなくコンパイルできる次のコードが

C

1 i = 0; 2 while (fscanf(fp, "%s", &words[i]) != EOF) { 3 printf("%s\n", &words[i]); // 読み込んだ単語を表示する 4 i++; 5 } 6 printf(" => %s\n", words); // words[] 配列の結果を表示する

"This" "is" "a" "pen" という4単語(4行)を char words[10000]; 配列に読み込む様子です。
結果、words[] には "Tiapen" という文字列が残ります。こうしたいわけじゃないでしょ。
words[]を図示

投稿2022/03/29 06:49

編集2022/03/31 00:33
rubato6809

総合スコア1380

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

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

0

char siny[] = {0};

こいつの配列の要素数は、1です

while(fgets(siny,3000,fp) != NULL) {

さっそくアクセス違反ですね

投稿2022/03/28 06:55

y_waiwai

総合スコア87774

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問