• ベストアンサー

C言語で文字配列の問題がわかりません

初めて質問します。最近、C言語の勉強をし始めた者ですが、今回「20字以上の行を全て印字せよ。」という演習プログラムを書いています。 専門書の方では文字配列の単元の演習問題なのですが、例題を参考にして以下にここまでは自力で書きました。しかしこのソースコードに対して実行したところ、どうやら「20字以上ある行の、次の行」が印字されているようで、全く原因がわかりません。 putcharの使用が必須だったのですが、試しに関数putlineを消して printf("%s",line); で出力してみるとうまくいきました。どうやら関数putlineに問題があると思っているのですが(ここは完全に自力だったため^^;)、ご指摘、アドバイス頂けると光栄です。 よろしくお願いしますm(_ _)m #include<stdio.h> #define MAXLINE 1000 int getline (char s[], int lim) { int c,i; for (i=0; i<lim-1 && (c=getchar()) !=EOF && c!='\n'; i++){ s[i]=c; } if (c= ='\n'){ s[i]=c; i++; } s[i]='\0'; return i; } int putline (char t[]) { int c,i; for (i=0; (c=getchar()) !=EOF && c!='\n'; i++){ t[i]=c; putchar(t[i]); } if (c= ='\n'){ t[i]=c; putchar(t[i]); } return 0; } main() { int len; char line[MAXLINE]; while( (len=getline(line,MAXLINE) )>0 ){ if (len>20){ putline(line); } } }

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

  • ベストアンサー
  • yaha_2007
  • ベストアンサー率21% (13/61)
回答No.2

・コメント文がない 演習問題といえども、日頃からコメントを付加する習慣を つけたほうがいいですよ。 人の書いたプログラムなんて初見では意味不明です。 ・インデントがない プログラムが非常に見づらく感じます。 あと、問題の原因は putline関数の中でline配列に新たに文字列を入力している為です。 確認ですけど、getline関数が文字列を入力し、 putline関数が文字列を出力する関数ですよね? ならputline関数の中でgetcharしなくてもいいはずです。

その他の回答 (7)

  • yaha_2007
  • ベストアンサー率21% (13/61)
回答No.8

特に無いと思います。 頑張ってください

mirtan
質問者

お礼

わかりました。ありがとうございます^^ Cを学び始めてから日が浅いですが、自力で考えることを忘れずに精進します。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.7

> 配列tから一文字ずつ取り出す 配列tのn番目の要素を取り出すときは t[n] と書きます。

mirtan
質問者

お礼

度々のアドバイスありがとうございます。 関数、配列についてまだ理解できていない点が多々あるので、よく学んで行きたいと思います。

  • yaha_2007
  • ベストアンサー率21% (13/61)
回答No.6

老婆心ながら一つ忠告しておきますが 「なんとなく」や「イメージ」ではプログラムは作れません。 ちゃんと関数の機能やアルゴリズム、仕様を理解して作ってください。 たとえ”まぐれ”で上手くいったとしても、 中身の分からないプログラムは無価値です。 とりあえず、どこがどのように分からないのか 示していただかないと、答えようがありません。 もうちょっと情報ください。

参考URL:
http://www.bohyoh.com/CandCPP/C/Library/hindex.html
mirtan
質問者

補足

確実に理解していくように努めます。 関数getlineとmainの部分は理解できています。分からない部分は関数putlineのなかで、「配列tから一文字ずつ取り出す。」という部分でした。これまでの演習で、getcharとputcharは関数内で同時に使われる、つまり  int c; c = getchar(); while (c != EOF) { putchar( c ); c = getchar(); } という感じでputcharの前には必ずgetcharがなくてはならないのだと勘違いをしていました。 みなさんからの指摘を受けこのように書き換えてみました。 int putline (char t[ ]) /*関数の宣言*/ { int n; for (n=0; t[n] != '\0'; n++){ /*'\0'まで配列tを一文字ずつとりだす*/ putchar( t[n] ); /*配列tの出力*/ } return 0; } 結果うまくいったようです。シンプルにまとめることができたと思うのですが、もっと明確にすべきところはありますでしょうか?

  • yaha_2007
  • ベストアンサー率21% (13/61)
