Finding Total Memory in Bytes in C - c

In my assignment I am expected that Print the total memory in bytes required for the dynamic array
I have to read the file and find required byte.
And also it is not my assignment main purpose
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define N 100 //Change this acording to the size of the file.
#define PATH "list.txt"
int * read_array(char *filename,int *count);
int main(void){
int *arr,count;
arr=read_array(PATH,&count);
int byte_used= count * sizeof(int);
printf("%d number of byte used\n",byte_used);
free(arr);
}
int * read_array(char *filename, int *i){
FILE *fp=fopen(filename, "rb");
if (fp==NULL){ printf("File does not exist\n"); *i=0 return 0; }
int a=0,counter=1;
int *arr;
arr=(int*)malloc(counter*N*sizeof(int));
while(fscanf(fp,"%d,",&arr[a]) == 1){
a++;
/* When all allocated memory is filed, do this */
if (counter*N<=a){
counter++;
arr=(int*)realloc(arr,counter*N*sizeof(int));
}
}
*i=a; //returns how many numbers in this file
return arr;
}
So I am wondering in 3rd line in main is valid for expectations or there is another way to find the usage of byte?
Also I will do the same thing with using linked list. So we learning dynamic memory allocation.
little example of list.txt
107557,55092,62318,70428,176047,80485,54378,196442,189223,30437,60540,192159,33269,76106,45347,157100,146714,148826,117640,101563,76183,37355,182131,177126,194497,183527,194987,38558,33858,32845,125977,63521,119818,152605,188990,76983,129104,6248,16584,166616,130089,18922,24273,156750,101204,196746,188582,120890,74983,112513,129785,77139,173710,29203,113654,65771,190139,133410,130882,120492,50775,137392,165089,105591,147175,57138,61213,112020,180819,90229,89965,90348,113128,61010,141313,6982,59301,136882,16740,35281,120563,10840,112388,72077,136377,26905,171965,101848,112372,107374,153418,113139,37599,122005,53904,101215,86164,38777,122907,16655,115439,153224,25420,193267,115505,89156,156848,137102,31725,19419,25086,105131,144132,40022,143155,99377,31892,831,139379,191996,162653,82880,170260,61363,80250,115883,117688,92847,184991,49799,122085,21224,48320,48359,119315,96627,159768,80137,93466,15103,174821,83863,129759,173513,118821,63486,77311,87648,23289,12885,39730,89500,58910,136438,118109,175974,7664,160314,98305,78389,31732,24061,160832,3729,61192,112101,129654,180326,59920,165289,58643,107106,44683,54488,175689,7988,70030,52949,89169,112724,181046,144363,56838,100020,26208,118902,197054,186915,2010,76672,194157,23433,166280,88101,85856,91119,57961,33077,198816,111023,55898,75583,58333,153127,20589,14342,61971,127062,1377,34588,131515,121206,110805,3851,172936,72173,73173,175725,21785,68748,6056,80365,24673,125787,105702,181725,175734,32495,178036,137669,63675,444,164708,191622,156968,62629,131119,84594,8586,124567,116197,75871,49064,1049,27621,108219,16135,176144,43276,198582,117926,33090,128903,70690,11719,43055,42658,46582,150291,14896,138883,44807,83779,26870,192992,183926,54984,165114,138820,139714,20630,85346,16490,96596,111548,138552,159941,48643,160220,149088,126113,173179,79943,7088,187176,36160,53923,111483,91996,38794,78371,148969,43052,56343,32518,1922,64291,23974,191324,1011,182138,197160,154265,15338,140128,76576,51349,150257,149451,5498,184812,178437,56529,179679,158530,165798,141758,84579,188457,7807,154972,51980,78319,13982,131312,143826,143181,33524,15063,81554,15272,124150,28990,168269,40077,112055,1340,90010,144856,152767,131248,59260,73587,36615,36189,167944,145935,68244,180668,35806,4456,152727,57047,120876,41564,193295,176540,168954,23092,28061,1541,58999,115210,97097,148034,54665,102469,152367,56568,145834,33905,44792,173362,16842,78441,174358,34009,174751,114538,122805,167504,179079,58505,28972,164371,136677,39996,179655,24916,199296,189433,108802,183450,136978,109015,167131,29554,12661,68967,189654,27690,45662,149812,48602,17899,130212,102263,89393,133828,178975,52897,120831,32563,95749,109746,184058,197708,140014,164609,145017,103794,98801,148181,102247,55108,128686,75497,127044,185145,66265,67860,140704,10899,114890,103232,12392,116319,180102,132965,146363,177084,191390,190615,44790,51776,31505,135222,12767,113621,40095,73462,142896,152514,

