No.9
- 回答日時:
★回答者No.6です。
・デバッグしてみました。
どうやら回答 No.6 のサンプルに一部間違いがありました。
それが原因で文字化けしていました。
修正版:
for ( j = 0, n++ ; string[n] != '\n' ; n++, j++ ){
list[ i ].job[ j ] = string[ n ];
}
list[ i ].job[ j ] = '\0';
修正箇所1:
・job 配列の添え字に n を使っていたのが間違いです。
正しくは新しいカウンタ変数 j などを用意して添え字が 0 から始まるようにします。
これにより最後の '\0' も job[ j ] = '\0'; と j カウンタに変更します。
修正箇所2:
・for()文の条件式で string[n] != '\0' としていましたが、改行を job 配列に
含めないようにするため string[n] != '\n' と変更して下さい。
修正箇所3:
・meibo 構造体の job のサイズが 5 です。
質問にあるテキストファイル(meibo.txt)には『公務員』『学生』ですよね。
『学生』はともかく『公務員』はサイズが 6 です。'\0'文字も含めると 7 になります。
配列の容量が不足しています。job[ 10 ]; ぐらいに変更して下さい。
上記の3箇所を修正すれば正しく動きました。
なおスペースが 2 個以上連続していたり、名前が 9 文字以上だったり、または
職業名が 4 文字以上だと name、job の配列容量を越えます。この辺のチェックを
付け加えた方が良いでしょう。あとポインタを使ったり、strcpy()、atoi() 関数を
使って処理させる方法もあります。いろいろと工夫してみてください。
>Oh-Orangeさん
本当に丁寧な解説ありがとうございました☆☆☆
おかげでこのやり方でもうまく表示できました(^o^)
Oh-Orangeさんのお陰で、
文字列の処理(入門)の仕方が
かなりわかりました(^o^)b
今度は自分の文字列処理の仕方を
見つけて、知識を深めたいと思います☆
ありがとうございました☆
No.8
- 回答日時:
★回答者No.6です。
・補足より。文字列から整数値の変換の仕方を書きます。
>>list[ i ].age *= 10;
>>list[ i ].age += (string[n] - '0'); ←文字から数値に変換
>
>の2行が理解しがたいのですが…これは、
>決まりみたいなものなのでしょうか?
>特に上の行の10を代入の意味は???
↑
これを次のように書き換えてみます。
char str[] = "123";
int age = 0; ←初期化
for ( i = 0 ; str[i] != '\0' ; i++ ){
age = (age * 10) + (str[i] - '0');
}
とします。また、
>age = (age * 10) + (str[i] - '0');
の行は次の2行でも同じ処理になります。記述が違うだけ。
age *= 10;
age += (str[i] - '0');
こういうことです。
・それではfor文を展開してみます。
i=0のとき age = (age * 10) + ('1' - '0'); … age = 0 + 1;⇒age=1
i=1のとき age = (age * 10) + ('2' - '0'); … age = 10 + 2;⇒age=12
i=2のとき age = (age * 10) + ('3' - '0'); … age = 120 + 3;⇒age=123
となって age = 123 がセットされます。
この仕組みが『文字列から整数値の変換』の決まりみたいな方法です。
・以上。
この回答への補足
Oh-Orangeさん
ありがとうございます☆
とてもすばらしい解説でした(*^o^*)
しかし、Oh-Orangeさんのプログラムを参考に作ってみたのですが、
どうしても job が文字化けしてしまいます(T_T)
どこがおかしいでしょうか?
#include <stdio.h>
#include <stdlib.h>
#define PROF 256
int main(void)
{
struct meibo{
char name[20];
int age;
char job[5];
}list[10];
char FileName[20];
unsigned char string[PROF];
int i=0,j,n;
FILE *fp;
printf("入力ファイル名>>>");
scanf("%s",FileName);
if((fp=fopen(FileName,"r"))==NULL)
{
printf("ファイルが見つかりません。---%s\n",FileName);
exit(EXIT_FAILURE);
}
while(fgets(string,PROF,fp)!=NULL)
{
for(n=0;string[n]!=' ';n++)
{
list[i].name[n]=string[n];
}
list[i].name[n]='\0';
list[i].age=0;
for(n++;string[n]!=' ';n++)
{
list[i].age*=10;
list[i].age+=(string[n]-'0');
}
for(n++;string[n]!='\0';n++)
{
list[i].job[n]=string[n];
}
list[i].job[n]='\0';
i++;
}
for(j=0;j<i;j++)
{
printf("%s %d %s\n",list[j].name,list[j].age,list[j].job);
}
fclose(fp);
return EXIT_SUCCESS;
}
No.7
- 回答日時:
初心者向きなら
以下のようなfscanfを使うやり方もあります
int i;
FILE *fp
fp = fopen("meibo.txt", "r");
i = 0;
while (!feof(fp))
{
fscanf(fp,"%s %d %s",list[i].name,&(list[i].age),list[i].job);
i++;
}
尚、プロは、scanfやfscanfの使用は嫌うようです。
gyrocompasさん
初心者なので、このような解説もとてもありがたいです☆
シンプルなのですぐに組み込んでみたいと思います☆
No.6ベストアンサー
- 回答日時:
★全く分からんのですか?
>としたあとにどのように入れたらよいかがわかりません…
↑
これは文字列の表現の仕組みを理解していれば出来ると思います。
回答者 No.2 さんの補足にあるソースで strcpy() 関数を使わなでコピーすれば
上手くいくようになります。もちろんすべてが正しいわけではなく、考え方が
大よそあっているという事です。
HNDHDKさんのソース
while(fgets(string,128,fp)){
for(n=0;string[n]!=" ";n++){
strcpy(list[i].name,string[n]);
}
for(n=n+1;string[n]!=" ";n++){
list[i].age=;
}
for(n=n+1;string[n]!='\0';n++){
strcpy(list[i].name,string[n]);
}
}
これを strcpy() 関数を使わないで処理すると
while ( fgets(string,128,fp) != NULL ){
for ( n = 0 ; string[n] != ' ' ; n++ ){ ←スペースは文字定数で比較(文字列ではない)
list[ i ].name[ n ] = string[ n ];
}
list[ i ].name[ n ] = '\0'; ←末尾の'\0'(重要)
list[ i ].age = 0; ←ゼロを入れておく
for ( n++ ; string[n] != ' ' ; n++ ){ ←ここも文字定数で比較
list[ i ].age *= 10;
list[ i ].age += (string[n] - '0'); ←文字から数値に変換
}
for ( n++ ; string[n] != '\0' ; n++ ){
list[ i ].job[ n ] = string[ n ];
}
list[ i ].job[ n ] = '\0'; ←ここも末尾の'\0'(重要)
}
となります。
最後の要素は job メンバに入れるように修正しておきました。
こんな感じでいいです。
strcpy() 関数を使いたい場合は区切り文字(スペース)に '\0' をセットしてから
文字列の先頭を strcpy() 関数に渡すことでコピーできます。今回は文字単位で
コピーする方法を紹介しました。改良してみて下さい。
>ageはint型なのでどのようにしたら?
これも区切り文字(スペース)に '\0' をセットした後に atoi() 関数で文字列から
整数値に変換できます。今回は文字単位で整数値に変換してみました。
それが次の2行です。
>list[ i ].age *= 10;
>list[ i ].age += (string[n] - '0'); ←文字から数値に変換
このようにすることで文字列から整数値に変換できます。
最後に:
文字定数と文字列定数を混同しないように注意して下さい。
また、文字の比較と文字列の比較も違いますので同じに考えないで下さい。
C言語では文字列の比較にstrcmp()関数で行います。
この回答への補足
Oh-Orangeさん
>list[ i ].age *= 10;
>list[ i ].age += (string[n] - '0'); ←文字から数値に変換
の2行が理解しがたいのですが…これは、
決まりみたいなものなのでしょうか?
特に上の行の10を代入の意味は???
No.5
- 回答日時:
> while(string!=" ")
これは、ローカル変数のstringの「アドレス」と、プログラム中のどこかに確保された
" "(メモリ上では 0x20 0x00)の「アドレス」を比較しています。
結果が等しくない時に真となりますので、ここの条件判定は常に真です。
# 値の書き換わる変数と、文字列定数の先頭アドレスが同一になることは絶対にありませんので。
表示されないのは、
strcpy(list[i].name,string);
を無限ループで実行しているため、ここから先に進まないからではないでしょうか。
文字列の比較はstrcmp()を使用しましょう。
# C++の文字列クラスの場合、string!=" "と言う判定が可能になっている場合がありますが。
No.4
- 回答日時:
★デリミタは、半角空白(0x20)ひとつとする。
★最大レコード長は255バイトとする。
★名前、職業には半角空白を含めない。
★レコード数は30以内。
のファイルの条件があり、
★構造体の職業項目には、復帰改行コードを含めない(◆)。
の作成仕様があるとき、
☆基本部分のみでは、説明できないので・・ほぼ「丸受け」?
#define un_char unsigned char
typedef struct{
int iAge;
char cName[16];
char cJob[32];
}LIST;
int toStruct( int iCntSpace, LIST sWork[], int nn, un_char cBuf[], int iTop )
{
int i, iCnt = 0;
for( i = 0; i < 256; i++ ){
if( 0x0D >= cBuf[i] ) cBuf[i] = 0x20; // 復帰改行コード(◆)
if( 0x20 == cBuf[i] ) iCnt++; // 0x20 デリミタ
if( iCnt == iCntSpace ){
cBuf[i] = 0x00; // 要素の末端
if( 1 == iCnt ) strcpy( sWork[nn].cName, &cBuf[iTop] );
if( 3 == iCnt ) strcpy( sWork[nn].cJob, &cBuf[iTop] );
if( 2 == iCnt ) sWork[nn].iAge = atoi( &cBuf[iTop] );
return( i + 1 ); // 次の要素の先頭
}
}
return( 0 );
}
void main()
{
LIST sWork[30];
int i, nn = 0, iTop;
FILE *fp1;
un_char cBuf[256];
fp1 = fopen( "meibo.txt", "r" );
// File check(略)
while( NULL != fgets( cBuf, 255, fp1 ) ){
iTop = toStruct( 1, sWork, nn, cBuf, 0 );
iTop = toStruct( 2, sWork, nn, cBuf, iTop );
iTop = toStruct( 3, sWork, nn, cBuf, iTop );
nn++;
}
fclose( fp1 );
for( i = 0; i < nn; i++ ){
printf( "%-10s %2d %s\n", sWork[i].cName, sWork[i].iAge, sWork[i].cJob );
}
}
注:インデントに全角空白を用いています。
yama5140さん
この間の質問といい、たびたびありがとうございます☆
サブ関を使ったやり方ですね☆
参考にさせていただきます☆
No.3
- 回答日時:
>ageはint型なのでどのようにしたら?
じゃあ、ひとまずコイツは list[i].age = 0; にしといて、コンパイルしてみよか。
エラーが出ると思うので strcpy のマニュアルなどみつつ修正して下さい。
この回答への補足
なんとかコンパイルまでこぎつけました☆
現段階でのプログラムはこんな感じなんですが、
表示がされなくて…
while(fgets(string,PROF,fp))
{
while(string!=" ")
{
strcpy(list[i].name,string);
}
while(string!=" ")
{
list[i].age=0;
}
while(string!='\0')
{
strcpy(list[i].male,string);
}
i++;
}
for(i=0;i<5;i++)
{
printf("%s %d %s\n",list[i].name,list[i].age,list[i].male);
}
ご指導お願いします!!!
koko_u_さん
皆様の解説とを参考にしながら、ようやく表示に成功しました!!
理解力に乏しい自分に何度も解説していただき
本当にありがとうございましたm(_ _)m
No.2
- 回答日時:
>中の処理は、
>
>strcpy(list[i].name,~);
>
> みたいなことこですか?
ま、こういうのは「正解」はないので、
まずは自分の知っている関数を使ってとにかく動くコードを書きましょう。
strcpy はコピー元の文字列で '\0' が現れるまでをコピーしますね。
「田中」までをコピーするにはどうすればよいか考えましょう。
はい。補足にどうぞ。
この回答への補足
while(fgets(string,128,fp))
{
for(n=0;string[n]!=" ";n++)
{
strcpy(list[i].name,string[n]);
}
for(n=n+1;string[n]!=" ";n++)
{
list[i].age=;
}
for(n=n+1;string[n]!='\0';n++)
{
strcpy(list[i].name,string[n]);
}
}
こんな感じでいいのでしょうか?
ageはint型なのでどのようにしたら?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
プログラムによく出てくるst...
-
C#でstringをポインタとして渡す
-
c#で他のアプリの文字入力フォ...
-
シリアル通信で0x00を送信した...
-
数字の入った配列をファイルへ...
-
VB6.0でのバイナリデータの扱い...
-
C++で文字列の右端から特定の文...
-
構造体→文字列→構造体 をする方法
-
%dなどの違い
-
Excelシートを固定長のテキスト...
-
【c++】文字列の操作
-
関数から配列を返すには?
-
C言語 配列の長さの上限
-
VB.NETでファイル名順にファイ...
-
System.IO.Directory.GetFiles...
-
C言語のポインタに直接アドレス...
-
VBAのプログラムで、DIAG = 1# ...
-
セグメントエラー
-
CStringからchar*への型変換に...
-
配列の要素数に変数を入れたい...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
プログラムによく出てくるst...
-
C#でstringをポインタとして渡す
-
nullと""、\\0とEOFの違いにつ...
-
WSH(VBS)でJSONの文字列を読み...
-
VB6.0でのバイナリデータの扱い...
-
TCL言語で文字列検索方法を教え...
-
C++で入力した文字列から数字を...
-
シリアル通信で0x00を送信した...
-
16進数を2文字ずつ配列に格納し...
-
char型配列の最大要素数
-
[C++]WCHARの1文字目しか表示で...
-
_tcscpy_s(wcscpy_s)の第二引数...
-
構造体→文字列→構造体 をする方法
-
%dなどの違い
-
数字の入った配列をファイルへ...
-
c#で他のアプリの文字入力フォ...
-
引用符と二重引用符
-
Shift_JIS(16進)を文字に変換す...
-
CSVファイルの「”」について
-
AnsiStringについて
おすすめ情報