テキストファイル処理について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
tomoya

テキストファイル処理について

#1

投稿記事 by tomoya » 13年前

現在 テキストファイル処理について悩んでおります。
C言語初心者です。
フォルダにはいくつものテキストファイルがあります。(500くらい)
そのテキストファイルを一括処理したいです。

処理の内容は
まず一行目のタイトルを削除し、いくつもの数字を一行表示にしたいです。
またその際に出力ファイル名も指定 (0001 0002 0003 ....) したいです。
C言語でこのようなプログラミングは可能でしょうか?

テキストの中身は
________________________________
Test
1110.02034 4444.33454 23434.2292 29.49349
12.394323443 94.545432 94.43434 9123432
243490 203942 49204
33322003 32049324 3030 230209
_________________________________

出力したい結果は
_________________________________
1110.02034 4444.33454 23434.2292 29.49349 12.394323443 94.545432 94.43434 9123432 ......
________________________________

box
記事: 2002
登録日時: 15年前

Re: テキストファイル処理について

#2

投稿記事 by box » 13年前

tomoya さんが書きました: まず一行目のタイトルを削除し、いくつもの数字を一行表示にしたいです。
またその際に出力ファイル名も指定 (0001 0002 0003 ....) したいです。
C言語でこのようなプログラミングは可能でしょうか?
そりゃまあ何でもできるといえばできますが、
「いくつもの数字」→いくつなんですか?固定ですか?可変ですか?
「出力ファイル名を指定」→どこからどこまでをどのファイルに出力するか、どうやって判断するんですか?
というような、仕様の不明確な部分を明確にしていただく必要があるかもしれません。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

non
記事: 1097
登録日時: 15年前

Re: テキストファイル処理について

#3

投稿記事 by non » 13年前

OSは何ですか?
non

ゆうたろう

Re: テキストファイル処理について

#4

投稿記事 by ゆうたろう » 13年前

試していませんがこんな感じでできます↓

FILE *fp = fopen(nextopen, "r");
if (fp == NULL) {
printf("file open error!!\n");
exit(EXIT_FAILURE);
}

//1行読みとばす
while(getc(fp)!='\n');

while ( fgets(dainyuu, 256, fp ) !=NULL)
{
sscanf(dainyuu,"%f %f %f %f", murabito[m].message , murabito[m].gazou , &murabito[m].x , &murabito[m].y );
m++;
}

tomoya

Re: テキストファイル処理について

#5

投稿記事 by tomoya » 13年前

いくつもの回答ありがとうございます。

「いくつもの数字」→可変です。
テキストファイルの中身の数字は固定ではありません。

「出力ファイル名を指定」 test1 →00001 変換
元のテキストファイル名は test1 だとすると
出力ファイル名を 00001 に変換したいです。

それらの作業をフォルダ内にあるすべてのテキストファイルに処理がしたいです。

Microsoft Visual Studio2010を使用しています。

non
記事: 1097
登録日時: 15年前

Re: テキストファイル処理について

#6

投稿記事 by non » 13年前

tomoya さんが書きました:フォルダにはいくつものテキストファイルがあります。(500くらい)
ファイル名が一連番号のようについていて、既知なのか、それともフォルダに入っているファイル名は
バラバラでフォルダに入っているファイルをすべて処理したいのかによります。
前者なら良いですが、後者なら、findfirstfileなどを使って、ファイル名を取得する必要があります。
non

かずま

Re: テキストファイル処理について

#7

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

各行が何をしているのかを調べて、理解してください。
分からなければ、どの部分が分からないのか質問してください。

コード:

#include <stdio.h>
#include <string.h>
#include <windows.h>

int proc(const char *infile)
{
    FILE *fpi, *fpo;  char outfile[12];  int c;

    if (sscanf(infile, "%*[^0-9]%d", &c) != 1)
        return fprintf(stderr, "number not found in %s\n", infile), 1;
    sprintf(outfile, "%05d", c);
    fpi = fopen(infile, "r");
    if (!fpi) return fprintf(stderr, "can't open %s\n", infile), 1;
    fpo = fopen(outfile, "w");
    if (!fpo) return fprintf(stderr, "can't create %s\n", outfile), 1;
    while ((c = fgetc(fpi)) != EOF && c != '\n') ;
    while ((c = fgetc(fpi)) != EOF) fputc(c == '\n' ? ' ' : c, fpo);
    fclose(fpi);
    fclose(fpo);
    return 0;
}

