using while loop does not save data to file in c - c

I want take input from user and then save that input into the file. In my below code if I remove my while loop then the file is appended but I want this loop so that user can enter data upto 500 characters.
int main()
{
char Buffer1[5];
FILE *ot;
fopen_s(&ot, "D:\\export1.txt", "a+");
fseek(ot, 0L, SEEK_END);
int sz = ftell(ot);
printf("Enter Data.\n");
while (sz<500) {
for (int i = 0; i < 5; i++) {
scanf_s("%c", &Buffer1[i]);
}
// write data to file
for (int i = 0; i < 5; i++) {
fputc(Buffer1[i], ot);
}
sz = ftell(ot);
}
fclose(ot);
_gettch();
return 0;
}

This implementation only works if the user appends exactly the amount of bytes necessary to make 500 bytes in total.
It might be easier to first check the filesize, then let the user enter at most 500 - filesize characters, and only after that append the userinput to the file.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <conio.h>
#define ARRAY_LIMIT 10
int main()
{
char array[ARRAY_LIMIT];
int i = 0;
FILE *ot;
fopen_s(&ot, "export1.txt", "a+");
fseek(ot, 0L, SEEK_END);
int sz = ftell(ot);
printf("Enter Data.\n");
while (sz < 500)
{
while (i < ARRAY_LIMIT)
{
array[i] = getch();
printf("%c", array[i++]);
}
i = 0;
fwrite(array, sizeof(array), 1, ot);
sz = ftell(ot);
//be on the safe side...
if (sz != 500 && 500 - sz < ARRAY_LIMIT)
i = ARRAY_LIMIT - (500 - sz);
}
fclose(ot);
return 0;
}

Related

remove() function doesn't work as expected

I am working with a code that generates a fixed number of files and keeps that number. After every new file is created, an old one has to be deleted. This is the code:
#include <stdio.h>
#include <stdlib.h> // needed for malloc
#include <string.h> // needed for strcpy
#include <unistd.h>
#define Extension ".txt"
#define LOG_MIN_FILENAME_SIZE 32
#define NBR_OF_FILES 6
char buffer[LOG_MIN_FILENAME_SIZE];
int timez = 0;
int minutes = 0;
int count = 0;
FILE* pf = NULL;
char* ListOfFiles[6];
int main(void)
{
for (int i = 0; i < 3; i++) {
ListOfFiles[i] = calloc(LOG_MIN_FILENAME_SIZE + 1, 1);
}
for (int i = 0; i < 10; i++) {
sprintf(buffer, "%d" "%d" Extension, minutes, timez);
if (access(buffer, F_OK) == -1) {
pf = fopen(buffer, "w"); // create the file
count++;
fclose(pf); //closing the files is necessary
if (count >= NBR_OF_FILES) {
remove(ListOfFiles[0]); //remove the oldes file.
}
for (int i = 0; i < NBR_OF_FILES - 1; i++) {
strcpy(ListOfFiles[i], ListOfFiles[i + 1]); // u cant use just normal assignment because it copies the head ot the pointer rather than the actual content of it
}
strcpy(ListOfFiles[NBR_OF_FILES - 1], buffer);
}
timez++;
minutes++;
}
for (int i = 0; i < NBR_OF_FILES - 1; i++) {
printf("%s", ListOfFiles[i]);
}
}
In the output, I get only one file created at a time (with every execution). When I execute the program more than NBR_OF_FILE times, no files are deleted! Do you have any idea that what the issue could be?

Printing randomly to the screen in C

I am trying to print to the screen randomly in C. I am using random and time to generate random index and printing it but It definetely is not the way to do it. How do I print every element randomly to the screen in c?
Here is the code I have so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define leng 128
#define arr 10
int main(void)
{
char line[arr][leng];
char fname[20];
FILE *fptr = NULL;
int i = 0;
int tot = 0;
scanf("%s",fname);
fptr = fopen(fname, "r");
while(fgets(line[i], leng, fptr))
{
line[i][strlen(line[i]) - 1] = '\0';
i++;
}
srand(time(0));
for(int i = 0; i < 6; ++i)
{
printf("%s\n", line[rand()%10]);
}
return 0;
}
My random text file has 6 lines of code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define LEN 128 //Don't mind the capital, personal preference for defines
#define ARR 6 //Make this match the number of lines in your file
int main(void)
{
char line[ARR][LEN];
char fname[20];
int test[ARR] = {0}; //Added an array to test if index already created
int ind[ARR] = {0}; //Array to store index created randomly
int ind_done = 0; //Counter for index array
FILE *fptr = NULL;
int i = 0;
int tot = 0;
scanf("%s",fname);
fptr = fopen(fname, "r");
while(fgets(line[i], LEN, fptr))
{
line[i][strlen(line[i]) - 1] = '\0';
i++;
}
srand(time(0));
for(int i = 0; i < ARR; ++i)
{
printf("%s\n", line[rand()%ARR]);
}
//Keep creating indexes using rand till all unique indexes are created
while (ind_done<ARR) {
int i = rand()%ARR;
if (test[i] == 0) {
ind[ind_done] = i;
ind_done++;
test[i] = 1;
}
}
for(int i = 0; i < ARR; ++i)
{
printf("%s\n", line[ind[i]]);
}
return 0;
}

