C では、複数の行を含む入力を受け入れてから、出力の行を逆の順序で (各行の単語の順序を変更せずに) 受け入れるにはどうすればよいでしょうか。
例えば:
入力: 1 行目 2行目 3号線 4号線 出力: 4 行目 3号線 2行目 ライン1
解決策は簡単です。lines
それが length の行の配列 (末尾の改行なし) であると仮定するとsize
、次のループを実行する必要があります。
for(i = size - 1; i >= 0; --i)
puts(lines[i])
つまり、行を逆の順序で出力するだけです。最後の行から始まり、最初の行で終わります。
「行を入力して保存する方法」という質問について:いくつかのオプションがあります。入力はgetline
(POSIX 関数) またはfgets
関数 (必要に応じて末尾の改行を手動で削除できます) を使用して実行できます。使用しないでくださいgets
- それは悪です。行を入力するには、ループを使用する必要があります。realloc
行は、タスクに基づいて、静的または動的に拡張する ( 経由の) 配列のいずれかに格納できます。または、それほどスマートではないトリックを実行することもできます: 行を格納するためにスタックを利用する再帰関数を記述します (疑似コード):
function reverseLines():
{
string line;
input(line);
if not end-of-input():
{
reverseLines();
output(line);
}
}
ただし、入力が十分に大きい場合は、スタック オーバーフローエラーが発生します。
行の最大長を設定できる場合は、標準の Cfgets()
関数を使用して行を読み取ることができます。最近の POSIX 準拠のオペレーティング システムを使用している場合、または GNU glibc を使用している場合は、行にメモリを割り当てる getline() を使用できるため、任意の行の長さを読み取ることができます。こちらの SO でこの回答を参照してください。
行ごとに、char*
ポインターが取得されます。
サポートする最大行数を設定できる場合はchar *lines[MY_MAX_LINE_COUNT]
、ポインタを格納するために使用でき、配列から逆の順序で単純に出力できます。先頭に追加できる非常に単純な連結リストを実装することをお勧めします (これはおそらく最も単純な連結リスト コードであり、基本的にはpushだけでpopは不要なスタックです ...)。読まれました。
char*
単純なケースでは、リンクされたリスト構造体をすべての行に割り当てることを避けるために、:を使用して拡張される配列に行ポインターを格納するのが最善かもしれませんrealloc()
。
最初に必要な変数:
int arraysize = 16; /* any size will do, 16 is nice round number */
char *lines[16] = malloc(sizeof(char*) * arraysize);
int linecount = 0;
次にループして入力を取得します。
while(/* test for eof or whatever */) {
char *line = /* code to get the line */;
if (linecount == arraysize) {
arraysize *= 2;
lines = realloc(lines, sizeof(char*) * arraysize);
}
lines[linecount] = line; /* old lines are at indexes 0..(linecount-1) */
++linecount;
そしてそのための印刷ループ:
for(int index = linecount-1 ; index >= 0 ; --index) {
puts(lines[index]); /* if line has newline stripped, else printf("%s", lines[index]);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void reverseLines(void);
int main (void) {
reverseLines();
return 0;
}
void reverseLines(void) {
char *line;
size_t len = 0;
getline(&line, &len, stdin);
if (strcmp(line, "") != 0) // NOT end of input
{
reverseLines();
printf ("%s", line);
}
free (line);
}
/* References:
*
* http://www.gnu.org/software/libc/manual/html_node/Line-Input.html
* http://souptonuts.sourceforge.net/code/getline.c.html
*/
疑似コードの@namelessとgetline関数の@hydeに感謝します(私は知りませんでした)。