「一気に最後まで読んだ」本、教えて下さい!

ご質問です。
構造体で、あらかじめメンバ数を固定したものではなく、
テキストファイルを読み込んだときにメンバ数を変えて読み込みたいのです。
(カンマできりたい)

aaa.txt
------------------------
あああ,いいい
------------------------
となっているときは、

tmp.nm[0]=あああ
tmp.nm[1]=いいい
となり、

kamoku.nm[0]
kamoku.nm[1]
をprintf。

aaa.txt
---------------------------
あああ,いいい,ううう,えええ
---------------------------
の場合は
tmp.nm[0]=あああ
tmp.nm[1]=いいい
tmp.nm[2]=ううう
tmp.nm[3]=えええ

kamoku.nm[0]
kamoku.nm[1]
kamoku.nm[2]
kamoku.nm[3]

をprintf。

下記は動きません。。
よろしくお願いいたします。
#include <stdio.h>

struct kamokumei {
char nm[10];
}kamoku;

int main(void)
{
int i,P,t;


FILE *fp;
struct kamokumei kamoku[20];
char buf[1024];
fp = fopen("aaa.txt", "r");

P=3;
t=0;


while( fgets(buf, sizeof(buf), fp) ){

struct kamokumei tmp;
sscanf(buf, "%s", tmp.nm[t]);

nm[t++] = tmp;
}
for(i = 0; i < P; i++) {
printf("%s\n",
kamoku.nm[i]);
}

return 0;
}

A 回答 (6件)

FILE *fp;


char buf[1024];
while( fgets(buf, sizeof(buf), fp) )
これだと
1行が1024文字以上だと当然うまく読み込めません。
まずその部分から改善する必要があります。

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define MAX_BUF 2
int main()
{
FILE *fp;
int len;
char buf[MAX_BUF];
int buflen;
fp = fopen("aaa.csv", "r");
char *pBuf2 = NULL;

while( fgets(buf, MAX_BUF , fp) ){
int buflen = strlen(buf);
if ( buf[buflen - 1] == '\n'){
buf[buflen - 1] = '\0';
pBuf2 = (char*)realloc( pBuf2 , buflen );
printf("%s\n",pBuf2);
if (pBuf2) free(pBuf2);
pBuf2 = NULL;
}else{
if ( pBuf2 == NULL ){
pBuf2 = (char*)malloc( buflen + 1 );
strcpy( pBuf2 , buf );
}else{
pBuf2 = (char*)realloc( pBuf2 , buflen + 1 );
strcat( pBuf2 , buf );
}

}
}
if (pBuf2) free(pBuf2);
}
    • good
    • 0

訂正



int i,j;
for( i = 1 ; i <= mycsv.cnt ; i++ ){
printf( "(mycsv.line + i)->cnt=%d\n" , (mycsv.line + i - 1)->cnt );
for( j = 1 ; j <= (mycsv.line + i - 1)->cnt ; j++ ){
printf( "%d行目%d列目は「%s」\n" ,i,j, ReadCsv( &mycsv , i-1 , j-1 ) );
}
}



ちなみにこのソース、最後が改行で終わっていなければ
最後の行が読まれませんでした。
printf( "2行目3列目は「%s」" , ReadCsv( &mycsv , 2 - 1 , 3 - 1 ) );
の上に
if (pBuf2) AddCsv( &mycsv , pBuf2 );
を追加すれば解消します。
    • good
    • 0
この回答へのお礼

沢山の回答ありがとうございました。

大変勉強になりました。
(が、結局可変長のところはうまくいかず締め切りがきてしまいました、、)

もう少し勉強していきたいと思います。

今後ともよろしくお願いいたします。

お礼日時:2005/02/15 01:31

>aaa.txtを読み込んだ時の


>最大行の数、最大列の数はどの変数にあたるのでしょうか?
最大行の数:mycsv->cnt
1行目の最大列の数:mycsv->line->cnt
2行目の最大列の数:(mycsv->line + 1)->cnt

int i,j;
for( i = 1 ; i <= mycsv->line->cnt ; i++ ){
for( j = 1 ; j <= (mycsv->line + i)->cnt ; j++ ){
printf( "%d行目%d列目は「%s」" ,i,j, ReadCsv( &mycsv , i-1 , j-1 ) );
}
}

この回答への補足

早速回答を頂きありがとうございます。

すみません、再々度質問なのですが、、

-> か ->* の左には構造体のポインタが必要
とerrorがでます。

ポインタについて本を読みながらやっているものの、
解決できません、、

よろしくお願いいたします。

http://oshiete1.goo.ne.jp/kotaeru.php3?q=1217707
でも受け付けています。

