• ベストアンサー

単語数、文字数のカウントプログラム

以下のような単語数、文字数のカウントプログラムを作ったのですが、10行目に「フォーマットは char ですが、引数は different type です」というエラーが出てしまいます。どのように修正したらよいでしょうか?教えてください。 #include <stdio.h> int main(void){ int wordcnt = 0; int charactercnt = 0; int i; char line[100]; printf("String: "); fgets(line, sizeof(line), stdin); sscanf(line, "%s", &line); if(line[0] != ' '){ wordcnt++; } for(i = 0; line[i] != '\0'; i++){ if(line[i - 1] == ' '){ wordcnt++; } if(line[i] != '\n'){ charactercnt++; } } if(wordcnt == 1){ printf("%d word,", wordcnt); }else{ printf("%d words,", wordcnt); } if(charactercnt == 1){ printf(" %d character", charactercnt); }else{ printf(" %d characters", charactercnt); } return 0; }

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

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

char line[100]; と定義していますから, &line の型は char (*)[100] です. これが (%s の期待する) char * と違っているのが原因です. それにしても, なんでこんな風に書くんだろう. 単純に line と書けばいいのに.... あと, この sscanf は危険です. #1 の「sscanfの第1引数はconst char*ですので第3引数に同じものは使わないようにしましょう」は今一つ意味不明ですが, sscanf で「読み取る領域」 (第1引数が示す) と「書き込む領域」 (第3引数以降が示す) が重なっているため未定義動作になっているはずです. C では, ほとんどの関数で「読み書きする部分が重なっていたら動作は未定義」になっています (少ない例外が memmove). あ, sscanf の %s 変換は「最初の方にある空白文字」をすべて読み飛ばしますし「そのあとの最初の空白文字までで変換終了」なので, sscanf のあとの if と for はほとんど無意味です. 仕様を確認してください.

その他の回答 (1)

  • php504
  • ベストアンサー率42% (926/2160)
回答No.1

10行目と言うことは sscanf(line, "%s", &line); これが問題ですね フォーマットと引数が合わないと言ってますので合わせてください %sはchar*ですが&lineはchar**になります そしてsscanfの第1引数はconst char*ですので第3引数に同じものは使わないようにしましょう。

