The file becomes NULL after printing 254 rows in .txt - c

I am trying to solve the problem of recursion.
The problem is : Given a number n, print out all the possible combinations of set {a, b, ..., a+n-1}. Output the answer in "output-n.txt". 1<=n<=9.
Here's my code:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
void comb(int n,int curlen,int j,int num[],int flag) {
int i,k;
char filename[20] = "output-0.txt";
filename[7] = n + '0';
char ans[20] = { 0 };
FILE* fptr;
fptr = fopen(filename, "a");
if (fptr != NULL) {
if (curlen < n && flag != 0) {
for (i = 0; num[i] != 0; i++) {
ans[i] = num[i] + '`';
}
for (k = 0; k <= curlen; k++) {
fprintf(fptr, "%c", ans[k]);
}
fprintf(fptr, " ");
if (curlen == 0 && num[0] == n) {
fclose(fptr);
}
else {
comb(n, curlen + 1, j + 1, num, 0);
}
}
else {
for (; j <= n; j++) {
num[curlen] = j;
comb(n, curlen, j, num, 1);
}
}
}
}
int main() {
int n,flag=0,num[20] = { 0 };
scanf("%d", &n);
comb(n, 0, 1, num, flag);
system("pause");
return 0;
}
My program is doing fine while 1<=n<=7, but at n=8 and n=9, the FILE pointer becomes NULL in the middle and can only output part of the answers.
I looked closely to the output .txt file and realized that both of the files can only output to the 254th row.I wonder did I make any mistake.
Thanks for answering.

You have hit the limit for the number of open files.
You keep opening the same file for append and don't always close it. When I rearranged the code so that it opens the file once in main in "w" mode, it works correctly.
#include <stdio.h>
#include <stdlib.h>
void comb(FILE *fptr, int n,int curlen, int j, int num[], int flag) {
int i,k;
char ans[20] = { 0 };
if (curlen < n && flag != 0) {
for (i = 0; num[i] != 0; i++) {
ans[i] = num[i] + '`';
}
for (k = 0; k <= curlen; k++) {
fprintf(fptr, "%c", ans[k]);
}
fprintf(fptr, " ");
if (curlen == 0 && num[0] == n) {
//fclose(fptr);
}
else {
comb(fptr, n, curlen + 1, j + 1, num, 0);
}
}
else {
for (; j <= n; j++) {
num[curlen] = j;
comb(fptr, n, curlen, j, num, 1);
}
}
}
int main() {
int n,flag=0,num[20] = { 0 };
char filename[20] = "output-0.txt";
if(scanf("%d", &n) != 1 || n < 1 || n > 9) // sanity check
return 1;
filename[7] = n + '0';
FILE *fptr = fopen(filename, "w"); // open once
if(fptr != NULL) {
comb(fptr, n, 0, 1, num, flag); // pass the file pointer
fclose(fptr);
}
return 0;
}

Related

User inputs a number, and program should surround it with charatchers

