配列
数回に渡り質問させてもらってますが
構造体のメンバをポインタで宣言してるのが不評で
配列の方でも組んでみました。
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE -1
char* get(char **p_str);
char *get_line(char buf[]);
int comp_rtn(const void *p1, const void *p2);
typedef struct {
int number;
char class_type[10];
char name[15];
char subject[10];
int ten;
} my;
my *data;
void myswap(my *p, my *q);
int main(int argc, char* argv[])
{
FILE *fp;
int field = 0, line = 0;
char buf[1000], *str;
char *bufFormat;
char *bufG;
bufFormat =(char *)malloc(1000);
bufG = (char *)malloc(1000);
int line2 = 0;
if((fp=fopen("jjj.txt","r"))==NULL){
printf("ファイルが開けません");
}
while(fgets(buf, 1000, fp) != NULL){
line2++;
}
fclose(fp);
if((fp=fopen("jjj.txt","r"))==NULL){
printf("ファイルが開けません");
}
data = (my *)malloc(sizeof(my) * line2);
while(fgets(buf,1000,fp) != NULL){
bufFormat = get_line(buf);
str = bufFormat;
while(*str != '\0'){
bufG = get(&str);
switch(field){
case 0:
data[line].number = atoi(bufG); break
case 1:
strcpy(data[line].class_type, bufG);
break;
case 2:
strcpy(data[line].name, bufG);
break;
case 3:
strcpy(data[line].subject, bufG);
break;
case 4:
data[line].ten = atoi(bufG);
break;
}
str++;
field++;
}
line++;
field = 0;
}
fclose(fp);
qsort(data,line,sizeof(my),comp_rtn);
for(int m = 0; m < line; m++){
printf("%d\n", data[m].number);
printf("%s\n", data[m].class_type);
printf("%s\n", data[m].name);
printf("%s\n", data[m].subject);
printf("%d\n", data[m].ten);
printf("\n");
}
free(data);
return 0;
}
void myswap(my *p, my *q)
{
my temp;
temp = *p;
*p = *q;
*q = temp;
}
char *get(char **p_str)
{
int i;
char *str;
str = *p_str;
static char bufG[1000];
for(i = 0; *str != ',' && *str != '\0' ; i++){
if(*str == '\n'){
bufG[i] = '\0';
}
else if(*str == '\\'){
str++;
if(*str == 'c'){
bufG[i] = ',';
}
else if(*str == '"'){
bufG[i] = '"';
}
}
else{
bufG[i] = *str;
}
str++;
}
bufG[i] = '\0';
*p_str = str;
return bufG;
}
char *get_line(char buf[])
{
int in_quotation = FALSE, i = 0;
char* str = buf;
static char bufG[1000];
while(*str != '\0'){
if(*str=='"'){
if(in_quotation == TRUE){
str++;
if(*str == '"'){
bufG[i] = '\\';
i++;
bufG[i] = '"';
i++;
}
else{
in_quotation = FALSE;
bufG[i] = *str;
i++;
}
}
else{
in_quotation = TRUE;
}
}
else{
switch(*str){
case '\n':
if(in_quotation == TRUE){
bufG[i] = '\\';
i++;
bufG[i] = 'n';
i++;
}
else{
bufG[i] = *str;
i++;
}
break;
case ',':
if(in_quotation == TRUE){
bufG[i] = '\\';
i++;
bufG[i] = 'c';
i++;
}
else{
bufG[i] = *str;
i++;
}
break;
default:
bufG[i] = *str;
i++;
}
}
str++;
}
bufG[i] = '\0';
return bufG;
}
ファイルは
1,犬,ボルト,国語,2
2,猫,山田,数学,1
3,犬,鈴木,英語,2
4,犬,居合,国語,1
5,猫,伊藤,数学,2
6,猫,斎藤,数学,1
こういう感じになりますが
不思議なことにこのファイルの文字列の所を 表 にすると
バグって表示されます。
例えば
1,表,山田,数学,2とか
1,犬,ボルト,国語,2
2,猫,山田,数学,1
3,犬,鈴木,英語,2
4,犬,居合,国語,1
5,猫,伊藤,表,2
6,猫,斎藤,数学,1
とかです。
この現象は何故起きるのでしょうか?
デバグした所、代入のときにはちゃんとしたものが代入されていますが
次の項目を代入したときにバグ化しているようです
V開発環境はC++6.0のコンソールappです。
お礼
す、すごいです…ふむふむ!なるほろ!! としか言いようがありません汗 >配列は連続したメモリのアドレスに確保されます。 これ知りませんでした!!2次元配列の等しい前1次元に対する後1次元のアドレスは連続するのだろうと思っていましたが、考えてみれば連続して定義したんだからアドレスも連続しなきゃおかしい…というかこんがらがりますよね。 それで1つ疑問なのですが、 >一方comp[5]は > >comp[0] == "P" >comp[1] == "o" >comp[2] == "l" >comp[3] == "e" >comp[4] == "\0" >comp[5] == (null) > >nameは連続して配列を宣言しましたがcompはもう次に配列を宣言して>いないので、 >comp[5]は何も入っていません。 >つまりnullです。 あともう1つ上で回答してくださったWernerさんの >>>#5 >> name[0][6] == (null) 何もないという意味です。 >分かりやすく説明するためにあえてnullが入っていると言うことにしたのかもしれませんが、 >実際には配列の初期化時に値が明示的に指定されなかった要素は0で初期化されます。 >(今回の場合char型なので'\0'が入っているともいえます。) この辺の話なのですが、確かCかFortran77の講義で「変数を割り当てていないアドレスには予め何らかの値が入っている」と習って、実際定義前の適当なアドレスの中身を表示させるとアトランダムな値が出てきた、という記憶があるのですが、記憶違いなんでしょうか?今回のcomp[5]のように char comp[5]="Pole"; の割り当てからnull文字が入ったcomp[4]の次のアドレスを表すcomp[5]なので初期化される、という理由ならこの私の疑問は見当違いな話なんですが。ちなみに講義ではLinuxを使ってました…関係ないとは思いますが一応。。