PDA

View Full Version : سوال: چند سوال در مورد فایل ها



...StacK...
یک شنبه 11 مرداد 1388, 05:59 صبح
سلام.
فرض کنید یه ساختمان به صورت زیر داریم:


struct x{
char name[20];
int ,x,y;
}list[20];
int main(void){
....
....
...
return 0;
}
void x (void)
{
...
*(list[5].name)='a';
*list[5].name='a';


حالا اولین ابهامی که دارم در دو خط اخر از برنامه هست....

من فکر میکنم دو خط اخر برنامه یکی هست و بود یا نبود اون پرانتز فرقی نمیکنه....

ایا این موضوع درسته؟چون ما در هر دو صورت به محتوای ادرس name میرسیم

یعنی اولین خونه از ارایه از متغیر ساختمان لیست.

حالا اگه بنویسیم :

list[5].name[0]='a';

من بازم نتیجه میگیرم که این خط هم با اون دو خط هیچ فرقی نداره ,درسته؟؟؟

-----------------------------------------------------

سوال بعدی :

میگم این قضیه حالت های باز شدن یک فایل چیه؟؟؟مثلا باینری و یا متنی

منظور از باینری مگه فایل های اجرایی نیست؟؟؟ پس چرا ما از این حالت (b) برای فایل

های متنی هم استفاده میکنیم؟؟؟؟مثل نوشتن یک متن در یک فایل و یا باز کردن یک فایل

متنی موجود در حالت باینری...؟؟؟
-----------------------------------------------------
سوال بعدی:به این کد دقت کنید:xx


#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<string.h>
#include<ctype.h>
#define SIZE 100
struct student {
char name[10];
int stno,sex;
float grade;
}list[SIZE];
int menu(void);
void init_list(void),enter(void);
void display(void),save(void);
void load(void);
int main(void)
{
init_list();
for(;;){
switch(menu()){
case 'e':enter();break;
case 'd':display();break;
case 's':save();break;
case 'l':load();break;
case 'q':exit(0);
}//end of switch
}//end of for
}
//******************************
void enter(void)
{
register int i;
int row;
char numstr[10];
for(i=0;i<SIZE;i++)
if(!(*list[i].name))
break;
if(i==SIZE){
printf("\n list is full press a key...");
getch();
}
clrscr();
gotoxy(10,2);
puts("<<INPUT DATA>>");
gotoxy(1,3);
printf(" name stno gread sex(1,2)");
gotoxy(1,4);
puts("-------- ------- ------ --------");
row=5;
for(;;){
gotoxy(1,row);
gets(list[i].name);
if(!(*list[i].name)) break;
gotoxy(16,row);
gets(numstr);
list[i].stno=atoi(numstr);
gotoxy(28,row);
gets(numstr);
list[i].grade=atof(numstr);
gotoxy(40,row);
gets(numstr);
list[i].sex=atoi(numstr);
row ++;
i++;
}
}
//****************
void init_list(void)
{
register int t;
for(t=0;t<SIZE;t++)
*list[t].name='\0';
}
//********************
int menu(void)
{
char s[10];
clrscr();
do{
gotoxy(20,4);
printf("E) enter data ");
gotoxy(20,6);
printf("D) display on screen");
gotoxy(20,8);
printf("L) load file");
gotoxy(20,10);
printf("S) save in file");
gotoxy(20,12);
printf("Q) quit");
gotoxy(20,14);
printf("enter your select:");
gets(s);
}while(!strchr("edlsq",tolower(*s)));
return tolower(*s);
}
//*********************************
void display(void)
{
register int t;
int row;
clrscr();
gotoxy(10,2);
puts("<< OUTPUT DATA >>");
gotoxy(1,3);
printf("----------- ------- ------ -----------");
row=5;
for(t=0;t<SIZE;t++)
if(*list[t].name){
gotoxy(1,row);
printf("%s",list[t].name);
gotoxy(12,row);
printf("%d",list[t].stno);
gotoxy(20,row);
printf("%5.2f",list[t].grade);
gotoxy(30,row);
printf("%d",list[t].sex);
row++;
}//end of if
gotoxy(5,row+2);
printf("press a key ...");
getch();
}
//*******************************
void save(void)
{
FILE *fp;
register int i;
fp=fopen("st.txt","w(wt)");
if(!fp){
printf("\n cannot open file press a key...");
getch();
return;
}
for(i=0;i<SIZE;i++)
if(*list[i].name)
fwrite(&list[i],sizeof(struct student),1,fp);//end of if /end of for
fclose(fp);
clrscr();
gotoxy(20,10);
printf("data saved. prees a key.");
getch();
}
//*****************
void load(void)
{
FILE *fp;
register int i;
fp=fopen("st.txt","r+(r+t)");
if(!fp){
printf("\n cannot open file. press a key...");
getch();
return;
}
init_list();
for(i=0;i<SIZE;i++){
fread(&list[i],sizeof(struct student),1,fp);
if(feof(fp)){
clrscr();
gotoxy(20,10);
printf("data loaded.press a key.");
getch();
fclose(fp);
return;
}//end of if
}
fclose(fp);
}

بعد از اجرای فایل یه سری داده به برنامه بدید و در فایل ذخیره کنید, و بعد فایل رو ببینید

بعضی از قسمت های رشته به صورت نا معلوم هست ,یعنی یه حالت هش شده مانندی

مثلا محتوای فایلی که باید به صورت زیر باشه:

ali 2222 20 1
barnamenevis 1111 20 1

به صورت زیر هست:
ali ق AbarnamenevW A

این کد یه مثال از کتاب c قمی هست ,که البته از روی کتاب دوباره نوشتم و یه سری

کم و کاستی هاشو درست کردم "نظیر اینکه در کد اصلی بعد از بازکردن فایل اونا نبسته بود

و یا در مد باینری باز کرده بود"... با این حال در کد اصلی هم این مشکل وجود داره:

اینم کد اصلی:

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>
#define SIZE 100
struct student {
char name [10] ;
int stno, sex ;
float grade ;
} list[SIZE] ;
int menu(void) ;
void init_list(void) , enter(void) ;
void display(void) , save(void) ;
void load(void) ;
int main()
{
init_list();
for(;;) {
switch(menu()) {
case 'e': enter(); break;
case 'd': display(); break ;
case 's' : save() ; break;
case 'l' : load() ; break ;
case 'q': exit(0) ;
}//end of switch
} //end of for
}
//**********************
void init_list(void)
{
register int t;
for (t = 0 ; t < SIZE ; t++)
*(list[t].name) = '\0' ;
}
//***********************
void enter(void)
{
register int i ;
int row ;
char numstr[10];
for(i = 0; i < SIZE; i++)
if (!(*list[i].name))
break ;
if(i == SIZE) {
printf("\n list is full press a key ...") ;
getch() ;
}
clrscr() ;
gotoxy(10, 2) ;
puts("<< INPUT DATA >>");
gotoxy(1, 3) ;
printf(" name stno gread sex(1, 2)" ) ;
gotoxy(1,4) ;
puts (" ------- ----- ------- -------") ;
row = 5 ;
for(;;) {
gotoxy(1, row);
gets(list[i].name);
if(! (*list[i].name))
break ;
gotoxy(16, row);
gets(numstr) ;
list[i].stno = atoi(numstr) ;
gotoxy(28, row) ;
gets(numstr) ;
list[i].grade = atof(numstr) ;
gotoxy(40, row) ;
gets(numstr) ;
list[i].sex = atoi(numstr) ;
row ++ ;
i ++ ;
}
}
//***********************
void display(void)
{
register int t ;
int row ;
clrscr() ;
gotoxy(10, 2) ;
puts("<< OUTPUT DATA >> ") ;
gotoxy(1, 3) ;
printf(" name stno grade sex(1,2)") ;
gotoxy(1, 4);
printf("------- ---- ----- --------") ;
row = 5 ;
for(t = 0 ; t < SIZE ; t++)
if(*list[t].name) {
gotoxy(1, row) ;
printf("%s", list[t].name);
gotoxy(12, row) ;
printf("%d", list[t].stno);
gotoxy(20, row) ;
printf("%5.2f", list[t].grade) ;
gotoxy(30, row) ;
printf("%d", list[t].sex) ;
row ++ ;
} //end of if
gotoxy(5, row+2);
printf(" press a key ...");
getch() ;
}
//***********************
void save(void)
{
FILE *fp ;
register int i ;
fp = fopen("st", "wb");
if(!fp) {
printf("\n cannot open file press a key ...");
getch() ;
return ;
}
for(i = 0 ; i < SIZE ; i++)
if(*list[i].name)
fwrite(&list[i], sizeof(struct student), 1, fp) ;
clrscr() ;
gotoxy(20, 10) ;
printf("data saved.press a key.");
getch() ;
}
//************************
void load(void)
{
FILE *fp ;
register int i ;
fp = fopen("st", "rb");
if(!fp) {
printf("\n cannot open file press a key ...");
getch() ;
return ;
}
init_list() ;
for(i = 0 ; i < SIZE ; i++) {
fread(&list[i], sizeof(struct student), 1, fp);
if(feof(fp)) {
clrscr() ;
gotoxy(20,10) ;
printf("data loaded.press a key.");
getch() ;
return ;
}//end of if
}
}
//*****************
int menu(void)
{
char s[10] ;
clrscr();
do {
gotoxy(20, 4);
printf("E) enter data ");
gotoxy(20, 6);
printf("D) display on screen");
gotoxy(20, 8);
printf("L) load file");
gotoxy(20, 10);
printf("S) save in file");
gotoxy(20, 12);
printf("Q) quit");
gotoxy(20, 14);
printf("enter your select:");
gets(s) ;
} while(!strchr("edlsq", tolower(*s)));
return tolower(*s) ;
}


---------------------------------
سوال بعدیم:xx

فرض کنید این خط کد به صورت عمومی (در بالای main) تعریف میشه....


FILE *fopen();

منظور از این خط چیه؟؟ نه به اشاره گر فایل میخوره و نه ...پس چیه....

این کتاب قمی ادما روانی میکنه....برداشته یه مثال 300 خطی نوشته ...

حتی یک دونه متغیر رو هم توضیح نداده بعد تو قسمت بعد هم میگه:

خب در قسمت قبل مسئله فایل های ترتیبی برسی شد...بر هرچی دروغ گو هست لعنت.

------البته از یه کتاب انگلیسی به اسم:
C Primer Plus, Fifth EditionBy Stephen Prata دارم میخونم ولی خب اولاش هستم....واسه توضیح یه متغیر 100 شکل کشیده و 200خط

توضیح داده--به این میگم کتاب....

ولی کتاب اون قمی رو هم شروع کردم ....نمیتونم نیمه کار رهاش کنم...

پس مجبورم مشکلاتم رو اینجا مطرح کنم ....امیدوارم در حد توان راهنماییم کنید...

ممنونم.:قلب::بوس:

clover
یک شنبه 11 مرداد 1388, 11:42 صبح
من فکر میکنم دو خط اخر برنامه یکی هست و بود یا نبود اون پرانتز فرقی نمیکنه....

ایا این موضوع درسته؟چون ما در هر دو صورت به محتوای ادرس name میرسیم

یعنی اولین خونه از ارایه از متغیر ساختمان لیست.

حالا اگه بنویسیم :
کد:
list[5].name[0]='a';
من بازم نتیجه میگیرم که این خط هم با اون دو خط هیچ فرقی نداره ,درسته؟؟؟

بله دوست عزیز ، هر سه دستور معادل هم هستن . یاد آوری می کنم که عملگر نقطه ( . ) نسبت به عملگر دسترسی به محتوا ( * ) دارای تقدم بالاتری هست . پس پرانتز ها هیچ تاثیری ندارن .
یه مساله شبیه به این تو کتاب دایتل مطرح شده که تفاوت ظریفی با مساله شما داره ، به قطعه کد زیر دقت کنید :

struct Time{
int hour;
int minute;
int second;
}timeObject, *timePtr = &timeObject;

int main()
{
*timePtr.hour = 12;
*(timePtr.hour) = 12;
(*timePtr).hour = 12;
timePtr->hour = 12;
return 0;
}
کامپایلر از دستور اول و دوم در تابع main خطای نحوی می گیره ( دقت کنید که timePtr یه اشاره گره و عملگر نقطه ( . ) نسبت به عملگر دسترسی به محتوا ( * ) دارای تقدم بالاتری هست ) ، دستور های سوم و چهارم درست هستند و hour مقدار 12 می گیره .

حالا در مساله شما هم اگر از list بدون اندیس و به صورت اشاره گر استفاده کنیم این قوانین صدق می کنن .

clover
یک شنبه 11 مرداد 1388, 12:07 عصر
میگم این قضیه حالت های باز شدن یک فایل چیه؟؟؟مثلا باینری و یا متنی

منظور از باینری مگه فایل های اجرایی نیست؟؟؟ پس چرا ما از این حالت (b) برای فایل

های متنی هم استفاده میکنیم؟؟؟؟مثل نوشتن یک متن در یک فایل و یا باز کردن یک فایل

متنی موجود در حالت باینری...؟؟؟

فایل های متنی :
در مورد فایل ها باید بگم که فایل ها یا stream های متنی استاندار شامل یک دنباله از کاراکتر ها از جمله خط بعد و ابتدای خط هستند . در مد متنی وقتی که کارکتر ها خوانده یا نوشته میشن بون تغییر نمی مونن و بسته به سیستم مواردی اضافه یا کم میشه . مثلا کاراکتر خط جدید یا انتهای فایل . این کار برای بعضی از برنامه ها مشکل ایجاد میکنه . توضیح اینکه برای مثال مقدار اسکی کاراکتر خط جدید ، عدد 10 هست و میشه اونو به صورت یک 0A هگزا دسیمال 8 بیتی هم نوشت . هم در برنامه های C و هم در برنامه های ++C این کاراکتر فقط یک ثابت کاراکتری ( 'n\' ) تلقی میشه ، اما در عملیات سازگار با MS-DOS کاراکتر خط جدید به صورت CR/LF - یک جفت کاراکتر خط بعد ( عدد 13 دهدهی ) / ابتدای خط ( عدد 10 دهدهی ) - نمایش داده میشه ، این به خودی خود مشکل نیست چون برنامه تبدیلاتو انجام میده ، مساله اینجاست که یک کاراکتر خط جدید 1 بایت فضا اشغال میکنه در حالی که جفت کاراکتر CR/LF دو بایت فضا ، حالا خودتون تصور کنید که عملیات شما وابسته به طول فایل و مکان کاراکتر ها باشه .

فایل های دودویی :
فایل ها یا stream های دودویی شامل یک دنباله از بایت ها هستن که یک رابطه یک به یک بین این فایل ها و وسایل ورودی و خروجی وجود داره ، به همین دلیل هیچ تبدیل کاراکتری صورت نمی گیره و کنترل کاملا دست شماست .
در ضمن این فایل ها به غیر از فایل های اجرایی شامل پایگاه های داده هم میشن ! و کلا هر جایی که لازم باشه داده های محض خونده یا نوشته بشن ، استفاده از فایل های دودویی تضمین میکنه که به غیر از تغییراتی که صریحا توسط برنامه صورت میگیره ، هیچ تغییر دیگه ای انجام نمیشه .

clover
یک شنبه 11 مرداد 1388, 12:12 عصر
در کل من پیشنهاد می کنم که بی خیال کتاب قمی و C بشی و به کتاب دایتل و ++C رو بیاری ( البته اگه حتما فارسی می خوای ) لازم نیست که چرخ رو از ابتدا اختراع کنی . کلاس های I/O در ++C بسیار غنی هستند .

...StacK...
یک شنبه 11 مرداد 1388, 18:07 عصر
ممنون ...توضیحات واقعا کامل بود.

در مورد سوالات بعدیم کسی تا حالا باهاش برخورد نکرده...؟

بالاخره قبل از من هم کسانی با این مسئله و مشکل برخورد کردند...

afi_program
یک شنبه 11 مرداد 1388, 19:28 عصر
منظور کدوم سواله؟

...StacK...
یک شنبه 11 مرداد 1388, 23:43 عصر
جدی متوجه نشدی یا نخوندی؟

با این حال با دوتا xx به رنگ قرمز مشخص کردم.

clover
دوشنبه 12 مرداد 1388, 00:17 صبح
فرض کنید این خط کد به صورت عمومی (در بالای main) تعریف میشه....

کد:
FILE *fopen();
منظور از این خط چیه؟؟ نه به اشاره گر فایل میخوره و نه ...پس چیه....

متوجه منظورتون نمیشم ، یعنی شما می خواید همچین کاری بکنید . خب این به این معنیه که شما دارید یه اشاره گر به فایل با نام fopen به صورت سراسری تعریف می کنید و چون تابعی به نام fopen قبلا در هدر فایل stdio اعلان شده کامپایلر یک خطای نحوی می گیره . در ضمن اگر همین کار را در تابع main انجام بدید باعث می شه که یک متغیر از نوع اشاره گر به فایل ایجاد بشه و تابع fopen به دلیل همنام بودن درون تابع main دیده نشه .


بعد از اجرای فایل یه سری داده به برنامه بدید و در فایل ذخیره کنید, و بعد فایل رو ببینید

بعضی از قسمت های رشته به صورت نا معلوم هست ,یعنی یه حالت هش شده مانندی

مثلا محتوای فایلی که باید به صورت زیر باشه:

ali 2222 20 1
barnamenevis 1111 20 1

به صورت زیر هست:
ali ق AbarnamenevW A

در این مورد فقط می دونم که فایل های باینری لزوما در همه تکست ادیتور ها به صورتی که شما انتظار دارید دیده نمیشن . محتوای فایل را با خود برنامه بخونید یا با یک ادیتور باینری ببینید .

afi_program
دوشنبه 12 مرداد 1388, 00:57 صبح
در مورد فایل باینری خوب طبیعی همینه که اگه با ادیتوری مثل notepad باز بشه اون چیزی که باید باشه نیست
چون فایل با حالت text ذخیره نشده و چیزایی که دوستمون گفتن درسته.
اگه می خوای در خارج برنامه متن فایل را ببینی چرا text ذخیره نمیکنی؟

...StacK...
دوشنبه 12 مرداد 1388, 03:31 صبح
متوجه منظورتون نمیشم ، یعنی شما می خواید همچین کاری بکنید . خب این به این معنیه که شما دارید یه اشاره گر به فایل با نام fopen به صورت سراسری تعریف می کنید و چون تابعی به نام fopen قبلا در هدر فایل stdio اعلان شده کامپایلر یک خطای نحوی می گیره . در ضمن اگر همین کار را در تابع main انجام بدید باعث می شه که یک متغیر از نوع اشاره گر به فایل ایجاد بشه و تابع fopen به دلیل همنام بودن درون تابع main دیده نشه .

.

من نمیخوام این کارو بکنم و خودم هم موندم اخه این چیه دیگه...به این خاطر در موردش

سوال کردم...

این یه مثال از کتاب قمی هست,اینم چند خط از کدهای اولیه(عمومی)


# include <stdio.h>
# include <conio.h>
# include <string.h>
# include <stdlib.h>
# define READONLY "r"
# define WRITEONLY "w"
# define FALSE 0
# define TRUE 1
typedef int boolean;

# define NAMESIZE 21
# define SUBJECTSIZE 11
# define TRAILER 9999
# define INSERT 'I'
# define DELETE 'D'
# define CHANGE 'C'
char *prog;
FILE *fopen();

اخه موندم قمی این خطو از کجا پیدا کرده.!!!قول میدم حتی یه مثال از کتاب خودش رو هم

نمیتونه تحلیل کنه...

این کد کامل که این خط داخلش بود:

http://barnamenevis.org/forum/attachment.php?attachmentid=34471&stc=1&d=1249255064


جالب اینجاست که کامپایلر هیچ خطایی هم نمیگیره.!!!




در این مورد فقط می دونم که فایل های باینری لزوما در همه تکست ادیتور ها به صورتی که شما انتظار دارید دیده نمیشن . محتوای فایل را با خود برنامه بخونید یا با یک ادیتور باینری ببینید


منم همین فکرو میکردم اول (که در کد اصلی به صورت باینری باز شده بود ,ولی بعد که

کد رو ویرایش کردم و دیدم باز هم مشکل پابرجاست,دوباره رسیدم سرجای اول)...

این توابعی که که فایل به عنوان ورودی و خروجی ,جهت ذخیره رشته از ارایه به فایل

و لود رشته از فایل در ارایه به کار میره:

void load(void)
{
FILE *fp;
register int i;
fp=fopen("st.txt","r+(r+t)");
if(!fp){
printf("\n cannot open file. press a key...");
getch();
return;
}
init_list();
for(i=0;i<SIZE;i++){
fread(&list[i],sizeof(struct student),1,fp);
if(feof(fp)){
clrscr();
gotoxy(20,10);
printf("data loaded.press a key.");
getch();
fclose(fp);
return;
}//end of if
}
fclose(fp);
}

------------------------------

void save(void)
{
FILE *fp;
register int i;
fp=fopen("st.txt","w(wt)");
if(!fp){
printf("\n cannot open file press a key...");
getch();
return;
}
for(i=0;i<SIZE;i++)
if(*list[i].name)
fwrite(&list[i],sizeof(struct student),1,fp);//end of if /end of for
fclose(fp);
clrscr();
gotoxy(20,10);
printf("data saved. prees a key.");
getch();
}

میبینید که به صورت متنی باز و بسته کردم....

کد اصلی و کد ویرایش شده رو هم در پست اول ارائه کردم....

اینم کامپایل شده کد:(ویرایش شده--تا به صورت متنی کار انجام بشه,توضیحات بیشتر

در پست اول):

http://barnamenevis.org/forum/attachment.php?attachmentid=34472&stc=1&d=1249255636