This is my code, it works but i feel i could do something different
#include <stdio.h>
int main()
{
int n;
printf("Input a number [0,9]: ");
scanf("%d", &n);
printf("*****\n");
printf("*****\n");
printf("**%d", n);
printf("**");
printf("\n*****\n");
printf("*****\n");
return 0;
}
Is this the best solution or is there something easier?
I tend to do 1 printf() per output line
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n;
printf("Input a number [0,9]: ");
if (scanf("%d", &n) != 1) exit(EXIT_FAILURE);
if ((n < 0) || (n > 9)) printf("nope\n");
else {
printf("*****\n");
printf("*****\n");
printf("**%d**\n", n);
printf("*****\n");
printf("*****\n");
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n;
printf("Input a number [0,9]: ");
if (scanf("%d", &n) != 1) exit(EXIT_FAILURE);
if ((n < 0) || (n > 9)) printf("nope\n");
else {
for (int i = 0; i < 5; i++) {
if (i == 2) {
printf("**%d**\n", n);
} else {
printf("*****\n");
}
}
}
return 0;
}
you can do it a bit more universal way. It will print NCHARS around the number and NLINES lines of FILLER around the number. Any number is covered (including negave ones)
#include <stdio.h>
#define NCHARS 3
#define NLINES 3
#define FILLER '*'
size_t countdigits(int n)
{
size_t ndigits = n <= 0 ? 1 : 0;
while(n)
{
ndigits++;
n /= 10;
}
return ndigits;
}
void printlines(size_t nchars, char ch)
{
for(size_t before = 0; before < NLINES; before++)
{
for(size_t pos = 0; pos < nchars; pos++ )
printf("%c", ch);
printf("\n");
}
}
void printfsurrounded(int n)
{
size_t nchars = countdigits(n);
printlines(nchars + NCHARS * 2, FILLER);
for(int pos = 0; pos < NCHARS; pos++) printf("%c", FILLER);
printf("%d", n);
for(int pos = 0; pos < NCHARS; pos++) printf("%c", FILLER);
printf("\n");
printlines(nchars + NCHARS * 2, FILLER);
}
int main(void)
{
printfsurrounded(4);
printf("\n");
printfsurrounded(1024);
printf("\n");
printfsurrounded(-233445);
}
https://godbolt.org/z/hz1eq9

Can someone explain how i would open a file (containg a list of numbers) and then pass them though my selection sort algorithm?

So ive genertaed a list of random numbers (of varying size) that need to be sorted using selection sort, i have the selection sort algoruthm but im not sure how to open my file, read it and then pass it through my algorithm.
In my selection sort i have an array of number for temporary ue but they need to be replaced with the numbers from the file.
This is my selection sort code im using...
int main() {
int arr[10]={6,12,0,18,11,99,55,45,34,2};
int n=10;
int i, j, pos, s;
for (i = 0; i < (n - 1); i = i + 1) {
pos = i;
for (j = i + 1; j < n; j = j + 1) {
if (arr[pos] > arr[j])
pos = j;
}
if (pos != i) {
s = arr[i];
arr[i] = arr[pos];
arr[pos] = s;
}
}
for (i = 0; i < n; i = i + 1)
printf("%d\n", arr[i]);
return 0;
}
Here is a solution which reads the numbers from standard input. The first number in the input is the number of integers to read.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NEW_ARRAY(pointer, length) \
{ \
(pointer) = malloc((size_t) (length) * sizeof (pointer)[0]); \
if ((pointer) == NULL) { \
fprintf(stderr, "Allocating memory failed: %s\n", strerror(errno)); \
exit(EXIT_FAILURE); \
} \
}
void Read(int **numbers, int *numbersLength)
{
int count, i;
count = scanf("%d", numbersLength);
if ((count == 1) && (*numbersLength > 0)) {
NEW_ARRAY(*numbers, *numbersLength);
i = -1;
do {
i++;
count = scanf("%d", &(*numbers)[i]);
} while ((count == 1) && (i < *numbersLength - 1));
if (count != 1) {
fprintf(stderr, "Expected %d numbers but got only %d\n", *numbersLength, i);
exit(EXIT_FAILURE);
}
} else {
fprintf(stderr, "Number of integers should be a positive integer\n");
exit(EXIT_FAILURE);
}
}
void Sort(int numbers[], int numbersLength)
{
/*your sorting logic here*/
}
void Print(const int numbers[], int numbersLength)
{
int i;
for (i = 0; i < numbersLength; i++) {
printf(" %d", numbers[i]);
}
}
int main(void)
{
int numbersLength;
int *numbers;
Read(&numbers, &numbersLength);
Sort(numbers, numbersLength);
Print(numbers, numbersLength);
putchar('\n');
free(numbers);
return 0;
}
I think you'll want fgetc and fopen: https://man7.org/linux/man-pages/man3/fopen.3.html, https://man7.org/linux/man-pages/man3/fgetc.3.html. If they have varying lengths you will probably also be looping until you read EOF, the end of file character. Hope this helps and good luck!

How to save to file?