Third line in your code is enough for you, but if you want to make your code better you can something line;
if( a < counter*N ) arr=(int*)realloc( arr, a*sizeof(int) );

According to the question text:
Assignment: Print the total memory in bytes required for the dynamic array
With that assignment you can simplify your code a lot.
Something like:
int getIntsRequired(char *filename)
{
FILE *fp = fopen(filename, "rb");
if (fp == NULL) return 0;
int tmp;
int counter = 0;
while(fscanf(fp, "%d,", &tmp) == 1) ++counter;
fclose(fp);
return counter;
}
size_t getBytesRequired(char *filename)
{
return sizeof(int) * getIntsRequired(filename);
}
int main(void){
size_t bytes_required = getBytesRequired(YOUR_FILE_NAME);
printf("%zu number of byte required\n", bytes_required);
return 0;
}

Related

Trying to copy contens of a file multiple times into another file in c

I am trying to write a program in c that copies the contents of a file into another one multiple times but something is off. Some weird characters appear, and it only copies once.
c code
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
char* laod_with_correct_size(char* file_location, int size) {
char* buffer=NULL;
FILE* file;
size=0;
int len;
file=fopen(file_location,"rb");
if(file==NULL) {
fclose(file);
return NULL;
}
fseek(file,0,SEEK_END);
len=ftell(file);
if(len<1) {
fclose(file);
return NULL;
}
rewind(file);
buffer=(char*) malloc(len);
if(buffer==NULL) {
fclose(file);
return NULL;
}
if(fread(buffer,1,len,file)!=(size_t)len) {
free(buffer);
fclose(file);
return NULL;
}
fclose(file);
size=len;
printf("Size in fucntion is %d\n",len);
return buffer;
}
int get_size(char* filepath) {
FILE* f;
int len;
f=fopen(filepath,"rb");
fseek(f,0,SEEK_END);
len=ftell(f);
fclose(f);
printf("TOTAL SIZE THAT SHOULD BE IN THE FUCNTION IS %d",len);
}
int write_correctly(char* file,char* buffer,int len) {
// printf("len size is %d\n",len);
int file_descriptor = open(file,O_APPEND || O_CREAT);
int len_to_use=get_size(file);
int size=write(file_descriptor,buffer,len_to_use);
printf("Second size in fucntion is %d\n",size);
close(file_descriptor);
printf("SIZE OF SIZE+1 IS %d and SIZE OF LEN IS %d\n",size+1,len);
if(size!=len) {
return-1;
} else {
return size;
}
}
int main(int argc,char** argv) {
int size=0;
size=get_size(argv[1]);
char* buffer=laod_with_correct_size(argv[1],size);
printf("Size of %s is %d\n",argv[1],size);
// if(write_correctly(argv[2],buffer,size)<0) {
// printf("Couldn't write\n");
// }
write_correctly(argv[2],buffer,size);
write_correctly(argv[2],buffer,size);
write_correctly(argv[2],buffer,size);
write_correctly(argv[2],buffer,size);
return 0;
}
first file(to copy from)
salut
buna
alo
second file(to copy to)
salut
buna
alo
\00\00\00\00\00\00\00\00\00Q\F7\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00
My pointers are rusty but I hope I didn't make any huge mistakes.
The function get_size is declared to return a value of type int, but never returns a value.
By using these non-existant return values in the functions main and write_correctly, your program is invoking undefined behavior.
Also, it does not make sense that in the function write_correctly, you are attempting to write an amount of data equal to the size of the already existing output file. Instead, you should always write the size of the buffer, which is supposed to be the size of the input file.
You may find it easier to understand what is going on in your program if you run it line by line in a debugger, while monitoring the values of all variables.