回答No.5

#2です。 インデント消えるんですか!知らなかったスイマセン >putline内にgetcharは必要ないとのことでしたが、どのように >putcharを用いたらよろしいんでしょうか? 初心者で本当にお手数 >おかけします^^;;; そちらのプログラムの正確な仕様が分からないので 関数名から推測して暫定的にお答えします。 putline関数の中ではputcharは必要ありません。 >「20字以上ある行の、次の行」が印字されている この場合印字されている文字列を獲得しているのはgetline関数でなく putline関数だと思われます。 おそらく目指しているのは (1)getlineで文字列取得 (2)20文字以内ならputlineで表示 という仕様だと思います。 しかし、getcharをputline内においた場合 せっかくgetline関数で取得した文字列を それが20文字以上だった場合、putline関数で再度取り直しています。 その結果、問題が生じています。

mirtan
質問者

補足

問題が起きてる部分は何となくですが、その原因が理解できました。 >おそらく目指しているのは >(1)getlineで文字列取得 >(2)20文字以内ならputlineで表示 はい、その通りです。配列tから一文字ずつ取り出す、というイメージもわかるのですが、取り出す=「getchar」しか浮びませんでした。 違いますよね^^; もう少しご教授頂けますか?

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.4

putline()で、出力すべきデータは配列tに入っています。 tから1文字ずつ取り出し、putchar()してください。 1文字ずつ取り出すのが終わるのは、'\0'が見つかったときです。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.3

> ・インデントがない > プログラムが非常に見づらく感じます。 仮に、元のソースがタブやスペースできちんとインデントしていたとしても、 アップロードした時点できれいさっぱり消えてしまいます。残念なことですけれど。 例えば全角スペースを使えば、アップロード結果はインデントしているように見えますが、 そうするとそのままコピー&ペーストしたのではコンパイルできない、 という痛しかゆしの状態です。

mirtan
質問者

お礼

asuncionさんの仰る通りです^^; コピーペーストの結果、かなり見にくくなってしまったのに気付かなくて…すいませんでした。 初めての投稿だったもので、コメント文がないなど、気が付かなくてこれもまたすいませんでした。これから気をつけたいと思ってます。 putline内にgetcharは必要ないとのことでしたが、どのようにputcharを用いたらよろしいんでしょうか? 初心者で本当にお手数おかけします^^;;;

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

putline関数の機能(役割分担)は何でしょうか? getline関数で入力を受け持っている上に、 さらにputline関数で入力を行なう必要はあるのでしょうか? putline関数は、引数で受け取った内容を出力する、 という機能に特化すべきではないでしょうか。

