ご質問です。
構造体で、あらかじめメンバ数を固定したものではなく、
テキストファイルを読み込んだときにメンバ数を変えて読み込みたいのです。
(カンマできりたい)
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;
}
No.1ベストアンサー
- 回答日時:
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);
}
No.6
- 回答日時:
訂正
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 );
を追加すれば解消します。
沢山の回答ありがとうございました。
大変勉強になりました。
(が、結局可変長のところはうまくいかず締め切りがきてしまいました、、)
もう少し勉強していきたいと思います。
今後ともよろしくお願いいたします。
No.5
- 回答日時:
>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
でも受け付けています。
No.4
- 回答日時:
最終的に何がしたいのかわからないのですが、元のソースをベースに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 ) );
No.3
- 回答日時:
とりあえず書いてみました。
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);
}
回答を頂いた皆様へ
ありがとうございます。
>二次元配列にする必要があり、最大の列・行数が不定ならば・・・
できれば二次元配列にしたいので、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 ) );
No.2
- 回答日時:
#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は構造体はこんな定義でどうでしょう。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
double型の値をchar配列に変換...
-
YUV⇔RGB変換がうまくいきません。
-
fgetsなどのときのstdinのバッ...
-
単語数、文字数のカウントプロ...
-
CStringをwchar_tに変換したい
-
間接操作のレベルとは
-
下記のプログラムがコンパイラ...
-
型変換
-
文字列から空白を取り除きたい...
-
Win32APIでのエディットボック...
-
C言語プログラミングについて(...
-
単語を読み取る(c言語)
-
c言語配列の結合についてです。...
-
'const char *' 型は 'char *' ...
-
C言語です
-
int main()の・・・
-
Microsoft OfficeをDDEで操作
-
3桁区切(コンマ)記号をつけ...
-
DPマッチング
-
C言語 構造体(2)
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CStringをwchar_tに変換したい
-
fgetsなどのときのstdinのバッ...
-
charからLPTSTRへの変換方法
-
C言語のfor文です。 繰り返しの...
-
文字列から空白を取り除きたい...
-
配列をnビットシフトする
-
間接操作のレベルとは
-
charでの計算?
-
テキストデータをそのままバイ...
-
型変換
-
'const char *' 型は 'char *' ...
-
double型の値をchar配列に変換...
-
間接参照のレベルが異なっています
-
干支のプログラム
-
atoi( ) の反対をやりたい
-
C言語です
-
絶対パスからのファイル名の切...
-
ネットワークにつながっている...
-
【C言語】文字型と整数型の違い
-
Win32APIでのエディットボック...
おすすめ情報