Reading in Large Integer txt file into 2D array

Attempting to create a program that reasons in a large Text File and filled them into Rows + Columns. Eventually I'll have to computer best path but having trouble just implementing an Array that can store the values.
#include <stdio.h>
#include <stdlib.h>
//max number of characters to read in a line. //MAXN=5 means 4 chars are read, then a \0 added in fgets. See reference for functionality
#define MAXN 100L
int main(void) //char** argv also ok {
int i=0, totalNums, totalNum,j=0;
size_t count;
int numbers[100][100];
char *line = malloc(100);
FILE* inFile ;
inFile = fopen("Downloads/readTopoData/topo983by450.txt", "r"); //open a file from user for reading
if( inFile == NULL) { // should print out a reasonable message of failure here
printf("no bueno \n");
exit(1);
}
while(getline(&line,&count, inFile)!=-1) {
for(;count>0; count--,j++)
sscanf(line, "%d", &numbers[i][j]);
i++;
}
totalNums = i;
totalNum = j;
for(i=0;i<totalNums; i++){
for(j=0;j<totalNum;j++){
printf("\n%d", numbers[i][j]);
}
}
fclose(inFile);
return 0;
}
count does not tell you how many numbers there are. Further: sscanf(line, "%d", &numbers[i][j]); will just scan the same number every time.
So this
for(;count>0; count--,j++)
sscanf(line, "%d", &numbers[i][j]);
should be something like:
j = 0;
int x = 0;
int t;
while(sscanf(line + x, "%d%n", &numbers[i][j], &t) == 1)
{
x += t;
++j;
}
where x together with %n helps you move to a new position in the string when a number has been scanned.
Here is a simplified version that scans for numbers in a string:
#include <stdio.h>
int main(void) {
char line[] = "10 20 30 40";
int numbers[4];
int j = 0;
int x = 0;
int t;
while(j < 4 && sscanf(line + x, "%d%n", &numbers[j], &t) == 1)
{
x += t;
++j;
}
for(t=0; t<j; ++t) printf("%d\n", numbers[t]);
return 0;
}
Output:
10
20
30
40

Read a txt file with gets in C