補足日時:2005/02/14 09:55
    • good
    • 0

最終的に何がしたいのかわからないのですが、元のソースをベースに1行を分割するものを書いてみます。


複数の行ならばkamokuを二次元配列にする必要があり、最大の列・行数が不定ならばsha-girlさんのように書く必要があります。

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

struct kamokumei { char name[32]; };

static char *split(char *buf, char delimiter)
{
char *next = strchr(buf, delimiter);
if (next == NULL)
return buf + strlen(buf);
*next = '\0';
return next + 1;
}

static int split_csvline(char *buf, struct kamokumei *dest, int max)
{
char *next, *item;
int i;
for(i = 0, item = next = buf; *next != '\0' && i < max; i++, item = next)
{
next = split(item, ',');
strcpy(dest[i].name, item);
}
return i;
}

int main(void)
{
int i, count, length;
FILE *fp;
struct kamokumei kamoku[20];
char buf[1024];
fp = fopen("aaa.txt", "r");
if (fgets(buf, sizeof buf, fp)) {
buf[sizeof buf - 1] = '\0';
length = strlen(buf);
if (buf[length - 1] == '\n')
buf[length - 1] = '\0';
count = split_csvline(buf, kamoku, sizeof kamoku / sizeof kamoku[0]);
for(i = 0; i < count; i++)
printf("%s\n", kamoku[i].name);
}
return 0;
}

ちなみにテキストファイルを処理して出力するだけならばperlをお勧めします。

open(FP, "<aaa.txt") or die;
while (<FP>) {
chomp;
@columns = split(/,/);
push(@csv, [@columns]);
}
printf('2行目3列目は「%s」' , $csv[2-1]->[3-1]);

この回答への補足

回答を頂いた皆様へ

ありがとうございます。

>二次元配列にする必要があり、最大の列・行数が不定ならば・・・

できれば二次元配列にしたいので、sha-girlさんから回答いただいたソースを元にしたいと思います。

printf( "2行目3列目は「%s」" , ReadCsv( &mycsv , 2 - 1 , 3 - 1 ) );
は、理解できたのですが、
その他の動きがまったくわからない状態です、、

aaa.txtを読み込んだ時の
最大行の数、最大列の数はどの変数にあたるのでしょうか?

たとえば、
最大行の数=x
最大列の数=y
i=1,j=1として、
i=1 to x
j=1 to y
とし、ループで全部表示させることが目的です。

printf( "%d行目%d列目は「%s」" , i,j,ReadCsv( &mycsv , i - 1 , j - 1 ) );

補足日時:2005/02/13 21:07
    • good
    • 0

とりあえず書いてみました。


aaa.csvから読み込み
char* ReadCsv( MYCSV* pCsv , int l , int r )
の関数で読み込みます。
printf( "2行目3番目は「%s」" , ReadCsv( &mycsv , 2 - 1 , 3 - 1 ) );
の部分で2行目3番目にある項目を表示しています。

#include <stdio.h>
#include <string.h>
#include <malloc.h>
typedef struct ___mycsvline{
int cnt;
char **str;
} MYCSVLINE;
typedef struct ___mycsv{
int cnt;
MYCSVLINE* line;
} MYCSV;
#define MAX_BUF 2
char* ReadCsv( MYCSV* pCsv , int l , int r )
{
MYCSVLINE* pLine;
if ( l >= pCsv->cnt ){
return "";
}
pLine = (pCsv->line + l );
if ( r >= pLine->cnt ){
return "";
}
return *(pLine->str + r);
}

int GetStrToken(char* str){
int cnt = 0;
while( *str != '\0' && *str != ',' ){
cnt++;
str++;
}
return cnt;
}

int GetConmaCnt(char* str){
int cnt = 0;
while( *str != '\0'){
if ( *str == ',' ) cnt++;
str++;
}
return cnt;
}

void AddLine( MYCSVLINE* pLine , char* str ){
int i;
int NextConma;
int ConmaCnt = GetConmaCnt(str);
pLine->cnt = ConmaCnt + 1;
pLine->str = (char**)malloc( sizeof(char*) * pLine->cnt );
for( i = 0 ; i < pLine->cnt ; i++ ){
NextConma = GetStrToken(str);
*(pLine->str + i) = (char*)malloc( NextConma + 1 );
strncpy( *(pLine->str + i) , str , NextConma );
*( *(pLine->str + i) + NextConma ) = '\0';
str += ( NextConma );
if ( *str == ',' ) str++;
}

}

void AddCsv( MYCSV* pCsv , char* str ){
pCsv->cnt++;
pCsv->line = (MYCSVLINE*)realloc( pCsv->line , sizeof( MYCSV ) * pCsv->cnt );
AddLine( (pCsv->line + (pCsv->cnt - 1) ) , str );
}