Using malloc, and transferring what's in the allocated memory to a file

so I'm testing out a program that I made and for some reason some things are not working.
Please note that the code that I typed in the first and second problem are not related.
So although the names for some things are the same, they are not in the same .c file, neither do they #include each other
First is this: I FIXED IT!
Second problem is this: I have a for loop that is based on two factors. The first factor affects the value based on the character (reading argv[2]), the second factor affects the value based on how many copies of it self it has. I'm trying to get the data in that for loop into memory, and then from memory to a file.
For some reason, nothing is being transferred into the file.
It looks something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
FILE *filename;
float length, rate, bytesper;
char *data;
data = malloc(sizeof(strlen(argv[2]) * length * rate * bytesper);
if(data == NULL)
{
printf("\nMemory could not be allocated.");
return -1;
}
filename = fopen(argv[1], "wb");
if(filename == NULL)
{
printf("File %s was not created", argv[1]);
return -1;
}
for(size_t i = 0; argv[3][i] != '\0'; i++)//reads each character until NULL
{
for(size_t j = 0;
{
int a[i][j];
a[i][j] = value(argv[3][i], j);
//value is the function I made that takes the character and the j value into account
*ptr = a[i][j] + '0';//did + '0' to make sure the int is converted into char
}
}
if( (fwrite(ptr, sizeof(char), rate*strlen(argv[3])*length, filename)) != rate*strlen(argv[3])*length)
{
printf("\nWas not able to copy data to file.");
}
fclose(filename);
free(ptr);
return 0;
}

fscanf always returns 0(CLOSED)

I am a beginner in C programming, and I am trying to write a simple code to read a text file and write its content into an array, then print it on console. However, I always get 0.0000, and I could not solve the problem.
#include <stdio.h>
#include <stdlib.h>
int numOfLines(FILE *fp1);
void printarr(float arr[], int size);
float *filetoArr(FILE *fp, int arrsize);
int main(int argc, const char *argv[]) {
char *fileName1 = argv[1];
FILE *fp1 = fopen(fileName1, "r");
printf("File name: %s", fileName1);
int size = numOfLines(fp1);
printf("Number of lines in the file: %d\n", size);
float *arr = filetoArr(fp1, size);
printarr(arr, size);
free(arr);
fclose(fp1);
}
void printarr(float *arr, int size) {
for (int i = 0; i < size; i++) {
printf("%f ", *(arr + i));
}
}
float *filetoArr(FILE *fp, int arrsize) {
int size = arrsize;
float *arr = (float *)malloc(sizeof(float) * size);
for (int i = 0; i < size; i++) {
fscanf(fp, "%f\n", (arr+i));
}
return (arr);
}
int numOfLines(FILE *fp1) {
int numberOfLines = 0;
char c;
do {
c = getc(fp1);
if (c == '\n') {
numberOfLines++;
}
} while (c != EOF);
return numberOfLines;
}
your numOfLines goes to the end of the file.
You have to rewind(fp1) to reset your file handle to position 0, or fscanf hits the end of the file, and doesn't read anything (check return code from fscanf: it should be 1 I bet you're getting 0 all the time)
There are multiple problems in your code:
you read the whole file in numOfLines(): you must reset the file pointer to the beginning of file with rewind(fp1); so fscanf() can read the file instead of hitting the end of file immediately.
the variable c used to read bytes from the file must be defined as an int for the test for end of file to be reliable. Otherwise, depending on whether char is signed or not by default, the EOF would never match or could potentially match the character \377 as end of file erroneously.
you do not check for failure to open the file.
Although returning 0 is implicit for function main() since C99, it is advisable to write the return 0; statement explicitly for better clarity.