I've got a problem with my project. I don't know how to add an option which will save to file the result's from console. I think i shoud use fprintf but nothing works. Please help ;D
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct symbole
{
int symbol;
int czestosc;
};
struct symbole nowy[256];
void odczytIwyznaczenie(void);
void wyswietl(struct symbole nowy[]);
void sortuj(struct symbole nowy[]);
int main()
{
odczytIwyznaczenie();
sortuj(nowy);
wyswietl(nowy);
getchar();
return 0;
}
void odczytIwyznaczenie (void)
{
FILE *plik;
char n;
int i;
for (i=0; i<256; i++)
{
nowy[i].czestosc=0;
nowy[i].symbol=i;
}
plik = fopen("plik.txt","r");
if (plik == NULL)
{
printf("Blad odczytu!");
getchar();
exit(1);
}
while (n != EOF)
{
n = fgetc(plik);
for(i=0; i<256; i++)
{
if (nowy[i].symbol == n)
{
nowy[i].czestosc++;
break;
}
}
}
fclose (plik);
}
void sortuj(struct symbole nowy[])
{
int i, j, temp, temp1;
for (i = (256); i > 0; i--)
{
for (j = 1; j <= i; j++)
{
if (nowy[j-1].czestosc < nowy[j].czestosc)
{
temp = nowy[j-1].czestosc;
temp1=nowy[j-1].symbol;
nowy[j-1].czestosc = nowy[j].czestosc;
nowy[j-1].symbol=nowy[j].symbol;
nowy[j].czestosc = temp;
nowy[j].symbol=temp1;
}
}
}
}
void wyswietl(struct symbole nowy[])
{
int i;
for (i=0; i<256; i++)
{
if (nowy[i].czestosc!= 0)
printf ("%5d| %5c| %5d\n", nowy[i].symbol, nowy[i].symbol, nowy[i].czestosc);
}
}
You indeed need fprintf(), use it as follows
void wyswietl(struct symbole nowy[])
{
FILE *output;
int i;
output = fopen("OuptputFile.txt", "w");
if (output == NULL) /* maybe you don't have permission to create the file */
return;
for (i = 0 ; i < 256 ; i++)
{
if (nowy[i].czestosc == 0)
continue;
fprintf(output, "%5d| %5c| %5d\n", nowy[i].symbol,
nowy[i].symbol, nowy[i].czestosc);
}
}
Also, you have to initialize n before comparing it to EOF, change
while (n != EOF)
which is reached before n is initialized, to
while ((n = fgetc(pilk)) != EOF)

Function not updating an int field