void AllFree( MYCSV* pCsv ){
int i,j;
MYCSVLINE* pLine;
for ( i = 0 ; i < pCsv->cnt ; i++ ){
pLine = (pCsv->line + i);
for( j = 0 ; j < pLine->cnt ; j++ ){
free( *(pLine->str + j) );
}
free(pLine->str);
}
free( pCsv->line );
}

int main()
{
FILE *fp;
char buf[MAX_BUF];
int buflen;
int ttlbuflen = 0;
fp = fopen("aaa.csv", "r");
char *pBuf2 = NULL;
MYCSV mycsv;
mycsv.cnt = 0;
mycsv.line = NULL;

while( fgets(buf, MAX_BUF , fp) ){
buflen = strlen(buf);
ttlbuflen += buflen;
if ( buf[buflen - 1] == '\n'){
buf[buflen - 1] = '\0';
if (pBuf2 == NULL){
pBuf2 = (char*)malloc( ttlbuflen + 1 );
strcpy( pBuf2 , buf );
}else{
pBuf2 = (char*)realloc( pBuf2 , ttlbuflen + 1 );
strcat( pBuf2 , buf );
}
AddCsv( &mycsv , pBuf2 );
if (pBuf2) free(pBuf2);
ttlbuflen = 0;
pBuf2 = NULL;
}else{
if ( pBuf2 == NULL ){
pBuf2 = (char*)malloc( ttlbuflen + 1 );
strcpy( pBuf2 , buf );
}else{
pBuf2 = (char*)realloc( pBuf2 , ttlbuflen + 1 );
strcat( pBuf2 , buf );
}
}
}
printf( "2行目3列目は「%s」" , ReadCsv( &mycsv , 2 - 1 , 3 - 1 ) );

AllFree( &mycsv );
if (pBuf2) free(pBuf2);
}
    • good
    • 0
この回答へのお礼

回答を頂いた皆様へ

ありがとうございます。

>二次元配列にする必要があり、最大の列・行数が不定ならば・・・

できれば二次元配列にしたいので、sha-girlさんから回答いただいたソースを元にしたいと思います。

printf( "2行目3列目は「%s」" , ReadCsv( &mycsv , 2 - 1 , 3 - 1 ) );
は、理解できたのですが、
その他の動きがまったくわからない状態です、、

aaa.txtを読み込んだ時の
最大行の数、最大列の数はどの変数にあたるのでしょうか?

たとえば、
最大行の数=x
最大列の数=y
i=1,j=1として、
i=1 to x
j=1 to y
とし、ループで全部表示させることが目的です。

printf( "%d行目%d列目は「%s」" , i,j,ReadCsv( &mycsv , i - 1 , j - 1 ) );

お礼日時:2005/02/14 07:57

#1です。

ちょっと下のソースおかしかったので訂正しときます。

int main()
{
FILE *fp;
char buf[MAX_BUF];
int buflen = 0;
int ttlbuflen = 0;
fp = fopen("aaa.csv", "r");
char *pBuf2 = NULL;

char* pp;
while( fgets(buf, MAX_BUF , fp) ){
buflen = strlen(buf);
ttlbuflen += buflen;
if ( buf[buflen - 1] == '\n'){
buf[buflen - 1] = '\0';
if (pBuf2 == NULL){
pBuf2 = (char*)malloc( ttlbuflen + 1 );
strcpy( pBuf2 , buf );
}else{
pBuf2 = (char*)realloc( pBuf2 , ttlbuflen + 1 );
strcat( pBuf2 , buf );
}
printf("%s\n",pBuf2);
if (pBuf2) free(pBuf2);
ttlbuflen = 0;
pBuf2 = NULL;
}else{
if ( pBuf2 == NULL ){
pBuf2 = (char*)malloc( ttlbuflen + 1 );
strcpy( pBuf2 , buf );
}else{
pBuf2 = (char*)realloc( pBuf2 , ttlbuflen + 1 );
strcat( pBuf2 , buf );
}
}
}
if (pBuf2) free(pBuf2);
}



ところでC++(stlのvectorやstring)を使うっていうのは無しですよね?
Cのみで構造体を可変長にする場合、上記と同じようにreallocやmalloc、callocを
使用します。
可変長文字列かつ可変長リストであるなら
typedef struct ___mycsvline{
int cnt;
char **str;
} MYCSVLINE;
typedef struct ___mycsv{
int cnt;
MYCSVLINE* line;
} MYCSV;
CSVは構造体はこんな定義でどうでしょう。
    • good
    • 0

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