int main(int argc, char *argv[])
{
    WIN32_FIND_DATA fd;  HANDLE h;

    if (argc != 2)
        return fprintf(stderr, "usage: %s diretoryname\n", argv[0]), 1;
    if (!SetCurrentDirectory(argv[1]))
        return fprintf(stderr, "can't set directory: %s\n", argv[1]), 1;
    h = FindFirstFile("*", &fd);
    if (h == INVALID_HANDLE_VALUE)
        return fprintf(stderr, "can't get file names\n"), 1;
    do {
        if (strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, ".."))
            proc(fd.cFileName);
    } while (FindNextFile(h, &fd));
    FindClose(h);
    return 0;
}

かずま

Re: テキストファイル処理について

#8

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

かずま さんが書きました:

コード:

    if (!fpo) return fprintf(stderr, "can't create %s\n", outfile), 1;
訂正です。

コード:

    if (!fpo) {
        fclose(fpi);
        return fprintf(stderr, "can't create %s\n", outfile), 1;
    }
あと気になるのが、test1, test2, ..., test500 を変換して
00001, 00002, ..., 00500 を同じディレクトリに書いていることです。
FindFirstFile がその実行時点でのディレクトリ情報をすべて読み込んで、
あとは FindNextFile がその情報を使うのならいいんですが、
FindFirstFile で一部の情報しか読み込ます、FindNextFile で追加情報を
読み込むのなら、新たに書き出した 00001, 00002, ... なども入力ファイルの
対象になってしまうかもしれません。sscanf の書式が 数字以外が 1文字以上で
そのあとに数字が来るものなので、実際には入力ファイルとなりませんが、
エラーメッセージが出てしまいます。
500個のファイルで試してみたところ、幸いそういう現象は出ませんでした。
でも、念のために、出力は別のディレクトリにしたほうがよいかもしれません。

ところで、最初の質問者はフォルダという言葉を使っていますが、
それがディレクトリと同じだということを理解されていますか?
フォルダというのは、Windows のような GUI が一般的になってから
ディレクトリをアイコンで表示したときにその名称を使い始めたようです。
OS の API は Windows なら SetCurrentDiretory、Linux などは chdir (change
diretory) となっています。

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: テキストファイル処理について

#9

投稿記事 by beatle » 13年前

C言語のソースコードだと全体的な流れを追いづらいだろうと思ったので、python版を作ってみました。
まったく読める気がしない、というのであれば無理に読んで理解する必要はありません。
ただ基本的な処理の流れはC言語で書く場合と大差ないので、理解の助けになるかもしれないと思って書きました。

コード:

import os
import re

def Conv(in_file_name, out_file_name):
	f = open(in_file_name)
	fo = open(out_file_name, 'w')
	line = f.readline()
	line = f.readline()
	while line:
		fo.write(line[:-1])
		line = f.readline()
		if line:
			fo.write(' ')

files = os.listdir('.')
file_name_regex = re.compile(r'\D+(\d+)')

for file in files:
	m = file_name_regex.match(file)
	if m:
		num = int(m.group(1))
		Conv(file, '%04d' % (num,))
re.compile(r'\D+(\d+)')
という部分が少しややこしいかもしれないので解説しておきます。
\D+(\d+) は正規表現といいます。
「\D」が「数字ではない文字」を表し、「\d」が「数字(0〜9)」を表します。「+」が「1文字以上」を表します。
\D+(\d+) 全体で「数字ではない文字が1文字以上続いた後に、数字が1文字以上続く文字列」を表します。
例えば test1, test2, foo_bar0123 のようなものが一致し、 test1a, foo_bar0123_hoge のようなものは一致しません。

\d+を括弧で囲んでいるのは、後に m.group(1) でその部分を取り出すためです。
括弧で囲むと後で取り出せるわけです。
今回の場合、m.group(1)では
test1 であれば 1
foo_bar0123 であれば 0123
を取り出すことができます。

Ryo

Re: テキストファイル処理について

#10

投稿記事 by Ryo » 13年前

課題の丸投げに見えるんだが…

閉鎖

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