Everything seems to working fine except for my SPOILED votes int is staying at 0 and not being updates by the function. I have tried adding a pointer thinking it would point to the object outside of the function which it does but the ++ function is not updating
#include <stdio.h>
struct candidates
{
char name[20];
int votes;
};
struct candidates electionCandidates[7];
void Initialize(struct candidates EC[]);
void Processvotes(struct candidates EC[], int *BadVote);
void printResults(struct candidates EC[], int *BadVote);
int main()
{
int i, SPOIL = 0;
Initialize(electionCandidates);
Processvotes(electionCandidates, &SPOIL);
printResults(electionCandidates, &SPOIL);
for(i = 0; i < 7; i++)
{
printf("%s",electionCandidates[i].name);
printf("%d\n\n",electionCandidates[i].votes);
}
printf("%d", SPOIL);
}
void Initialize(struct candidates EC[])
{
int i;
FILE *fp;
fp = fopen("elections.txt", "r");
for (i = 0; i < 7; i++)
{
fgets(EC[i].name, 20, (FILE*)fp);
}
fclose(fp);
}
void Processvotes(struct candidates EC[], int *BadVote)
{
int TVOTE, i;
FILE *fp;
fp = fopen("elections.txt", "r");
for (i = 0; i < 7; i++)
{
fgets(EC[i].name, 20, (FILE*)fp);
}
for (i = 0; i < 365; i++)
{
fscanf(fp, "%d", &TVOTE);
if (TVOTE == 1)
EC[0].votes++;
if (TVOTE == 2)
EC[1].votes++;
if (TVOTE == 3)
EC[2].votes++;
if (TVOTE == 4)
EC[3].votes++;
if (TVOTE == 5)
EC[4].votes++;
if (TVOTE == 6)
EC[5].votes++;
if (TVOTE == 7)
EC[6].votes++;
if (TVOTE < 1 || TVOTE > 7)
*BadVote++;
}
fclose(fp);
}
void printResults(struct candidates EC[], int *BadVote)
{
int i, Win = 0, WinSCORE = 0, Runner = 0, RunnerSCORE = 0;
for (i = 0; i < 7; i++)
{
if (EC[i].votes > WinSCORE)
{
WinSCORE = EC[i].votes;
Win = i;
}
if (EC[i].votes == WinSCORE)
{
RunnerSCORE = EC[i].votes;
Runner = i;
}
}
if (WinSCORE == RunnerSCORE)
{
printf("There was a tie between %s and %s who both got a total of %d votes each. There were %d spoiled votes\n", EC[Win].name, EC[Runner].name, WinSCORE, *BadVote);
}
else
printf("%s won the election with a total of %d votes. There was a total of %d spoiled votes.\n", EC[Win].name, WinSCORE, *BadVote);
}
Any help will be appreciated.
The postfix ++ operator takes precedence over the *; when you write *BadVote++, you're actually incrementing the pointer, not the value being pointed to. You should instead write (*BadVote)++. See this question for more.
I'm pretty sure it's a problem with the precedence of the operators. Try this:
if (TVOTE < 1 || TVOTE > 7)
(*BadVote)++;

Replacing elements in an array

