dポイントプレゼントキャンペーン実施中!

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行しか表示しません。
おそらくは配列の配列を使って保存しておくのだとは考えたのですが
使い方がわかりません。教えて下さい。

A 回答 (9件)

char line[MAXLINE][100];


char longest[MAXLINE][100];

まずここですが、すでに指摘されているようにMAXLINEと100が逆です。
で、せっかくMAXLINEをdefineしたんですから、100のほうもしましょう。

#define ALLLINES 100
・・・
char longest[ALLLINES][MAXLINE];

また、lineのほうは「読み込んだ一行」を保持するためのものですから、2次元配列にする意味がありません。

char line[MAXLINE];

次に getline() ですが、Visual C++なら標準関数にgets_s()というのがあります。ただ、これは読み込んだサイズを返してくれないので、別途strlen()が必要です。
gets_s()がなければ、大本のソースにあったgetline()でも問題はないでしょう。

int count = 0;
while(gets_s(line, MAXLINE) != NULL){
int len = strlen(line);

2次元配列は、最初の添え字だけを指定すると、1次元配列の先頭アドレスを返します。
if(len > 80)
strcpy_s(longest[count++], MAXLINE, line);
上記は、&longest[count++][0]と同じです。さらに言うと、
char longest[MAXLINE];
と定義した場合の strcpy_s(longest, MAXLINE, line); と、まったく同じ動作です。
また、count++としているので、80文字以上の行が次々と入ってきます。
ということは、countがALLLINESを超えたらメモリ破壊してしまうので、そこでwhileループを抜けないといけません。
if ( ++count >= MAXLINES ) break;

さて、ループを抜けた後は、longestに入れた文字列を一つずつ表示する必要があります。
ここは自分で考えてみてください。
    • good
    • 0

とりあえず2次元配列についてだけ。



char a[M][N];
と宣言した場合、aは要素数Mの「要素数Nのchar配列」の配列です。
要素数Nのchar配列というのは最大長Nの文字列とほぼ同義ですから、aは要素数Mの文字列(最大長N)の配列、ということになります。

そして、a[0][0]は最初の文字列の先頭文字、a[0][1]は最初の文字列の2文字目、a[1][0]は2番目の文字列の先頭文字……という風に割り当てられます。

また、アクセスできる範囲はa[M-1][N-1]までです。これは宣言時のMとNが要素数であるのに対し、添え字は0から始まるためM-1及びN-1でM個、N個になっているためです。

この辺りを理解したうえで、コードを見直してください。

#自分で書くならfstat(),fread(),strtok(),strlen()で済ませるけど元コードがカケラも残らないなぁ……
    • good
    • 0

>と単にかえてみただけですが。



すごく、遠ざかりました。
getline() と copy() の仕様を補足にどうぞ。
    • good
    • 0

>単にchar longest[MAXLINE][100]と宣言を変更していくと


>どこかクラッシュしてるようで問題が発生しましたってでて

そのソースを補足にどうぞ。
というか、多分 char longest[100][MAXLINE] の間違いですが。

この回答への補足

int getline(char line[][100], int maxline);
void copy(char s1[][100], char s2[])[100];

int main(int argc, char* argv[])
{
int len;
int max;
char line[MAXLINE][100];
char longest[MAXLINE][100];

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[][100], int lim)
{
int c, i;
for(i = 0; i < lim -1 && (c = getchar()) != EOF && c != '\n'; ++i){
s[i][100] = c;
}

if(c == '\n'){
s[i][100] = c;
++i;
}
s[i][100] = '\0';
return i;
}

void copy(char s1[][100], char s2[][100])
{
int i;
i=0;
while((s1[i][100] = s2[i][100]) != '\0'){
++i;
}
}
と単にかえてみただけですが。

補足日時:2009/05/11 12:01
    • good
    • 0

最も簡単なのは、while文中で条件に一致した時、配列longestにコピーなどせず、ダイレクトに表示させてしまう。


配列longestも、取って付けたような変数maxも不要。
また、条件に一致した文字列数の個数制限も回避できる。
    • good
    • 0

配列の配列を使っても、結局はその配列の配列のサイズ分しか表示できません。


動的に確保すれば、もっと柔軟にできますが、一行の長さが2GBとかあったらどうしますか?

どのような処理にするかは仕様次第ですが、特に必要がなければ、80文字表示して、続きはその直後からということになるでしょう。
もっとも、これだけのプログラムであれば、typeなりcatなりで十分なので、なんのためのプログラムなのかによりますけどね。
    • good
    • 0

えと.... 「80字より長い行を全て印字するというプログラムを作ろうと思います。

」って言ってるんだけど, プログラムは「最も長い行を表示する」ように見えます. そして, この 2つは明らかに異なる動作です. 本当にやりたいのはどちらでしょうか?
もちろん「80文字より長い行をすべて表示する」だけでいいなら「そのような行をただちに出力する」だけでよく, それなら配列は 1つで OK.

この回答への補足

元はもっとも長い行を表示するプログラムでしたが
条件をかえて文字列の長さlenが80以上なら印字という風に
しました。

補足日時:2009/05/11 11:28
    • good
    • 0

>おそらくは配列の配列を使って保存しておくのだとは考えたのですが


>使い方がわかりません。

「配列の配列」の存在は知っているんですよね。具体的に何がわからないかを補足にどうぞ。

あと、プログラムの内容についてちょっとだけ。
記載されている getline(), copy() の機能はいずれも標準 C ライブラリに用意されているので、それを使いましょう。

この回答への補足

メモリ関係を考慮した格納の仕方でしょうか。
単にchar longest[MAXLINE][100]と宣言を変更していくと
どこかクラッシュしてるようで問題が発生しましたってでて
使い方がさっぱりなんですよ

補足日時:2009/05/11 11:37
    • good
    • 0

先生にご相談ください。

この回答への補足

いやここQ&A掲示板なんですが・・
質問してはいけないってことはないと思いますが

補足日時:2009/05/11 11:30
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!