末尾行表示について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
あや
記事: 28
登録日時: 4年前

末尾行表示について

#1

投稿記事 by あや » 4年前

入力テクストの未尾N行を表示する問題です.
メイン関数の3-2と4のline[N]のところにエラーが出ます.
正しいコードにするにはどうしたらいいのか教えてください.
以下が現在のコードです.他にもおかしいところがあったら教えてください.
よろしくお願いします.

コード:

#include <string>
#include <fstream>
#include <iostream>
using namespace std;

// 定数定義
#define N 3

// プロトタイプ宣言
void addLine(string aline, string line[N], int num);  // 読み込んだ1行を最近読み込んだN行に追加する。
void showLine(string line[N], int num);  // 最近読み込んだN行を表示する。

/********************************
メイン関数
********************************/
void main() {

	ifstream file;  // 入力ファイル
	string aline;  // 読み込んだ1行の文字列		
	string line[N];  // 最近読み込んだN行の文字列
	int num;  // 読み込んだ行数

	// 1. 入力ファイルを開く。
	file.open("plain.txt");

	// 2. 読み込んだ行数を 0 に初期化する。
	num = 0;

	// 3. ファイルの末尾に到達するまで以下の処理を繰り返す。
	while (!file.eof()) {

		// 3 - 1. 入力ファイルから1行読み込む。
		getline(file, aline);

		// 3 - 2. 読み込んだ1行を最近読み込んだN行に追加する。
		addLine(aline,line[N],num);

		// 3 - 3. 読み込んだ行数を1増やす。
		num++;

		// 4. 最近読み込んだN行を表示する。
		showLine(line[N],num);

		// 5. 入力ファイルを閉じる。
		file.close();
	}
}

    /********************************************
    読み込んだ1行を最近読み込んだN行に追加する。
    ********************************************/
	void addLine(string aline, string line[N], int num) {
	
		// 1. 読み込んだ行数がNより小さければ line[num] に aline を代入する。
		if (num < N) {
			line[num] = aline;
		}

		// 2. そうでなければ以下の処理を行う。
		else {

			// 2 - 1. 変数 i を0~N - 2まで変えながら以下の処理を繰り返す。
			for (int i = 0; i > N - 2; i++) {

				// 2 - 1 - 1. line[i + 1] の値を一つ前の line[i] にずらす。
				line[i + 1] = line[i];

				// 2 - 2. line[N - 1] に aline を代入する。
				line[N - 1] = aline;
			}
		}
	}

	/********************************************
	最近読み込んだN行を表示する。
	********************************************/
	void showLine(string line[N], int num) {

		// 1. 変数 i を0~N - 1まで変えながら以下の処理を繰り返す。
		for (int i = 0; i > N - 1; i++) {

			// 1 - 1. i が読み込んだ行数より小さければ line[i] を表示する。
			if (i < num) {
				cout << line[i];
			}
		}
	}

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 末尾行表示について

#2

投稿記事 by みけCAT » 4年前

このコードには、
  • 16行目:C++の規格ではグローバルなmain関数の戻り値の型はintでなければいけないのに、そうなっていない
  • 30行目・33行目:読み込めたかを判定する前に次の処理に行ってしまうため、1回多くループが回ってしまうことにつながる
  • 36行目・42行目:配列の範囲外の要素を読み込んでいる上、string型を要素とする配列(の先頭要素へのポインタ)を渡すべき場所にstring型のデータを渡している
  • 42行目:1行処理するたびに出力しているので、余計な途中経過が出力される
  • 45行目:最初の1行を読み込んだだけでファイルを閉じてしまうため、最初の1行しか読み込めない
  • 49~87行目:インデントが不自然に1段多い
  • 63行目・80行目:「iをhogeまで変える」ではなく「iがhogeより大きい間繰り返す」という意味のi > hogeが使われている
  • 66行目:代入元と代入先が逆である
  • 69行目:最後の要素を前に移す前に破壊してしまう
  • 84行目:改行が入らず、全ての対象行のデータがつながって出力される
という問題があります。
これらの問題を修正したものが以下になります。

