我怎样才能使 fread 在 C 中正常工作?它用零填充我的动态数组
How can I make fread work properly in C? It fills my dynamic array with zeroes
我正在编写一个 c 程序,需要读取二进制文件,将其放入结构数组,然后对该数组进行排序。
结构:
#define NCHAR 64
typedef
struct data_
{
char country[NCHAR];
long int population;
float world_share;
}
data;
所有这些都发生在一个单独的函数中,该函数使用 freed()
从文件中获取数组。而这个功能并没有真正起作用。
我希望看到的:
CountryA 100 10%
CountryB 200 20%
我实际得到的是:
0 0 0%
0 0 0%
你能看看我做错了什么吗?我已经尝试重写我的代码并且可以并搜索 fread()
函数的用途,但似乎我使用它是正确的。
void SortAndDisplayASC( void )//main
{
FILE * worldData;
worldData = fopen("world.dat", "rb");
if(worldData == NULL)
{
printf("NO FILE CAN BE ACSESSED\n");
exit(1);
}
long size = fsize(worldData);
int amount = size / sizeof(data);
data * countries;
countries = (data *) malloc(size);
fread(countries, sizeof(data), amount, worldData); //PROBLEM HERE!
sortByPopulation(countries, amount);
for(int i = 0; i < amount; i ++)
{
PrintData(countries[i]);
}
free(countries);
fclose(worldData);
}
如果你愿意帮助我,我会分享整个代码。
Post 脚本:
你好所有碰巧遇到这个问题的人。
在撰写本文时,这是我的 C 作业。
那时我发现并修复了我代码中的错误,但忘了 post 它。
现在我需要 post 一个新问题,这个问题引起了我的注意。这是这个问题的源代码。这个版本应该可以正常工作。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NCHAR 64
#define WPOP 7800000000L
typedef
struct data_
{
char country[NCHAR];
long int population;
float world_share;
}
data;
void menu(int option);
//1st choise
void EnterAndWrite( void );
void ScanData(data * subject);
//2nd choise
void ReadTheCountry( void );
void PrintData(data subject);
//3rd choise
void SortAndDisplayASC( void );
long fsize(FILE * f);
void sortByPopulation(data *array, int n);
void dataArrayItemSwap(data *array, int a, int b);
//4th choise
void SortAndDisplayDSC( void );
void dataArrayFlip(data *array, int length);
//5th choise
void SearchForCountry( void );
void findByName(data * array, int n);
int myStrcmp(char * s1, char * s2);
//6th choise
void CompareDataWithWPOP();
int main(void)
{
int option;
do
{
printf( " (*) Here you will be able do persform several actions over the file world.dat\n\n"
" (*) Enter 1 to enter the data of new country that will be added to file.\n"
" (*) Enter 2 to enter the position of the country in the file that you want to see.\n"
" (*) Enter 3 to show the database sorted by population in asceding order.\n"
" (*) Enter 4 to show the database sorted by population in desceding order.\n"
" (*) Enter 5 to search file for a specific country by its name or it's first lettes.\n"
" (*) Enter 6 to see total population stored in DB and compare it with world population.\n"
" (*) Enter 0 to teminate.\n");
scanf("%d%*c", &option);
menu(option);
}while(option > 0);
return 0;
}
void menu(int option)
{
switch(option)
{
case 1:
{
EnterAndWrite();
break;
}
case 2:
{
ReadTheCountry();
break;
}
case 3:
{
SortAndDisplayASC();
break;
}
case 4:
{
SortAndDisplayDSC();
break;
}
case 5:
{
SearchForCountry();
break;
}
case 6:
{
CompareDataWithWPOP();
break;
}
}
}
//6th choise
void CompareDataWithWPOP()
{
FILE * worldData;
worldData = fopen("world.dat", "rb");
if(worldData == NULL)
{
printf("NO FILE CAN BE ACSESSED\n");
exit(1);
}
long size = fsize(worldData);
int amount = size / sizeof(data);
data * countries;
countries = (data *) malloc(size);
fread(countries, sizeof(data), amount, worldData);
long int sum = 0;
for(int i = 0; i < amount; i ++)
{
sum += countries[i].population;
}
float share = (float)sum / WPOP;
printf("%ld %.2f%%\n", sum, share*100);
free(countries);
fclose(worldData);
}
//5th choise
void SearchForCountry( void )
{
FILE * worldData;
worldData = fopen("world.dat", "rb");
if(worldData == NULL)
{
printf("NO FILE CAN BE ACSESSED\n");
exit(1);
}
long size = fsize(worldData);
int amount = size / sizeof(data);
data * countries;
countries = (data *) malloc(size);
fread(countries, sizeof(data), amount, worldData);
findByName(countries, amount);
free(countries);
fclose(worldData);
}
void findByName(data * array, int n)
{
char request[NCHAR];
fgets(request, NCHAR-1, stdin);
request[strlen(request)-1] = '[=14=]';
for(int i = 0; i < n; i ++)
{
if(myStrcmp(request, array[i].country) == 0)
{
PrintData(array[i]);
}
}
}
int myStrcmp(char * s1, char * s2)
{
int n = (strlen(s1) < strlen(s2)) ? strlen(s1) : strlen(s2);
char *temp = (char *) calloc(n+1, 1);
for(int i = 0; i < n; i ++)
{
temp[i] = (strlen(s1) > strlen(s2)) ? s1[i] : s2[i];
}
return (strlen(s1) > strlen(s2)) ? strcmp(temp, s2) : strcmp(s1, temp);
}
//4th choise
void SortAndDisplayDSC( void )//main
{
FILE * worldData;
worldData = fopen("world.dat", "rb");
if(worldData == NULL)
{
printf("NO FILE CAN BE ACSESSED\n");
exit(1);
}
long size = fsize(worldData);
int amount = size / sizeof(data);
data * countries;
countries = (data *) malloc(size);
fread(countries, sizeof(data), amount, worldData); //PROBLEM HERE!
sortByPopulation(countries, amount);
dataArrayFlip(countries, amount);
for(int i = 0; i < amount; i ++)
{
PrintData(countries[i]);
}
free(countries);
fclose(worldData);
}
void dataArrayFlip(data *array, int length)
{
data * temp;
temp = (data *) calloc(length, sizeof(data));
for(int i = 0; i < length; i++) temp[i] = array[(length - i) - 1];
for(int i = 0; i < length; i++) array[i] = temp[i];
free(temp);
}
//3rd choise
void SortAndDisplayASC( void )//main
{
FILE * worldData;
worldData = fopen("world.dat", "rb");
if(worldData == NULL)
{
printf("NO FILE CAN BE ACSESSED\n");
exit(1);
}
long size = fsize(worldData);
int amount = size / sizeof(data);
data * countries;
countries = (data *) malloc(size);
fread(countries, sizeof(data), amount, worldData); //PROBLEM HERE!(no problem now)
sortByPopulation(countries, amount);
for(int i = 0; i < amount; i ++)
{
PrintData(countries[i]);
}
free(countries);
fclose(worldData);
}
long fsize(FILE * f)
{
long lenght;
fseek(f, 0, SEEK_END);
lenght = ftell(f);
fseek(f, 0, SEEK_SET);
return lenght;
}
void sortByPopulation(data *array, int n)
{
//sorts countries in asceding order by population
for(int i = 0; i < n-1; i ++)
{
for(int j = i+1; j < n; j ++)
{
if(array[i].population > array[j].population)
{
dataArrayItemSwap(array, i, j);
}
}
}
}
void dataArrayItemSwap(data *array, int a, int b)
{
//changes places of 2 items in an array
data temp = array[b];
array[b] = array[a];
array[a] = temp;
}
//2nd choise
void ReadTheCountry( void )//main
{
FILE * worldData;
worldData = fopen("world.dat", "rb");
//test if file is a true thing
if(worldData == NULL)
{
printf("NO FILE CAN BE ACSESSED\n");
exit(1);
}
int n;
//get the country number to read(start form 0)
scanf("%d%*c", &n);
//caculating the position
int offset = sizeof(data) * n;
//moving to that position
fseek(worldData, offset, SEEK_SET);
data Country;
//reading data form that position
fread(&Country, sizeof(data), 1, worldData);
PrintData(Country);
fclose(worldData);
}
void PrintData(data subject)
{
//prints name, population and world share and starts a new line
printf("%-16s\t%10ld\t\t%5.2f%%\n", subject.country, subject.population, subject.world_share * 100);
}
//1st choise
void EnterAndWrite( void )//main
{
FILE * worldData;
worldData = fopen("world.dat", "ab");
//test if file can be acsessed
if(worldData == NULL)
{
printf("NO FILE CAN BE ACSESSED\n");
exit(1);
}
//get data to append the file
data Country;
ScanData(&Country);
//go to the end of file
fseek(worldData, 0, SEEK_END);
fwrite(&Country, sizeof(data), 1, worldData);
fclose(worldData);
}
void ScanData(data * subject)
{
//get name
fgets(subject->country, NCHAR-1, stdin);
subject->country[strlen(subject->country)-1] = '[=14=]';
//get population
scanf("%ld%*c", &subject->population);
//find world share
subject->world_share = (float)subject->population / WPOP;
//end of the function;
}
这段代码使用 world.dat 文件,其中描述国家的结构以二进制形式保存。我已经将它转换为 base64,你可以随意构造它。
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
原始文件的MD5:
c2c0571518b47973f719f5dba96621dc
原始文件的 SHA256:
10ba4a9bc275b2c12f1b1f52fefc124d83df4485fe24c40ffcf5ca97830f1721
因此,据我所知,fsize 函数中存在一个错误,在一个奇怪的情况下会返回错误的文件大小。这个版本应该没有bug。
感谢所有试图帮助我的人!
由于您没有完整的代码和数据:我重新创建了程序的缺失部分,并在代码中添加了一些注释以方便代码审查:
- 从用户那里收到示例数据(5 条记录),
- 将其写入二进制文件 (world.dat),
- 从文件中读取数据,
- 排序
按人口统计数据并列出。
它在我的机器 (gcc - Wall) 上编译 运行 很好,你可以浏览它并与你的代码进行比较;希望这对你有帮助。
排序后程序输出如下:
Sort is completed successfully using bubble-sorting technique!
Country: D - Population: 5 - World Share: 2 %
Country: C - Population: 20 - World Share: 8 %
Country: A - Population: 50 - World Share: 20 %
Country: E - Population: 80 - World Share: 31 %
Country: B - Population: 100 - World Share: 39 %
请注意,如果您的数据文件未准确反映结构,则不会生成正确的数据。
/** by: moemen.ahmed
* date: 16 May 20
* reference to Whosebug:
* purpose: collect and store countires population input in a binary file, then re-read the file, and sort it by population.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NCHAR 64
// define the main Country struct
typedef
struct Country_
{
char country[NCHAR];
long int population;
float world_share;
}
Country;
// store countries count in a global variable
int count = 0;
// store total population in a global variable
long int totalPopulation = 0;
// declare a global pointer that will point to the start of data-blocks
// functions declaration
// receives the user input and store it in memory
void addCountry();
// update the world_share% in each of the structs in memory
void updateWorldShare();
// list countries data from memory
void listCountries();
// write the list of countries to the file world.dat
void writeCountries();
// read the data from the file to memory
void readCountries ();
// calculate the number of records in the file; update the global variable 'count'
int fsize(FILE* file);
// sort the records in the memory
void sortCountriesByPopulation();
// main function
int main(int argc, char **argv) {
int x = 0;
while (x < 5) {
addCountry();
x += 1;
}
updateWorldShare();
listCountries();
writeCountries();
// let us reset the data, so everything comes from reading the file afterwards.
free(countries);
totalPopulation = 0;
count = 0;
// read the binary file
readCountries();
sortCountriesByPopulation();
listCountries();
free(countries);
return 0;
}
void listCountries(){
// int count = getCountriesCount();
Country* currCountry;
for (int i = 0; i < count; i++)
{
currCountry = countries + (i * sizeof(Country));
printf("Country: %s - Population: %ld - World Share: %0.00f %%\n", currCountry->country, (long int) currCountry->population, (float) currCountry->world_share * 100);
}
return;
}
void addCountry()
{
Country new;
printf("Enter Country Name.");
scanf("%s", new.country);
printf("Enter Population.");
scanf("%ld", &new.population);
// ignore calculating world-share% during input.
new.world_share = 0.0;
countries = (Country *) realloc( countries, (count + 1) * sizeof(Country));
*(countries + (count ) * sizeof(Country)) = new;
// update the goabl count and totalPopulation
totalPopulation += new.population;
count += 1;
return ;
}
void updateWorldShare(long int population){
printf("... updadting world share %% \n");
printf("... total population : %ld\n", (long int) totalPopulation);
Country* currCountry;
for (int i = 0; i < count; i++) {
currCountry = countries + (i * sizeof(Country));
currCountry->world_share = ((float) currCountry->population )/ ((float) totalPopulation);
}
return;
}
void updateTotalPopulation(){
printf("... updadting TotalPopulation\n");
totalPopulation = 0;
Country* currCountry;
for (int i = 0; i < count; i++) {
currCountry = countries + (i * sizeof(Country));
totalPopulation += currCountry->population;
}
printf("... total population : %ld\n", (long int) totalPopulation);
return;
}
void sortCountriesByPopulation(){
printf("... sorting countries by population, Count: %d\n", count);
Country *xCountry, *yCountry;
for (int i = 0; i < (count - 1); i++) {
for (int j = 0; j < (count - 1 - i ); j++) {
xCountry = countries + (j * sizeof(Country));
yCountry = countries + ((j+1) * sizeof(Country));
if (xCountry->population > yCountry->population){
// do a swap
Country tempCountry;
tempCountry = *xCountry;
*xCountry = *yCountry;
*yCountry = tempCountry;
}
}
}
printf("Sort is completed successfully using bubble-sorting technique!\n");
return;
}
void readCountries(void)//main
{
printf("reading ...... \n");
FILE * worldData;
worldData = fopen("world.dat", "rb");
if(worldData == NULL)
{
printf("NO FILE CAN BE ACSESSED\n");
exit(1);
}
long size = fsize(worldData);
count = size / sizeof(Country);
Country * countries;
countries = (Country *) malloc(size);
fread(countries, sizeof(Country), count, worldData);
fclose(worldData);
updateTotalPopulation();
return;
}
int fsize(FILE* file) {
fseek(file, 0L, SEEK_END);
int size = ftell(file);
fseek(file, 0L, SEEK_SET);
return size;
}
void writeCountries( void)
{
FILE * worldData;
worldData = fopen("world.dat", "wb");
fwrite(countries, sizeof(Country), count, worldData);
fclose(worldData);
}
我正在编写一个 c 程序,需要读取二进制文件,将其放入结构数组,然后对该数组进行排序。 结构:
#define NCHAR 64
typedef
struct data_
{
char country[NCHAR];
long int population;
float world_share;
}
data;
所有这些都发生在一个单独的函数中,该函数使用 freed()
从文件中获取数组。而这个功能并没有真正起作用。
我希望看到的:
CountryA 100 10%
CountryB 200 20%
我实际得到的是:
0 0 0%
0 0 0%
你能看看我做错了什么吗?我已经尝试重写我的代码并且可以并搜索 fread()
函数的用途,但似乎我使用它是正确的。
void SortAndDisplayASC( void )//main
{
FILE * worldData;
worldData = fopen("world.dat", "rb");
if(worldData == NULL)
{
printf("NO FILE CAN BE ACSESSED\n");
exit(1);
}
long size = fsize(worldData);
int amount = size / sizeof(data);
data * countries;
countries = (data *) malloc(size);
fread(countries, sizeof(data), amount, worldData); //PROBLEM HERE!
sortByPopulation(countries, amount);
for(int i = 0; i < amount; i ++)
{
PrintData(countries[i]);
}
free(countries);
fclose(worldData);
}
如果你愿意帮助我,我会分享整个代码。
Post 脚本:
你好所有碰巧遇到这个问题的人。 在撰写本文时,这是我的 C 作业。 那时我发现并修复了我代码中的错误,但忘了 post 它。 现在我需要 post 一个新问题,这个问题引起了我的注意。这是这个问题的源代码。这个版本应该可以正常工作。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NCHAR 64
#define WPOP 7800000000L
typedef
struct data_
{
char country[NCHAR];
long int population;
float world_share;
}
data;
void menu(int option);
//1st choise
void EnterAndWrite( void );
void ScanData(data * subject);
//2nd choise
void ReadTheCountry( void );
void PrintData(data subject);
//3rd choise
void SortAndDisplayASC( void );
long fsize(FILE * f);
void sortByPopulation(data *array, int n);
void dataArrayItemSwap(data *array, int a, int b);
//4th choise
void SortAndDisplayDSC( void );
void dataArrayFlip(data *array, int length);
//5th choise
void SearchForCountry( void );
void findByName(data * array, int n);
int myStrcmp(char * s1, char * s2);
//6th choise
void CompareDataWithWPOP();
int main(void)
{
int option;
do
{
printf( " (*) Here you will be able do persform several actions over the file world.dat\n\n"
" (*) Enter 1 to enter the data of new country that will be added to file.\n"
" (*) Enter 2 to enter the position of the country in the file that you want to see.\n"
" (*) Enter 3 to show the database sorted by population in asceding order.\n"
" (*) Enter 4 to show the database sorted by population in desceding order.\n"
" (*) Enter 5 to search file for a specific country by its name or it's first lettes.\n"
" (*) Enter 6 to see total population stored in DB and compare it with world population.\n"
" (*) Enter 0 to teminate.\n");
scanf("%d%*c", &option);
menu(option);
}while(option > 0);
return 0;
}
void menu(int option)
{
switch(option)
{
case 1:
{
EnterAndWrite();
break;
}
case 2:
{
ReadTheCountry();
break;
}
case 3:
{
SortAndDisplayASC();
break;
}
case 4:
{
SortAndDisplayDSC();
break;
}
case 5:
{
SearchForCountry();
break;
}
case 6:
{
CompareDataWithWPOP();
break;
}
}
}
//6th choise
void CompareDataWithWPOP()
{
FILE * worldData;
worldData = fopen("world.dat", "rb");
if(worldData == NULL)
{
printf("NO FILE CAN BE ACSESSED\n");
exit(1);
}
long size = fsize(worldData);
int amount = size / sizeof(data);
data * countries;
countries = (data *) malloc(size);
fread(countries, sizeof(data), amount, worldData);
long int sum = 0;
for(int i = 0; i < amount; i ++)
{
sum += countries[i].population;
}
float share = (float)sum / WPOP;
printf("%ld %.2f%%\n", sum, share*100);
free(countries);
fclose(worldData);
}
//5th choise
void SearchForCountry( void )
{
FILE * worldData;
worldData = fopen("world.dat", "rb");
if(worldData == NULL)
{
printf("NO FILE CAN BE ACSESSED\n");
exit(1);
}
long size = fsize(worldData);
int amount = size / sizeof(data);
data * countries;
countries = (data *) malloc(size);
fread(countries, sizeof(data), amount, worldData);
findByName(countries, amount);
free(countries);
fclose(worldData);
}
void findByName(data * array, int n)
{
char request[NCHAR];
fgets(request, NCHAR-1, stdin);
request[strlen(request)-1] = '[=14=]';
for(int i = 0; i < n; i ++)
{
if(myStrcmp(request, array[i].country) == 0)
{
PrintData(array[i]);
}
}
}
int myStrcmp(char * s1, char * s2)
{
int n = (strlen(s1) < strlen(s2)) ? strlen(s1) : strlen(s2);
char *temp = (char *) calloc(n+1, 1);
for(int i = 0; i < n; i ++)
{
temp[i] = (strlen(s1) > strlen(s2)) ? s1[i] : s2[i];
}
return (strlen(s1) > strlen(s2)) ? strcmp(temp, s2) : strcmp(s1, temp);
}
//4th choise
void SortAndDisplayDSC( void )//main
{
FILE * worldData;
worldData = fopen("world.dat", "rb");
if(worldData == NULL)
{
printf("NO FILE CAN BE ACSESSED\n");
exit(1);
}
long size = fsize(worldData);
int amount = size / sizeof(data);
data * countries;
countries = (data *) malloc(size);
fread(countries, sizeof(data), amount, worldData); //PROBLEM HERE!
sortByPopulation(countries, amount);
dataArrayFlip(countries, amount);
for(int i = 0; i < amount; i ++)
{
PrintData(countries[i]);
}
free(countries);
fclose(worldData);
}
void dataArrayFlip(data *array, int length)
{
data * temp;
temp = (data *) calloc(length, sizeof(data));
for(int i = 0; i < length; i++) temp[i] = array[(length - i) - 1];
for(int i = 0; i < length; i++) array[i] = temp[i];
free(temp);
}
//3rd choise
void SortAndDisplayASC( void )//main
{
FILE * worldData;
worldData = fopen("world.dat", "rb");
if(worldData == NULL)
{
printf("NO FILE CAN BE ACSESSED\n");
exit(1);
}
long size = fsize(worldData);
int amount = size / sizeof(data);
data * countries;
countries = (data *) malloc(size);
fread(countries, sizeof(data), amount, worldData); //PROBLEM HERE!(no problem now)
sortByPopulation(countries, amount);
for(int i = 0; i < amount; i ++)
{
PrintData(countries[i]);
}
free(countries);
fclose(worldData);
}
long fsize(FILE * f)
{
long lenght;
fseek(f, 0, SEEK_END);
lenght = ftell(f);
fseek(f, 0, SEEK_SET);
return lenght;
}
void sortByPopulation(data *array, int n)
{
//sorts countries in asceding order by population
for(int i = 0; i < n-1; i ++)
{
for(int j = i+1; j < n; j ++)
{
if(array[i].population > array[j].population)
{
dataArrayItemSwap(array, i, j);
}
}
}
}
void dataArrayItemSwap(data *array, int a, int b)
{
//changes places of 2 items in an array
data temp = array[b];
array[b] = array[a];
array[a] = temp;
}
//2nd choise
void ReadTheCountry( void )//main
{
FILE * worldData;
worldData = fopen("world.dat", "rb");
//test if file is a true thing
if(worldData == NULL)
{
printf("NO FILE CAN BE ACSESSED\n");
exit(1);
}
int n;
//get the country number to read(start form 0)
scanf("%d%*c", &n);
//caculating the position
int offset = sizeof(data) * n;
//moving to that position
fseek(worldData, offset, SEEK_SET);
data Country;
//reading data form that position
fread(&Country, sizeof(data), 1, worldData);
PrintData(Country);
fclose(worldData);
}
void PrintData(data subject)
{
//prints name, population and world share and starts a new line
printf("%-16s\t%10ld\t\t%5.2f%%\n", subject.country, subject.population, subject.world_share * 100);
}
//1st choise
void EnterAndWrite( void )//main
{
FILE * worldData;
worldData = fopen("world.dat", "ab");
//test if file can be acsessed
if(worldData == NULL)
{
printf("NO FILE CAN BE ACSESSED\n");
exit(1);
}
//get data to append the file
data Country;
ScanData(&Country);
//go to the end of file
fseek(worldData, 0, SEEK_END);
fwrite(&Country, sizeof(data), 1, worldData);
fclose(worldData);
}
void ScanData(data * subject)
{
//get name
fgets(subject->country, NCHAR-1, stdin);
subject->country[strlen(subject->country)-1] = '[=14=]';
//get population
scanf("%ld%*c", &subject->population);
//find world share
subject->world_share = (float)subject->population / WPOP;
//end of the function;
}
这段代码使用 world.dat 文件,其中描述国家的结构以二进制形式保存。我已经将它转换为 base64,你可以随意构造它。
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
原始文件的MD5:
c2c0571518b47973f719f5dba96621dc
原始文件的 SHA256:
10ba4a9bc275b2c12f1b1f52fefc124d83df4485fe24c40ffcf5ca97830f1721
因此,据我所知,fsize 函数中存在一个错误,在一个奇怪的情况下会返回错误的文件大小。这个版本应该没有bug。
感谢所有试图帮助我的人!
由于您没有完整的代码和数据:我重新创建了程序的缺失部分,并在代码中添加了一些注释以方便代码审查:
- 从用户那里收到示例数据(5 条记录),
- 将其写入二进制文件 (world.dat),
- 从文件中读取数据,
- 排序 按人口统计数据并列出。
它在我的机器 (gcc - Wall) 上编译 运行 很好,你可以浏览它并与你的代码进行比较;希望这对你有帮助。
排序后程序输出如下:
Sort is completed successfully using bubble-sorting technique!
Country: D - Population: 5 - World Share: 2 %
Country: C - Population: 20 - World Share: 8 %
Country: A - Population: 50 - World Share: 20 %
Country: E - Population: 80 - World Share: 31 %
Country: B - Population: 100 - World Share: 39 %
请注意,如果您的数据文件未准确反映结构,则不会生成正确的数据。
/** by: moemen.ahmed
* date: 16 May 20
* reference to Whosebug:
* purpose: collect and store countires population input in a binary file, then re-read the file, and sort it by population.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NCHAR 64
// define the main Country struct
typedef
struct Country_
{
char country[NCHAR];
long int population;
float world_share;
}
Country;
// store countries count in a global variable
int count = 0;
// store total population in a global variable
long int totalPopulation = 0;
// declare a global pointer that will point to the start of data-blocks
// functions declaration
// receives the user input and store it in memory
void addCountry();
// update the world_share% in each of the structs in memory
void updateWorldShare();
// list countries data from memory
void listCountries();
// write the list of countries to the file world.dat
void writeCountries();
// read the data from the file to memory
void readCountries ();
// calculate the number of records in the file; update the global variable 'count'
int fsize(FILE* file);
// sort the records in the memory
void sortCountriesByPopulation();
// main function
int main(int argc, char **argv) {
int x = 0;
while (x < 5) {
addCountry();
x += 1;
}
updateWorldShare();
listCountries();
writeCountries();
// let us reset the data, so everything comes from reading the file afterwards.
free(countries);
totalPopulation = 0;
count = 0;
// read the binary file
readCountries();
sortCountriesByPopulation();
listCountries();
free(countries);
return 0;
}
void listCountries(){
// int count = getCountriesCount();
Country* currCountry;
for (int i = 0; i < count; i++)
{
currCountry = countries + (i * sizeof(Country));
printf("Country: %s - Population: %ld - World Share: %0.00f %%\n", currCountry->country, (long int) currCountry->population, (float) currCountry->world_share * 100);
}
return;
}
void addCountry()
{
Country new;
printf("Enter Country Name.");
scanf("%s", new.country);
printf("Enter Population.");
scanf("%ld", &new.population);
// ignore calculating world-share% during input.
new.world_share = 0.0;
countries = (Country *) realloc( countries, (count + 1) * sizeof(Country));
*(countries + (count ) * sizeof(Country)) = new;
// update the goabl count and totalPopulation
totalPopulation += new.population;
count += 1;
return ;
}
void updateWorldShare(long int population){
printf("... updadting world share %% \n");
printf("... total population : %ld\n", (long int) totalPopulation);
Country* currCountry;
for (int i = 0; i < count; i++) {
currCountry = countries + (i * sizeof(Country));
currCountry->world_share = ((float) currCountry->population )/ ((float) totalPopulation);
}
return;
}
void updateTotalPopulation(){
printf("... updadting TotalPopulation\n");
totalPopulation = 0;
Country* currCountry;
for (int i = 0; i < count; i++) {
currCountry = countries + (i * sizeof(Country));
totalPopulation += currCountry->population;
}
printf("... total population : %ld\n", (long int) totalPopulation);
return;
}
void sortCountriesByPopulation(){
printf("... sorting countries by population, Count: %d\n", count);
Country *xCountry, *yCountry;
for (int i = 0; i < (count - 1); i++) {
for (int j = 0; j < (count - 1 - i ); j++) {
xCountry = countries + (j * sizeof(Country));
yCountry = countries + ((j+1) * sizeof(Country));
if (xCountry->population > yCountry->population){
// do a swap
Country tempCountry;
tempCountry = *xCountry;
*xCountry = *yCountry;
*yCountry = tempCountry;
}
}
}
printf("Sort is completed successfully using bubble-sorting technique!\n");
return;
}
void readCountries(void)//main
{
printf("reading ...... \n");
FILE * worldData;
worldData = fopen("world.dat", "rb");
if(worldData == NULL)
{
printf("NO FILE CAN BE ACSESSED\n");
exit(1);
}
long size = fsize(worldData);
count = size / sizeof(Country);
Country * countries;
countries = (Country *) malloc(size);
fread(countries, sizeof(Country), count, worldData);
fclose(worldData);
updateTotalPopulation();
return;
}
int fsize(FILE* file) {
fseek(file, 0L, SEEK_END);
int size = ftell(file);
fseek(file, 0L, SEEK_SET);
return size;
}
void writeCountries( void)
{
FILE * worldData;
worldData = fopen("world.dat", "wb");
fwrite(countries, sizeof(Country), count, worldData);
fclose(worldData);
}