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件)
- 最新から表示
- 回答順に表示
No.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に入れた文字列を一つずつ表示する必要があります。
ここは自分で考えてみてください。
No.8
- 回答日時:
とりあえず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()で済ませるけど元コードがカケラも残らないなぁ……
No.6
- 回答日時:
>単に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;
}
}
と単にかえてみただけですが。
No.5
- 回答日時:
最も簡単なのは、while文中で条件に一致した時、配列longestにコピーなどせず、ダイレクトに表示させてしまう。
配列longestも、取って付けたような変数maxも不要。
また、条件に一致した文字列数の個数制限も回避できる。
No.4
- 回答日時:
配列の配列を使っても、結局はその配列の配列のサイズ分しか表示できません。
動的に確保すれば、もっと柔軟にできますが、一行の長さが2GBとかあったらどうしますか?
どのような処理にするかは仕様次第ですが、特に必要がなければ、80文字表示して、続きはその直後からということになるでしょう。
もっとも、これだけのプログラムであれば、typeなりcatなりで十分なので、なんのためのプログラムなのかによりますけどね。
No.3
- 回答日時:
えと.... 「80字より長い行を全て印字するというプログラムを作ろうと思います。
」って言ってるんだけど, プログラムは「最も長い行を表示する」ように見えます. そして, この 2つは明らかに異なる動作です. 本当にやりたいのはどちらでしょうか?もちろん「80文字より長い行をすべて表示する」だけでいいなら「そのような行をただちに出力する」だけでよく, それなら配列は 1つで OK.
No.2
- 回答日時:
>おそらくは配列の配列を使って保存しておくのだとは考えたのですが
>使い方がわかりません。
「配列の配列」の存在は知っているんですよね。具体的に何がわからないかを補足にどうぞ。
あと、プログラムの内容についてちょっとだけ。
記載されている getline(), copy() の機能はいずれも標準 C ライブラリに用意されているので、それを使いましょう。
この回答への補足
メモリ関係を考慮した格納の仕方でしょうか。
単にchar longest[MAXLINE][100]と宣言を変更していくと
どこかクラッシュしてるようで問題が発生しましたってでて
使い方がさっぱりなんですよ
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# C言語で再起関数とポインタを用いて文字列反転をする方法がわかりません。 4 2023/04/29 20:32
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列を使わずに、変数名を動的...
-
配列で格納したものをmsgboxで...
-
C# Listを使わずに2次元配列の...
-
先頭アドレスとは何ですか?
-
配列の参照渡しで型が一致しま...
-
C言語で特定列だけを抽出して配...
-
C言語の配列番号が"0"から始ま...
-
C# 配列の変数宣言について。
-
プログラムが書けません。
-
VBで構造体の配列を関数に渡す...
-
【C言語】配列の中に配列を入れ...
-
テキストファイルから文字列を...
-
【速いブラインドタッチ】手を...
-
ポインタの配列のコンマについて
-
配列の中身を逆にするために。。。
-
unsigned char配列への入力の仕方
-
C言語の配列のサイズ
-
VBで動的なメモリの確保
-
c言語でのヒストグラム作成用の...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列を使わずに、変数名を動的...
-
先頭アドレスとは何ですか?
-
配列で格納したものをmsgboxで...
-
C# 配列の変数宣言について。
-
テキストファイルから文字列を...
-
unsigned char配列への入力の仕方
-
ExcelVBAで質問です。離れた二...
-
配列の参照渡しで型が一致しま...
-
パイソンの
-
C# Listを使わずに2次元配列の...
-
C言語で特定列だけを抽出して配...
-
複数の選択範囲の行番号を個別...
-
【C言語】配列の中に配列を入れ...
-
メモリの初期値
-
VBで構造体の配列を関数に渡す...
-
Excel、VBAのユーザーフォーム...
-
配列をEraseしてもメモリが開放...
-
2次元配列を戻り値とする関数?
-
【速いブラインドタッチ】手を...
おすすめ情報