関連するQ&A

  • 配列の配列?

    80字より長い行を全て印字するというプログラムを作ろうと思います。 それで今現在下記の状態なんですが #include <stdio.h> #define MAXLINE 1000 int getline(char line[], int maxline); void copy(char s1[], char s2[]); int main(int argc, char* argv[]) { int len; int max; char line[MAXLINE]; char longest[MAXLINE]; max = 0; while((len = getline(line, MAXLINE))> 0){ if(len > 80){ max = len; copy(longest, line); } } if(max > 0){ printf("%s", longest); } return 0; } int getline(char s[], int lim) { int c, i; for(i = 0; i < lim -1 && (c = getchar()) != EOF && c != '\n'; ++i){ s[i] = c; } if(c == '\n'){ s[i] = c; ++i; } s[i] = '\0'; return i; } void copy(char s1[], char s2[]) { int i; i=0; while((s1[i] = s2[i]) != '\0'){ ++i; } } この状態だと80字以上の行を1行しか表示しません。 おそらくは配列の配列を使って保存しておくのだとは考えたのですが 使い方がわかりません。教えて下さい。

  • コンパイルするとエラーに。C言語(改め)

    インクルード 定義 メイン関数 エラー内容 が収まりませんでした; (長すぎてどうすればよいのやら;) int readlines(char *lineptr[], int maxlines) { int len, nlines; char *p, line[MAXLEN]; nlines = 0; while ((len = getline(line, MAXLEN)) > 0) if (nlines >= maxlines || (p = alloc(len)) == NULL) return -1; else { line[len-1] = '\0'; strcpy(p, line); lineptr[nlines++] = p; } return nlines; } char *alloc(int n) { if (allocbuf + ALLOCSIZE - allocp >= n) { allocp += n; return allocp - n; } else return 0; } void kr_qsort(char *v[], int left, int right, int (*comp)(void *, void *)) { int i, last; void swap(char *v[], int i, int j); if (left >= right) return; swap(v, left, (left + right)/2); last = left; for (i = left+1; i <= right; i++) if ((*comp)(v[i], v[left]) < 0) swap(v, ++last, i); swap(v, left, last); kr_qsort(v, left, last-1, comp); kr_qsort(v, last+1, right, comp); } void swap(char *v[], int i, int j) { char *temp; temp = v[i]; v[i] = v[j]; v[j] = temp; } void readargs(int argc, char *argv[]) { char c; int atoi(char *); while (--argc > 0 && (c = (*++argv)[0] == '-' || c == '+') { if (c == '-' && !isdigit(*(argv[0]+1))) while (c = *++argv[0]) switch (c) { case 'd': option |= DIR; break; case 'f': option |= FOLD; break; case 'n': option |= NUMERIC; break; case 'r': option |= DECR; break; default: printf("sort: illegal option %c\n", c); error("Usage: sort -dfnr [+pos1] [-pos2]"); break; } else if (c == '-') pos2 = atoi(argv[0]+1); else if ((pos1 = atoi(argv[0]+1)) < 0) error("Usage: sort -dfnr [+pos1] [-pos2]"); } if (argc || pos1 > pos2) error("Usage: sort -dfnr [+pos1] [-pos2]"); } } void writelines(char *lineptr[], int nlines, int order) { int i; if (order) for (i = nlines-1; i >= 0; i--) printf("%s\n", lineptr[i]); else for (i = 0; i < nlines; i++) printf("%s\n", lineptr[i]); } int charcmp(char *s, char *t) { char a, b; int i, j, endpos; int option, pos1, pos2; int fold = (option & FOLD) ? 1 : 0; int dir = (option & DIR) ? 1 : 0; i = j = pos1; if (pos2 > 0) endpos = pos2; else if ((endpos = strlen(s)) > strlen(t)) endpos = strlen(t); do { if (dir) { while (i < endpos && !isalnum(s[i]) && s[i] != ' ' && s[i] != '\0') i++; while (j < endpos && !isalnum(t[j]) && t[j] != ' ' && t[j] != '\0') j++; } if (i < endpos && j < endpos) { a = fold ? tolower(s[i]) : s[i]; i++; b = fold ? tolower(t[j]) : t[j]; j++; if (a == b && a == '\0') return 0; } } while (a == b && i < endpos && j < endpos); return a - b; } int numcmp(char *s1, char *s2) { double v1, v2; char str[MAXSTR]; substr(s1, str, MAXSTR); v1 = atof(str); substr(s2, str, MAXSTR); v2 = atof(str); if (v1 < v2) return -1; else if (v1 > v2) return 1; else return 0; } void substr(char *s, char *str, int maxstr) { int i, j, len; extern int pos1, pos2; len = strlen(s); if (pos2 > 0 && len > pos2) len = pos2; else if (pos2 > 0 && len > pos2) error("substr: string too short"); for (j = 0, i = pos1; i < len; i++, j++) str[j] = s[i]; str[j] = '\0'; } int getline (char s[], int lim) { int c, i; i = 0; while (--lim > 0 && (c=getchar()) != EOF && c != '\n') s[i++] = c; if (c == '\n') s[i++] = c; s[i] = '\0'; return i; } void error(char *s) { printf("%s\n", s); exit(1); }

  • C言語

    文字列を逆順にするプログラムを考えているのですが分かりません。(例)qwerならrewqです。入力終了は、EOFです。考えたのですが、分かりません。(コンパイルエラーです。)教えてください。宜しくお願いします。#include <stdio.h> unsigned str_length(const char str[]) { unsigned len=0; while (str[len]) len++; return (len); } void put_rstring(const char str[]) { unsigned i = str_length(str): while (i-- >0) putchar(str[i]); } int main(void) { char str[30]; int ch; printf("文字列を入力\n"); /* ----この文字列を入力したあとに、Ctrl+Zを押すと、逆から表示               で反対から、文字列が表示----*/ while (1) { ch=getchar(); if (ch==EOF) break; } printf("逆から表示"); put_rstring(str); puts("です。"); return(0); }

  • プログラミング(配列と関数の引数)

    a : ABCDE a : ABCDEFGH Len : 8 a : FGHIJ a : FGH a : FGH, c : FGH 上記のように表示されるプログラムを作りたいのですが、なかなかできません。下記のようなプログラムを作ったのですがどこが間違っているのかよくわかりません。分かる方、指摘をお願いします。 #include <stdio.h> void my_strcpy(char s[], char t[]); int my_strlen(char s[]); void my_strcat(char s[], char t[]); int main(){ char a[10]; char b[10] = "ABCDE"; char c[] = "FGH"; int len; my_strcpy(a, b); printf("a : %s\n", a); my_strcat(a, c); printf("a : %s\n", a); len = my_strlen(a); printf("Len : %d\n", len); my_strcpy(a, "FGHIJ"); printf("a : %s\n", a); a[3] = '\0'; printf("a : %s\n", a); if(strcmp(a, c) == 0){ printf("a : %s, c : %s\n", a, c); } int i, s, t; my_strcpy(a, b + 2); printf("a : %s\n", a); void my_strcpy(char s[], char t[]){ for (i = 0; t[i] != '\0'; i++){ s[i] = t[i]; } s[i] = '\0'; } int my_strlen(char s[]){ int i; for (i = 0; s[i] != '\0'; i++); return i; } void my_strcat(char s[], char t[]){ int i, j; for (i = 0; s[i] != '\0'; i++); for (j = 0; t[j] != '\0'; i++, j++){ s[i] = t[j]; } s[i] = '\0'; } }

  • C言語の課題なのですが、助けてください

    C言語のプログラミングの課題で、「以下のプログラムをキーワードを引数として入力できるように変更する(argvを利用する)」という問題なのですが、プログラミングが苦手な私にはさっぱりわからず、大変困っています。設問のプログラミングがわかる方がいらっしゃいましたら、教えていただけると大変助かります。よろしくお願いします。 #include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX_LEN 256 int main(int argc, char *argv[]) { FILE *rfp; FILE *wfp; int i, score; double evalue; char id[MAX_LEN], name[MAX_LEN], fname[MAX_LEN]; char keyword[] = "glu"; for(i = 0; i < 100; i++){ sprintf(fname,"files/%d.txt",i); if((rfp = fopen(fname, "r")) == NULL) { printf("入力ファイルが存在しません。\n"); return (EXIT_FAILURE); } while (fscanf(rfp,"%s\t%s\t%d\t%f", id, name, &score, &evalue) != EOF){ if (strstr(name,keyword) != NULL){ printf("%s\n",id); } } fclose(rfp); } return (EXIT_SUCCESS); }

  • かぶった文字を消すプログラム

    文字列s2中の任意の文字に等しい文字をs1から除外するプログラムを以下の様に作りましたが、ビルトと入力は出来るものの、出力が出ません。何が間違っているのでしょう? #include <stdio.h> main() { int i,j,c; char s[100],t[100]; for( i = 0; (c = getchar()) != '\n'; i++){ s[i] = c; } for( i = 0; ((c = getchar()) != '\n') && (c != EOF); i++){ t[i] = c; } for( i = 0; s[i] != '\0'; i++){ for( j=0; t[j] != '\0'; j++){ if( s[i] == t[j] ){ s[i] = ' '; } } } for( i = 0; s[i] != '\0'; ++i ){ printf("%s", s[i]); } }

  • C言語 プログラミング 文字列

    C言語のプログラミングについての質問です。 文字列を入力して、それを逆順に表示するというプログラムを作っているのですが、 どうしても上手くいきません。 どこか間違えているのかわかりません。 わかる方いらっしゃいましたらご回答お願いします。 #include <stdio.h> int main(void) { char data[100]; int i, leng; char c; leng = 0; c =getchar(); while((c != '\n') && (c != EOF)) { data[leng] = c; leng = leng + 1; c = getchar(); } printf("%c", data[c]); return 0; }

  • C言語のことについて教えてください

    C言語のことで教えてください。お願いします #include <stdio.h> #include <time.h> #include <stdlib.h> #include <string.h> #include <windows.h> int main(int argc, char* argv[]) { char *data[] = {"おひつじ","おうし","ふたご","かに","しし","おとめ","てんびん", "さそり","いて","やぎ","みずがめ","うお"}; int data_len = 12; //データの数 char input[10]; //プレイヤーの入力値 int i,p,start; int win = 1; int mawari = 1; //内回りの場合は1 int p_turn = 0; //プレイヤーのターン if ((argc > 1) && (strcmp(argv[1], "-soto") == 0)) { mawari = 0; } srand(time(NULL)); start = rand()%data_len; printf("古今東西山手線ゲ~ム!\n"); printf("お題:星座の名前\n"); for(p = start,i = 1; i<= data_len; i++,p_turn = !p_turn ) { sleep(500); if(p_turn == 0) {printf("コンピューター");} else if (p_turn == 1) {printf("プレイヤー");} sleep(500); printf("ちゃん! >"); if(p_turn == 0) { printf("%s\n",*(data+p)); } else { scanf("%s", input); while (getchar() != '\n') { } if(strcmp(*(data+p),input) != 0) { win = 0; break; } } if(mawari == 1) { p++; } else {p--;} if((mawari ==1) && (p == data_len)) { p = 0;} if((mawari ==0) && (p == -1)) {p = data_len-1;} } if(win == 1) {printf("あなたの勝ち");} else {printf("あなたの負け");} return 0; } なんですが、どうしても } if(mawari == 1) { p++; } else {p--;} if((mawari ==1) && (p == data_len)) { p = 0;} if((mawari ==0) && (p == -1)) {p = data_len-1;} } 変数Pに今は乱数1-12がはいっているのに、なぜこの処理を行うかがわかりません。どうしてなんですか?教えてください。

  • c言語の文字列の逆順のプログラムがわかりません

    文字列を逆順して出力するプログラミングがわかりません。 #include <stdio.h> #include <string.h> void reverse(char *moji, char *gyaku); int main(void) { char x[30]; char y[30]; puts("文字を入力してください。\n"); scanf("%s", x); reverse(x, y); printf("逆順すると%sです。\n", y); return (0); } void reverse(char *moji, char *gyaku) { int i, len; len = strlen(moji); gyaku = moji + len - 1; for(i = 0; i < len; i ++){ putchar((int)*gyaku); gyaku--; } } 理想とする実行結果は 文字を入力してください。 abcdefg 逆順するとgfedcbaです。 なんですが、 上記のソースを実行すると 文字を入力してください。 abcdefg gfedcba逆順すると(謎の漢字)です。 となります。 どこがおかしいんでしょうか? よろしくおねがいします。

  • プログラミング言語Cの演習の質問

    単語数がnのものがいくつあるかを表示するプログラミングを作ったのですが上手くいけません。何故でしょうか、教えていただきたいです。 #include <stdio.h> main() { int c,i,j, len[10]; i=j=0; for (i=0; i<10; ++i){ len[i]=0; } while((c=getchar()) != EOF){ if(c != ' '){ ++i; } else { ++len[i]; i = 0; } } for (i=0; i<10; ++i){ printf("%d",len[i]); } }

専門家に質問してみよう