Confusing yet interesting C behavior while counting size of file

I am writing a very simple C program to count the size of a file. I have a success in counting both text,.odt, and binary files. However, after I made some minor changes in the code I get a different result for .odt and binary files.
This is my code that gives correct results:
while(fgetc(pFile)!=EOF) size++;
And this is the one that gives me different and wrong results for binary and odt files (and I can't understand why it is different?)
size=0;
c=fgetc(pFile);
while(c!=EOF)
{
c=fgetc(pFile);
size++;
}
Note: This code gives correct results for text files though.
This is the overall code (function) :
int count(char * file)
{
int size;
char c;
FILE * pFile;
size=0;
c=' ';
pFile = fopen(file, "rb");
if(!pFile)
{
printf("Invalid file(%s)!\n",file);
exit(EXIT_SUCCESS);
}
c=fgetc(pFile);
while(c!=EOF)
{
c=fgetc(pFile);
size++;
}
// while(fgetc(pFile)!=EOF) size++;
fclose(pFile);
return size;
}
I'm pretty sure it was the declaration of c. Here is some sample code which works.
#include <stdio.h>
#include <errno.h>
int fsize(char *s)
{
FILE *pF = NULL;
int c = 0; /* declaring this as char will bring you funny results */
int iSize = 0;
pF = fopen(s, "r");
if (! pF)
{
perror("Cannot open file");
return -1;
}
fseek(pF, 0, SEEK_SET);
while(EOF != (c = fgetc(pF)))
iSize ++;
fclose(pF);
return iSize;
}
int main(int argc, char **argv)
{
int i;
for(i = 1; argc > i; i ++)
printf("%10d %s\n", fsize(argv[i]), argv[i]);
return 0;
}
I am not sure what do you mean by " count the size of a file".
But if you want the file size,
Following code will do I hope.
#include <sys/stat.h>
struct stat sbuf;
stat(filepath, &sbuf);
printf("%jd\n", (intmax_t)sbuf.st_size);
I believe you are getting the file size a little lesser than the actual size.
The reason i believe causing that is the c=fgetc(pFile); being written twice. One outside while and one inside. The control executes the first c=fgetc(pFile);, goes into while and again inside while executes c=fgetc(pFile); without incrementing size.
size=0;
c=fgetc(pFile);
if(c!=EOF)
{
size++;
}
while(c!=EOF)
{
c=fgetc(pFile);
size++;
}
Here, if the file is empty fgetc will return a EOF. So we increment only if c is returned with a value other than EOF.
This should fix that. Hope this helped.

Converting Greek words to uppercase

I have to create a function that reads a file called grwords.txt containing around 540000 words which are written in Greek letters.
I have to convert these words to uppercase and fill an array called char **words.
This is what I have so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <windows.h>
#include <ctype.h>
void fp();
int main(int argc, char *argv[]) {
SetConsoleOutputCP(1253);
fp();
return 0;
}
void fp(){
char **words;
words = malloc(546490 * sizeof(int *));
for (i = 0; i < 546490; i++)
words[i] = malloc(24 * sizeof(int));
FILE *file;
char *word;
size_t cnt;
file = fopen("grwords.txt", "rt");
if (file == NULL){
printf("File cannot be opened.\n");
exit(1);
}
cnt = 0;
while (1==fscanf(file, "%24s",word)){
if (cnt == 546490)
break;
strcpy(words[cnt++], word);
}
fclose(file);
}
I'm still trying to figure out pointers. I know that & makes a pointer from a value and * a value from a pointer. Updated the program and it successfully fills the array with the words from the file! I still have no idea how to convert Greek lowercase to uppercase.
Handling Greek words can be dependent on your platform.
First of all, you need to understand how file handling works. Here is what I wrote:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define bufSize 1024 // max lenght of word
// we are going to receive the .txt from cmd line
int main(int argc, char *argv[])
{
FILE *fp;
// Assume file has max 10 words
const size_t N = 10;
// Allocate a 2D array of N rows
// and bufSize columns.
// You can think of it like an array
// of N strings, where every string
// has, at most, bufSize length.
char buf[N][bufSize];
// make sure we got the .txt
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
// open the file
if ((fp = fopen(argv[1], "r")) == NULL)
{ /* Open source file. */
perror("fopen source-file");
return 1;
}
// we will use that for toupper()
char c;
// counters
int i = 0, j;
while (fscanf(fp, "%1024s", buf[i]) == 1)
{ /* While we don't reach the end of source. */
/* Read characters from source file to fill buffer. */
// print what we read
printf("%s\n", buf[i]);
j = 0;
// while we are on a letter of word placed
// in buf[i]
while (buf[i][j])
{
// make the letter capital and print it
c = buf[i][j];
putchar (toupper(c));
j++;
}
i++;
printf("\ndone with this word\n");
}
// close the file
fclose(fp);
return 0;
}
For this test.txt file:
Georgios
Samaras
Γιώργος
Σαμαράς
the code would run as:
./exe test.txt
Georgios
GEORGIOS
done with this word
Samaras
SAMARAS
done with this word
Γιώργος
Γιώργος
done with this word
Σαμαράς
Σαμαράς
done with this word
As you can see, I could read the Greek words, but failed to convert them in upper case ones.
Once you got how file handling goes, you need to use wide characters to read a file with Greek words.
So, by just modifying the above code, we get:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>
#define bufSize 1024
int main(int argc, char *argv[])
{
setlocale(LC_CTYPE, "en_GB.UTF-8");
FILE *fp;
const size_t N = 15;
wchar_t buf[N][bufSize];
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("fopen source-file");
return 1;
}
wchar_t c;
int i = 0, j;
while (fwscanf(fp, L"%ls", buf[i]) == 1)
{
wprintf( L"%ls\n\n", buf[i]);
j = 0;
while (buf[i][j])
{
c = buf[i][j];
putwchar (towupper(c));
j++;
}
i++;
wprintf(L"\ndone with this word\n");
}
fclose(fp);
return 0;
}
And now the output is this:
Georgios
GEORGIOS
done with this word
Samaras
SAMARAS
done with this word
Γιώργος
ΓΙΏΡΓΟΣ
done with this word
Σαμαράς
ΣΑΜΑΡΆΣ
done with this word
I see that you may want to create a function which reads the words. If you need a simple example of functions in C, you can visit my pseudo-site here.
As for the 2D array I mentioned above, this picture might help:
where N is the number of rows (equal to 4) and M is the number of columns (equal to 5). In the code above, N is N and M is bufSize. I explain more here, were you can also found code for dynamic allocation of a 2D array.
I know see that you are on Windows. I tested the code in Ubuntu.
For Windows you might want to take a good look at this question.
So, after you read all the above and understand them, you can see what you asked for with dynamic memory management.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>
#define bufSize 1024
wchar_t **get(int N, int M);
void free2Darray(wchar_t** p, int N);
int main(int argc, char *argv[])
{
setlocale(LC_CTYPE, "en_GB.UTF-8");
FILE *fp;
const size_t N = 15;
wchar_t** buf = get(N, bufSize);
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("fopen source-file");
return 1;
}
wchar_t c;
int i = 0, j;
while (fwscanf(fp, L"%ls", buf[i]) == 1)
{
wprintf( L"%ls\n", buf[i]);
j = 0;
while (buf[i][j])
{
c = buf[i][j];
putwchar (towupper(c));
j++;
}
i++;
wprintf(L"\ndone with this word\n");
}
fclose(fp);
// NEVER FORGET, FREE THE DYNAMIC MEMORY
free2Darray(buf, N);
return 0;
}
// We return the pointer
wchar_t **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i;
wchar_t **table;
table = malloc(N*sizeof(wchar_t *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(wchar_t) );
return table;
}
void free2Darray(wchar_t** p, int N)
{
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
Note that this code is expected to work on Linux (tested on Ubuntu 12.04), not on Windows (tested on Win 7).

Resources