コード:

#include <string>
#include <fstream>
#include <iostream>
using namespace std;

// 定数定義
#define N 3

// プロトタイプ宣言
void addLine(string aline, string line[N], int num);  // 読み込んだ1行を最近読み込んだN行に追加する。
void showLine(string line[N], int num);  // 最近読み込んだN行を表示する。

/********************************
メイン関数
********************************/
/* main関数の戻り値の型はintにする */
int main() {

	ifstream file;  // 入力ファイル
	string aline;  // 読み込んだ1行の文字列		
	string line[N];  // 最近読み込んだN行の文字列
	int num;  // 読み込んだ行数

	// 1. 入力ファイルを開く。
	file.open("plain.txt");

	// 2. 読み込んだ行数を 0 に初期化する。
	num = 0;

	// 3. ファイルの末尾に到達するまで以下の処理を繰り返す。
	/* ファイルから読み込めている間のみ処理を行うようにする */
	// 3 - 1. 入力ファイルから1行読み込む。
	while (getline(file, aline)) {

		// 3 - 2. 読み込んだ1行を最近読み込んだN行に追加する。
		/* 配列(の先頭要素へのポインタ)を渡すようにする */
		addLine(aline,line,num);

		// 3 - 3. 読み込んだ行数を1増やす。
		num++;

	}

	/* 表示とファイルを閉じるのを、最後まで処理してからにする */
	// 4. 最近読み込んだN行を表示する。
	/* 配列(の先頭要素へのポインタ)を渡すようにする */
	showLine(line,num);

	// 5. 入力ファイルを閉じる。
	file.close();
}

/* インデントを普通にする */
/********************************************
読み込んだ1行を最近読み込んだN行に追加する。
********************************************/
void addLine(string aline, string line[N], int num) {

	// 1. 読み込んだ行数がNより小さければ line[num] に aline を代入する。
	if (num < N) {
		line[num] = aline;
	}

	// 2. そうでなければ以下の処理を行う。
	else {

		// 2 - 1. 変数 i を0~N - 2まで変えながら以下の処理を繰り返す。
		/* 適切なループの継続条件を使う */
		for (int i = 0; i <= N - 2; i++) {

			// 2 - 1 - 1. line[i + 1] の値を一つ前の line[i] にずらす。
			/* 代入元と代入先を適切にする */
			line[i] = line[i + 1];

		}
		/* 新しいデータを入れるのを、全ての要素を移動した後にする */
		// 2 - 2. line[N - 1] に aline を代入する。
		line[N - 1] = aline;
	}
}

/********************************************
最近読み込んだN行を表示する。
********************************************/
void showLine(string line[N], int num) {

	// 1. 変数 i を0~N - 1まで変えながら以下の処理を繰り返す。
	/* 適切なループの継続条件を使う */
	for (int i = 0; i <= N - 1; i++) {

		// 1 - 1. i が読み込んだ行数より小さければ line[i] を表示する。
		if (i < num) {
			/* 改行も出力するようにする */
			cout << line[i] << '\n';
		}
	}
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: 末尾行表示について

#3

投稿記事 by かずま » 4年前

あや さんが書きました:
4年前
以下が現在のコードです.他にもおかしいところがあったら教えてください.
おかしいところがたくさんあるので、書き直してみました。

コード:

#include <string>    // getline
#include <fstream>   // ifstream
#include <iostream>  // cout
using namespace std;

#define N 3

void addLine(const string &aline, string *line, int num);
void showLine(const string *line, int num);

int main()
{
	string aline, line[N];
	int num = 0;
	ifstream file("plain.txt");
	if (!file) { cerr << "can't open plain.txt\n"; return 1; }

	while (getline(file, aline))
		addLine(aline, line, num++);
	showLine(line, num);
}

void addLine(const string &aline, string *line, int num)
{
	line[num % N] = aline;
}

void showLine(const string *line, int num)
{
	for (int i = (num < N) ? 0 : num - N; i < num; i++)
		cout << line[i % N] << '\n';
}

返信

“C言語何でも質問掲示板” へ戻る