I have a problem thats giving me a huge ache.
This piece of code purpose is to fill up an array with integer values and at the same time defend against strings and etc....but it doesn't defend against duplicates, but tried I got to far as replacing the number with a new number for example
Enter 6 integers
1, 2, 2, 3, 4, 5
my code will let me replace that 2 at position 1 with another number. What I want it to do is not to repeat the same number again, for example please replace 2 at position 1. I dont want the user to enter 2 again... and I want to make it to double check the work the array if any repeating numbers exists thank you.
system("clear");
printf("\nEntering Winning Tickets....\n");
nanosleep((struct timespec[]){{1, 0}}, NULL);
system("clear");
char userInput[256];
char c;
int duplicationArray[6] = {-1, -1, -1, -1, -1, -1};
for (i = 0; i < 6; i++)
{
printf("\nPlease enter the %d winning ticket number!(#'s must be between 1-49): ", i+1);
fgets(userInput, 256, stdin);
if ((sscanf(userInput, "%d %c", &winningNumbers[i], &c) != 1 || (winningNumbers[i] <= 0) || winningNumbers[i] >= 50))
{
printf("\nInvalid Input.\n") ;
nanosleep((struct timespec[]){{0, 350000000}}, NULL);
system("clear");
i = i - 1;
}
}
for (i = 0; i < 6 - 1; ++i)
{
min = i;
for (j = i+1; j < 6; ++j)
{
if (winningNumbers[j] < winningNumbers[min])
min = j;
}
temp = winningNumbers[i];
winningNumbers[i] = winningNumbers[min];
winningNumbers[min] = temp;
}
for (i = 0; i < 6; i++)
{
if (winningNumbers[i] == winningNumbers[i+1])
{
duplicationArray[i] = i;
duplicationCounter++;
}
else
{
duplicationCounter--;
}
}
if (duplicationCounter > -6)
{
for (i = 0; i < 6; i++)
{
int j, min, temp;
min = i;
for (j = i+1; j < 6; ++j)
{
if (duplicationArray[j] > duplicationArray[min])
min = j;
}
temp = duplicationArray[i];
duplicationArray[i] = duplicationArray[min];
duplicationArray[min] = temp;
}
for (i = 0; i < 6; i++)
{
if (duplicationArray[i] == -1)
{
zeroCounter++;
}
}
int resize = (6 - zeroCounter)+1;
for (i = 0; i <= resize; i++)
{
if (duplicationArray[i] == -1)
{
i++;
}
else if (duplicationArray[i] != -1)
{
system("clear");
printf("\nDuplicated numbers has been dected in your array. ");
printf("\nPlease replace the number %d at postion %d with another number: ", winningNumbers[duplicationArray[i]], duplicationArray[i]);
fgets(userInput, 256, stdin);
if ((sscanf(userInput, "%d %c", &winningNumbers[duplicationArray[i]], &c) != 1 || (winningNumbers[i] <= 0) || winningNumbers[i] >= 50))
{
printf("\nInvalid Input.\n") ;
nanosleep((struct timespec[]){{0, 350000000}}, NULL);
system("clear");
i = i - 1;
}
}
}
duplicationCounter = 0;
for (i = 0; i < 6; i++)
{
if (winningNumbers[i] == winningNumbers[i+1])
{
duplicationArray[i] = i;
duplicationCounter++;
}
else
{
duplicationCounter--;
}
}
printf("%d, ", duplicationCounter);
}
#include <stdio.h>
#include <stdint.h>
#define DATA_SIZE 6
int main(void){
char userInput[256];
int inputNum, winningNumbers[DATA_SIZE];
uint64_t table = 0;
int i=0;
while(i<DATA_SIZE){
printf("\nPlease enter the %d winning ticket number!(#'s must be between 1-49): ", i+1);
fgets(userInput, sizeof(userInput), stdin);
if(sscanf(userInput, "%d", &inputNum) != 1 || inputNum <= 0 || inputNum >= 50)
continue;
uint64_t bit = 1 << inputNum;
if(table & bit)
continue;
table |= bit;
winningNumbers[i++] = inputNum;
}
for(i=0;i<DATA_SIZE;++i)
printf("%d ", winningNumbers[i]);
printf("\n");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define DATA_SIZE 6
int inputNumberWithRangeCheck(const char *msg, const char *errMsg, int rangeStart, int rangeEnd){
char inputLine[256];
int n;
for(;;){
printf("%s", msg);
fgets(inputLine, sizeof(inputLine), stdin);
if(sscanf(inputLine, "%d", &n) != 1 || n < rangeStart || n > rangeEnd)
fprintf(stderr, "%s", errMsg);
else
return n;
}
}
int inputNumber(void){
return inputNumberWithRangeCheck(
"\nPlease enter the winning ticket number!(#'s must be between 1-49): ",
"Invalid Input.\n",
1,49);
}
int *inputArray(int *array, size_t size){
int i;
for(i=0;i<size;++i){
printf("\nInput for No.%d\n", i+1);
array[i] = inputNumber();
}
return array;
}
int **duplicateCheck(int *array, size_t size){
int **check, count;
int i, j;
check = malloc(size*sizeof(int*));
if(!check){
perror("memory allocate\n");
exit(-1);
}
//There is no need to sort the case of a small amount of data
//(Cost of this loop because about bubble sort)
for(count=i=0;i<size -1;++i){
for(j=i+1;j<size;++j){
if(array[i] == array[j]){
check[count++] = &array[i];
break;
}
}
}
check[count] = NULL;
if(count)
return check;
else {
free(check);
return NULL;
}
}
int main(void){
int winningNumbers[DATA_SIZE];
int **duplication;
int i, j;
inputArray(winningNumbers, DATA_SIZE);
while(NULL!=(duplication = duplicateCheck(winningNumbers, DATA_SIZE))){
for(i=0;i<DATA_SIZE;++i){
if(duplication[i]){
printf("\nyour input numbers : ");
for(j=0;j<DATA_SIZE;++j)
printf("%d ", winningNumbers[j]);
fprintf(stderr, "\nThere is duplicate. Please re-enter.\n");
*duplication[i] = inputNumber();
} else
break;
}
free(duplication);
}
for(i=0;i<DATA_SIZE;++i)
printf("%d ", winningNumbers[i]);
printf("\n");
return 0;
}

Resources