関連するQ&A

  • 単語数のカウントについて

    C言語のプログラミングについて質問させていただきます。 『一行の入力に対し,入力された英文の文字数,単語数,文字の使用頻度を数える』という問題なんですが、一応プログラムを組むことはできました。 しかし、今のプログラムのままでは単語間にを連続して入力しても単語数が増加してしまいます。 そこで、単語間の空白が2文字以上でも安定して単語数を正しく数えることができるようにするためにはどのように変更すればいいのか教えてください。 よろしくお願いします。 #include <stdio.h> int main(void){ char line[100]; /* キーボード入力用汎用変数 */ int i; /* 繰り返し用カウンタ */ char temporary; /* テンポラリ */ int moji_acount[128]; /* 文字カウンタ */ int moji_count = 0; /* 文字数 */ int tango_count = 0; /* 単語数 */ /* 文字カウンタの初期化 */ for(i=32;i<128;i++){ moji_acount[i] = 0; } /* 文字列の入力 */ printf("文字列:"); fgets(line, sizeof(line), stdin); /* 繰り返し用カウンタの初期化 */ i = 0; /* 文字数を数える作業 */ while(line[i] != '\n'&& line[i] != '\0'){ moji_count++; i++; } /* 文字数の表示 */ printf("文字数:%d\n", moji_count); /* 文字をテンポラリに保存 + 文字カウンタを数える作業 */ for(i=0;i<moji_count;i++){ temporary = line[i]; moji_acount[(int)temporary]++; } /* 入力された文字と回数を表示 */ for(i=32;i<128;i++){ if(moji_acount[i] != 0){ /* 文字カウンタがゼロでないときに繰り返し */ printf("'%c': %2d個\n", (char)i, moji_acount[i]); } } /* 繰り返し用カウンタの初期化 */ i = 0; /* 単語数を数える作業 */ while(line[i] != '\n' && line[i] != '\0'){ if(line[i] == ' '){ /* もしline[i]がスペースのとき */ tango_count++; } i++; } printf("単語数:%d個\n", tango_count + 1); return 0; }

  • 配列とfor文の組み合わせがうまくいきません

    初心者なので質問文でおかしなことを言ってるかもしれませんが よろしくお願いします ソースは下に貼り付けました。 コースの数を入力し、そのコースに名前をつけるという プログラムを書いたのですが forでcoursename[0]からcoucename[3]までの4つに名前を入力しようと コース数に「4」を入力しても forによって繰り返されるのは coursename[0]からcoucename[2]までの3つでした どう直せばいいのでしょうか ==================================================== #include <stdio.h> #define MAX_COURSE 5 /*最大数*/ int main(void){ int course = 0; /*コース数*/ char coursename[MAX_COURSE][100]; /*コース名*/ char line[100]; /*入力用文字型配列*/ int i; /*コース数の入力*/ while (course < 1 || 5 < course){ printf("コース数の入力を行ってください。(1~5)\n"); printf("INPUT : "); fgets(line, sizeof(line), stdin); sscanf(line, "%d", &course); } /*コース名の入力*/ printf("コース名の入力を行ってください。\n"); for(i=0; i<course-1; i++){ printf("%d科目 : ", i+1); fgets(line, sizeof(line), stdin); sscanf(line, "%s" , coursename[i]); } return 0; } ====================================================

  • プレゼント交換プログラム

    クリスマスパーティーのプレゼント交換のためにプログラムを書いているのですがなかなか上手くいきません。下に実装したい機能(僕の考えた解決策)と僕の書いたコードを載せておくのでアドバイスをお願いします。よろしくお願いします。 実装したい機能(僕の考えた解決策) 1.自分の持ってきたプレゼントが自分に当たらないようにする (プレゼントの番号と配列に格納する順番を一致させれば解決できると 思うのですが…) 2.全員の手にプレゼントが渡るようにする (全ての数字(例えば参加者が5人なら0~4)が割り振られたことを確認し満たしていなければやり直しにすれば解決できると思ったのですが…) ---コードここから--- #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void){ char line[100]; /* キーボード入力用汎用変数 */ int participant; /* 参加者数 */ int flag = 0; int i, j; srand(time(NULL)); /* 参加者数を入力する */ printf("参加者数: "); fgets(line, sizeof(line), stdin); sscanf(line, "%d", &participant); int number[participant]; /* プレゼントの番号 */ char name[participant]; /* 参加者の名前 */ int check[participant]; /* チェック用配列 */ /* */ for(i = 0; i < participant; i++){ printf("参加者 %d 人目の名前: ", i + 1); fgets(line, sizeof(line), stdin); sscanf(line, "%s", &name[i]); } /* */ do{ for(i = 0; i < participant; i++){ number[i] = rand() % participant; check[i] = number[i]; } for(j = 0; j < participant; j++){ for(i = 0; i < participant; i++){ if(check[i] == j){ flag += 1; } } } }while(flag != participant); /* */ for(i = 0; i < participant; i++){ printf(" %s ―\―\>プレゼント %d\n", name[i], number[i] + 1); } return 0; } ---コードここまで---

  • ファイルの内容の表示

    実行時のコマンドライン引数で指定したファイルの内容を、行番号付きで画面に表示するプログラムを作る という問題です。ヒントも与えられています。 行番号付きの表示、コマンドライン引数の利用。両者を組み合わせればできるはずだ >  main関数の引数にargcとargvを指定して、コマンドライン引数をファイル名として利用する。キーボード入力を促す文(プロンプト)や改行チェックは不要なので書かないこと >  コマンドライン引数が指定されない場合は、メッセージを表示してプログラムを終了 >  ファイルの内容を画面表示する処理は、ユーザー定義関数put_file_contentsに記述する。仮引数には文字型のポインタ変数をひとつ指定し、ファイル名を受け渡せるようにする。put_file_contents自体の型は整数型(int)で、正常終了なら返り値0を返すこと。 行番号付きのプログラム#include<stdio.h> > int put_file(char *filename); > > int main() > { > char line[50]; > char *ptr; > > printf("ファイル名を入力:"); > fgets(line,sizeof(line),stdin); > ptr = line + strlen(line) - 1; > if(*ptr == '\n') { > *ptr = '\0'; > } > > put_file(line); > > return 0; > } > > int put_file(char *filename) > { > FILE *fp; > char buf[100]; > int line_no; > > fp = fopen(filename,"r"); > if (fp == NULL){ > printf("%sを開けません\n",filename); > return 1; > } > line_no = 1; > while (fgets(buf,sizeof(buf),fp) != NULL){ > printf("%3d: ",line_no); > printf("%s",buf); > line_no++; > } > fclose(fp); > > return 0; > } で、コマンドライン引数のプログラムは#include<stdio.h> void write_key_inputs(char *filiname); int main(int argc, char *argv[1]) { write_key_inputs(argv[1]); return 0; } void write_key_inputs(char *filename) { FILE *fp; char buf[100] ; fp = fopen(filename,"w"); while(fgets(buf, sizeof(buf),stdin) != NULL) { fputs(buf, fp); } fclose(fp); return ; } です。これらを組み合わせて少しいじると出来るみたいなのですが、できていません。ちなみに私が考えたプログラムは #include<stdio.h> int put_file_contents(char *filename); int main(int argc,char *argv[]) { int i; if(argc == 1){ printf("コマンドライン引数がありません\n"); return 1; } for(i = 0;i<argc;i++) printf("argv[%d]は「%s」です\n",i,argv[i]); put_file(i); return 0; } int put_file(char *filename) { FILE *fp; char buf[100]; int line_no; fp = fopen(filename,"r"); line_no = 1; while (fgets(buf,sizeof(buf),fp) != NULL){ printf("%3d: ",line_no); printf("%s",buf); line_no++; } fclose(fp); return 0; } です。コマンドライン引数は表示されるのですが、行番号が表示されません。どうしたらいいでしょうか??

  • c言語 文字数のカウント 合わない

    こんにちは. c言語のプログラムを書いて疑問に思ったことがあるのでお尋ねします.以下のプログラムで,data.txtに書かれている文字を読み取り,総文字数,スペース,タブ,ニューラインの数をカウントしようと思いました.スペース,タブ,ニューラインは正しくカウントするのですが,総文字数char_counterの数が合いません.ファイルから文字を読み取る時に使った,loop_counterもchar_counterと同義だと思いloop_counterを表示させてみたところ,こちらは文字数を正しくカウントしているようです. I am checking how it works. という文字列が入ったファイルなのですが,char_counterは100文字を越えてしまいます.どうしてloop_counterとchar_counterで違う値が出てしまうのでしょうか?解答をお待ちしております.その他正しく動いている部分に関しても,変な書き方のところがあればそれも指摘して頂ければ嬉しいです. なお,原因解明のために試行錯誤していて,ファイルの読み取りでは配列の[]の中身を足していき,文字を比較する際にはポインタの値を足していくという変なプログラムになっています.ご了承下さい. #include <stdio.h> #include <stdlib.h> #define BUF_SIZE (256) #define EXIT_FAILURE (1) int main() { FILE *fp; char read_line[BUF_SIZE]; int loop_counter = 0; fp = fopen("data.txt", "r"); if(fp == NULL) { printf("file open error\n"); exit(EXIT_FAILURE); } while((read_line[loop_counter] = getc(fp)) != EOF) { loop_counter++; } read_line[loop_counter] = '\0'; fclose(fp); if(fp == NULL) { printf("file close error\n"); exit(EXIT_FAILURE); } /* this counts the whole char numbers including space*/ int char_counter = 0; int space_counter = 0; int tab_counter = 0; int newline_counter = 0; char *read_line_address; read_line_address = &read_line; while(*read_line_address != EOF) { char_counter++; switch(*read_line_address) { case ' ': space_counter++; break; case '\t': tab_counter++; break; case '\n': newline_counter++; break; default: break; } read_line_address++; } printf("%s\n", read_line); printf("space %d ", space_counter); printf("tab %d ", tab_counter); printf("newline %d ", newline_counter); /* printf("whole chars %d\n", char_counter); */ printf("whole chars %d\n", loop_counter); return 0; }

  • 素数を判定するプログラム

    整数をひとつ入力して、それが素数かどうかを判定するプログラムを作ったのですが、素数でないものを入力しても「素数です」といわれます。 どうもfor文が評価されていないような気がしますが、原因がわかりません。 // homework4.cpp : コンソール アプリケーションのエントリ ポイントを定義します。 #include <stdio.h> int main(int argc, char* argv[]) { int number; int n = 2; int i; printf("1より大きい整数を入力してください: "); scanf("%d",&number); while (number <= 1) { printf("1より大きい整数を入力してください: "); scanf("%d",&number); } if (number == 2) { printf("%dは素数です\n",number); goto OUT; } else { for (; n == number - 1; n++) { i = number % n; if (i == 0) printf("%dは素数ではありません\n", number); if (i == 0) goto OUT; } } printf("%dは素数です\n", number); OUT: return 0; } どうかよろしくお願いします。

  • C言語で 数字を配列に入力し,q Qで終了させたい

    O.reillyのC実践プログラミング第3版で、勉強しています。 p105の 実習7-6 「いくつかの数字が入力されたとき、正の数がいくつあるか、負の数がいくつあるかを  数えるプログラムを作成せよ」に取り組んでみました。    例えば 「1 -1 2 -2 3 -3 -4 -5 で8つの数があり、正が3 負が5を出力させたい」のです。  入力の終わりは、q,Qで、終了させたいと考えました。  でも、「8個の数字を配列に入力させq、Qで入力終了」のところがうまくいきません。  次のようなプログラムで行き詰まっています。  どこを手直しすればいいのか教えて下さい。 #include <stdio.h> #include <math.h> #define KOSU 10 /*入力できる個数*/ char line[10];/*入力した数を受けるためのバッファ*/ int plus_count = 0;/*プラスカウンター*/ int minus_count = 0;/*マイナスカウンター*/ int number[20]; int given_number; int i; int main(void) { printf("+、ーの数を 入れなさい。(最大20まで)\n 終わるときは、qを入れる\n"); { for(i = 0; i < KOSU; i++) { fgets(line, sizeof(line), stdin); sscanf(line, "%d", &given_number); number[i] = given_number; /*ここからした、qを入れるとそこで終了のはずがうまく動きません 10個入れたらちゃんと終わるのですが。*/ if ( (given_number == 'q') || (given_number == 'Q') ) break; } } for(i = 0;i < KOSU;i++) { printf("number[%d] = %d \n", i, number[i]); } /*正負の数を数えることにする。*/ for(i = 0;i < KOSU;i++) { if(number[i] > 0) plus_count++; else minus_count++; } printf("plus is %d\n",plus_count); printf("minus or zero is %d\n",minus_count); }

  • ラベリング処理プログラム

    画像のラベリング処理プログラムを作っているんですが どうもうまく実行できません。よければ教えていただけないでしょうか。 #include<stdio.h> #include<stdlib.h> int column, row; unsigned char val[4] = {0,0,0,0}; unsigned char tmp[255]; int pos_y[4] = {-1, 0, 1, 0}; int pos_x[4] = {0, 1, 0, -1}; int i, j, x, y, label, level, label1; int label_count = 1; unsigned char *in, *out; void labeling_main(); void labeling_search(); void labeling_main() { for(i = 0; i < y; i++){ for(j = 0; j < x; j++){ printf("aaa\n"); if(out[i * x + j] == 255){ printf("bbb\n"); fflush(stdout); out[i * x + j] = label_count; labeling_search(label_count, i, j); label_count++; } } } } void labeling_search(int label_count, int x, int y) { for(i = 0; i < 4; i++){ if(out[(pos_y[i] + y) * x + (pos_x[i] + x)] == 255){ out[(pos_y[i] + y) * x + (pos_x[i] + x)] = label_count; labeling_search(label_count,(pos_y[i]+y),(pos_x[i]+x)); } } printf("ccc\n"); } int main(int argc, char *argv[]) { int result; int head, Magic; unsigned char *image, *in, *out, *res, *ros; FILE *fin, *fout; if(argc!=3){ printf("Usage : %s input output\n",argv[0]); exit(1); } fin = fopen(argv[1],"rb"); /* -------------------- ヘッダ取得ここから -------------------- */ fgets(tmp,255,fin); if(tmp[0]!='P') return 0; sscanf(tmp,"P%d",&Magic); if(Magic < 1 || Magic > 6) return 0; do fgets(tmp,255,fin); while(tmp[0]=='#'); sscanf(tmp,"%d %d",&x,&y); if(x < 1 || y < 1) return 0; fgets(tmp,255,fin); sscanf(tmp,"%d",&level); /* ヘッダの確認 */ printf("P%d\n",Magic); printf("%d %d\n",x,y); printf("%d\n",level); /* 画素の読み込み */ in = (unsigned char *)malloc(sizeof(unsigned char) *x*y); fread(in,sizeof(unsigned char),x*y,fin); fout = fopen(argv[2],"wb"); fprintf(fout,"P%d\n",Magic); fprintf(fout,"# My new PGM\n"); fprintf(fout,"%d %d\n",x, y); fprintf(fout,"%d\n",level); fwrite(out, sizeof(unsigned char),x*y, fout); out = (unsigned char *)malloc(sizeof(unsigned char) *x*y); //2値画像 for (i = 0; i < y; i++) { for (j = 0; j < x; j++){ if(in[i * x + j] > 120){ out[i * x + j] = 0; }else if(in[i * x + j] <= 120){ out[i * x + j] = 255; } } } labeling_main(); printf("Max label number:%d\n",label_count); free(in); free(out); fclose(fin); fclose(fout); } コンパイルは通るのですが実行するとlabeling_mainの if文でセグメンテーションが出てしまいます。

  • プログラムの雛型

    学校でプログラミングをやっているのですが、全くわからず行き詰まってしまいました。 /*   文   */のところがわかりません。 どなたかわかる方いらっしゃいましたらご指導のほどよろしくおねがいします。 #include <stdio.h> #define SIZE 1024 #define ALPH 26 /* alphabet: 26 */ #define CH 36 /* alphabet: 26 + number:10 */ main() { char line[SIZE], c; int i, j; int num[CH]; /* 文字の使用回数 */ int ch[CH]; /* 使用回数の多い文字順の情報 */ int max, tmp; /* 初期化 */ for (i = 0; i < CH; i++) { /* 配列 num, ch の初期化 */ } /* 一行ずつ読み込み、一行ずつ処理 */ while(fgets(line, SIZE, stdin) != NULL) { for (i = 0; line[i] != '\0'; i++) { c = line[i]; /* if 文 */ } } /* 使用回数の多い文字の順番を調べる */ for (i = 0; i < CH-1; i++) { max = i; /* for 文と if 文と値の交換部分 */ } /* 出力部分 */ for (i = 0; i < CH; i++) { if (i < ALPH) /* printf 文 */ else /* printf 文 */ if (ch[i] < ALPH) /* printf 文 */ else /* printf 文 */ } }

  • char型+char型ってint型? if(char型==int型)?

    C言語の「汎整数拡張(インテグラルプロモーション)」というものに関するものだと思います。 char型とchar型を加えた結果は、char型でしょうか。それともint型でしょうか。 (下のプログラムの printf("sizeof(a[0]+a[1])は%d\n", sizeof(a[0]+a[1])); /* char型+char型 */ という部分の結果は4なので、int型と考えるべきなのかな。) 私は、char型とint型の加算の結果はint型だと思っていましたが、 char型とchar型の加算の結果はやはりchar型だと思っていました。 (それが間違えているのでしょうか。) if(a[0]==i) /* char型とint型の比較(?) */ の部分では、左辺はchar型、右辺はint型ですが、このように型の違う変数を比較しても文法上構わないのでしょうか。 (私は、「比較は必ず型の同じもの同士でしかできない」と思っていました。) 左辺はchar型のように見えて、じつはint型ですか。 #include <stdio.h> int main(void) { char a[4]; int i=77; printf("sizeof(int)は%d\n", sizeof(int)); printf("sizeof(char)は%d\n", sizeof(char)); printf("sizeof('M')は%d\n", sizeof('M')); printf("sizeof(a[0])は%d\n", sizeof(a[0])); a[0]='M'; a[1]=7+6; a[2]=a[0]+a[1]; printf("sizeof(a[0]+a[1])は%d\n", sizeof(a[0]+a[1])); /* char型+char型 */ printf("sizeof(+a[0])=%d\n", sizeof(+a[0])); if(a[0]==i) /* char型とint型の比較(?) */ puts("a[0]==i"); else puts("a[0]!=i"); return(0); } ちなみにワーニングもエラーもなんにもでません。

専門家に質問してみよう