I want to know what is the best option to read a txt file that contain two line of numbers using gets function in c and save them in an array within 1 second.
Assume the following example as an txt file called ooo.txt and it has the number 2.000.000 in the first line (which will be the size of the array) and 2.000.000 number in the second line that will be stored in the array.
Eg
2000000
59 595 45 492 89289 5 8959 (+1.999.993 numbers)
code i try (only the fcanf function)
int t_size;
fscanf(fp, "%d",&t_size); //bypass the first character!
int* my_array = NULL;
my_array = malloc(t_size*sizeof(*my_array));
if (my_array==NULL) {
printf("Error allocating memory!\n"); //print an error message
return 1; //return with failure
getchar();
}
int i =0;
for ( i = 0; i < t_size; i++ )
{
fscanf(fp, "%d",&my_array[i]); /*p[i] is the content of element at index i and &p[i] is the address of element at index i */
}
best, so far, code to make the procedure in 1 second
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <time.h>
int is_end(char* input) {
return *input == 0;
}
int is_linebreak(char* input) {
return *input == '\r' || *input == '\n' || *input == ' ';
}
char* eat_linebreaks(char* input) {
while (is_linebreak(input))
++input;
return input;
}
size_t count_lines(char* input) {
char* p = input;
size_t rows = 1;
if (is_end(p))
return 0;
while (!is_end(p)) {
if (is_linebreak(p)) {
++rows;
p = eat_linebreaks(p);
}
else {
++p;
}
}
return rows;
}
/* split string by lines */
char** get_lines(char* input, size_t line_count) {
char* p = input;
char* from = input;
size_t length = 0;
size_t line = 0;
int i;
char** lines = (char**)malloc(line_count * sizeof(char*));
do {
if (is_end(p) || is_linebreak(p)) {
lines[line] = (char*)malloc(length + 1);
for (i = 0; i < length; ++i)
lines[line][i] = *(from + i);
lines[line][length] = 0;
length = 0;
++line;
p = eat_linebreaks(p);
from = p;
}
else {
++length;
++p;
}
} while (!is_end(p));
// Copy the last line as well in case the input doesn't end in line-break
lines[line] = (char*)malloc(length + 1);
for (i = 0; i < length; ++i)
lines[line][i] = *(from + i);
lines[line][length] = 0;
++line;
return lines;
}
int main(int argc, char* argv[]) {
clock_t start;
unsigned long microseconds;
float seconds;
char** lines;
size_t size;
size_t number_of_rows;
int count;
int* my_array;
start = clock();
FILE *stream;
char *contents;
int fileSize = 0;
int i;
// Open file, find the size of it
stream = fopen(argv[1], "rb");
fseek(stream, 0L, SEEK_END);
fileSize = ftell(stream);
fseek(stream, 0L, SEEK_SET);
// Allocate space for the entire file content
contents = (char*)malloc(fileSize + 1);
// Stream file into memory
size = fread(contents, 1, fileSize, stream);
contents[size] = 0;
fclose(stream);
// Count rows in content
number_of_rows = count_lines(contents);
// Get array of char*, one for each line
lines = get_lines(contents, number_of_rows);
// Get the numbers out of the lines
count = atoi(lines[0]); // First row has count
my_array = (int*)malloc(count * sizeof(int));
for (i = 0; i < count; ++i) {
my_array[i] = atoi(lines[i + 1]);
}
microseconds = clock() - start;
seconds = microseconds / 1000000.0f;
printf("Took %fs", seconds);
return 0;
}
First of all, you will want to use fgets instead to avoid dangerous buffer overflows. Second, you want to remove all punctuation from your numbers. Thus 2.000.000 becomes 2000000. Then you can use pointers and the strtol function to convert characters to integers; there are also other functions to convert to floats and other types.
Since code wants speed and IO is a typically bottle-neck, reading the entire file at once after using fstat() to find its length (#Charlon) makes some sense. Following is a quick parsing of that buffer.
// Stream file into memory
size = fread(contents, 1, fileSize, stream);
contents[size] = 0;
fclose(stream);
#if 1
// new code
size_t array_n;
int n;
if (sscanf(contents, "%zu%n", &array_n, &n) != 1) Handle_BadInput();
my_array = malloc(array_n * sizeof *my_array);
if (my_array == NULL) Handle_OOM();
char *p = &contents[n];
errno = 0;
char *endptr;
for (size_t count = 0; count < array_n; count++) {
my_array[count] = strtol(p, &endptr, 10);
if (p == endptr || errno)
Handle_BadInput();
p = endptr;
}
char ch;
if (sscanf(p, " %c", &ch) == 1) Handle_ExtraInput();
#else
//old code
// Count rows in content
number_of_rows = count_lines(contents);
// Get array of char*, one for each line
lines = get_lines(contents, number_of_rows);
// Get the numbers out of the lines
count = atoi(lines[0]); // First row has count
my_array = (int*)malloc(count * sizeof(int));
for (i = 0; i < count; ++i) {
my_array[i] = atoi(lines[i + 1]);
}
#endif
Still prefer the scale-able approach of reading one number at a time.
The fastest way needs a lot of RAM :
1) open the file (man open)
2) use the fstat function to get the size of you file (man fstat)
3) read the file with a buffer malloc-ed with the size you just get at 2) (man malloc)
4) close the file (man close)
5) parse your buffer and transform each block of digits (each time until ' ' or '\0') to int
EDIT : if your RAM is not enough large, you need to create a get_next_int function that only stores in your buffer the next number in the file
EDIT 2 : You can read until you know the number of int you will need to store and compares this number with a security coef to the size of your ram, and use the good way so that your program won't set errno to ENOMEM if you know what I'm talking about ;)

Calculating entropy in C

I'm trying to find the entropy of any given file. However, when I run my program, it always gives 3.00000 as an answer. I haven't used C in awhile, but I'm not sure where I'm going wrong here. I've been fiddling with it for a few hours now. Any tips would be great, thank you!
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define SIZE 256
int entropy_calc(long byte_count[], int length)
{
float entropy;
float count;
int i;
/* entropy calculation */
for (i = 0; i < SIZE; i++)
{
if (byte_count[i] != 0)
{
count = (float) byte_count[i] / (float) length;
entropy += -count * log2f(count);
}
}
return entropy;
}
int main(int argc, char **argv)
{
FILE *inFile;
int i;
int j;
int n; // Bytes read by fread;
int length; // length of file
float count;
float entropy;
long byte_count[SIZE];
unsigned char buffer[1024];
/* do this for all files */
for(j = 1; j < argc; j++)
{
memset(byte_count, 0, sizeof(long) * SIZE);
inFile = fopen(argv[j], "rb"); // opens the file given on command line
if(inFile == NULL) // error-checking to see if file exists
{
printf("Files does not exist. `%s`\n", argv[j]);
continue;
}
/* Read the whole file in parts of 1024 */
while((n = fread(buffer, 1, 1024, inFile)) != 0)
{
/* Add the buffer to the byte_count */
for (i = 0; i < n; i++)
{
byte_count[(int) buffer[i]]++;
length++;
}
}
fclose(inFile);
float entropy = entropy_calc(byte_count, length);
printf("%02.5f \t%s\n", entropy, argv[j]);
}
return 0;
}
Your return type of the function entropy_calc() should be float not int.

Resources