Count repeated numbers in a file - arrays

So I'm having this file myFile.txt with the following numbers in it: 1 2 3 4 5 6 7 8 9 0 2 3 4 5 6 6 5 4 3 2 1. I'm trying to write a program that calculates how many times a number from 0 to 9 is repeated, so it would be printed out like that Number %d repeats %d times. Right now I'm stuck at printing out the n number of elements of that file, so in example, if I would like to calculate how many times the 15 first numbers repeat themselves, firstly I would print out those 15 numbers, then the number of times each number repeats. But when I'm trying to print out those 15 numbers, it prints me this: 7914880640-10419997104210821064219560-1975428800327666414848.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
int main() {
FILE *fp;
fp = fopen("myFile.txt", "r");
char c;
int n, i, count = 0;
for (c = getc(fp); c != EOF; c = getc(fp)) {
if (!(c == ' '|| c == '\n'))
count = count + 1;
}
printf("The amount of numbers is:%d\nTill which element of the list would you like to count the amount of the each element: \n", count);
scanf("%d", &n);
int a[n];
if (n <= count) {
for (i = 0; i < n; i++) {
fscanf(fp, "%d", &a[i]);
}
for (i = 0; i < n; i++) {
printf("%d", a[i]);
}
} else {
printf("Error");
}
fclose(fp);
return 0;
}

That's the final solution.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
int count_occur(int a[], char exist[], int num_elements, int value)
{
int i, count = 0;
for (i = 0; i<num_elements; i++)
{
if (a[i] == value)
{
if (exist[i] != 0)
return 0;
++count;
}
}
return(count);
}
int main()
{
int a[100],track[10];
FILE *fp;
fp = fopen("myFile.txt", "r");
char c,exist[20]= {0};
int n,i,num,count=0,k=0,eval;
for (c = getc(fp); c != EOF; c=getc(fp))
{
if (!(c==' '|| c=='\n'))
count=count+1;
}
rewind(fp);
printf("The amount of numbers is:%d\nTill which element of the list would you like to count the amount of the each element: \n", count);
scanf("%d", &n);
if (n<=count)
{
while(fscanf(fp, "%d", &num) == 1)
{
a[k] = num;
k++;
}
for (i=0; i<n; i++)
{
printf("%d ", a[i]);
}
}
else
{
printf("Error");
}
fclose(fp);
if (n<=count)
{
for (i = 0; i<n; i++)
{
eval = count_occur(a, exist, n, a[i]);
if (eval)
{
exist[i]=1;
printf("\nNumber %d was found %d times\n", a[i], eval);
}
}
}
return 0;
}

Related

increment variable doubles at the end of my program

So I have this program where it asks the user for a filename to read, and a filename to save the output to. This program basically counts the frequency of a letter inside the txt file. Here is the program...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
char letter[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", FileName[50], SaveFile[50], print[256], stry[50], scount[50], point;
int i, j, count = 0;
FILE * readFile, *saveFile;
printf("Enter a file to read: ");
gets(FileName);
printf("Enter a filename to save results: ");
gets(SaveFile);
printf("Letter Frequency\n\n");
saveFile = fopen(SaveFile, "wb");
for(i = 0; i <= strlen(letter)-1; i++)
{
readFile = fopen(FileName, "r");
while(!feof(readFile))
{
fgets(print, 256, readFile);
for(j = 0; j <= strlen(print); j++)
{
if(toupper(print[j]) == toupper(letter[i]))
{
count++;
}
}
point = letter[i];
stry[0] = point;
sprintf(scount, "%d", count);
if(feof(readFile) && count > 0)
{
printf("%s %d\n", stry, count);
fprintf(saveFile, stry);
fprintf(saveFile, " ");
fprintf(saveFile, scount);
fprintf(saveFile, "\n");
}
}
count = 0;
}
fclose(readFile);
return 0;
}
I input a txt file named readme.txt that I modified. It contains
aaa
bbb
ccc
ddd
But when I run it, and used readme.txt to be read, the output is
A 3
B 3
C 3
D 6
The frequency of letter D must be only 3. I further modified the content of the readme.txt file, and figured out that value of the variable count is doubled when reading the last line. For example, the content of the txt file is
hello mama
hihihi
maria maria
woohoo
the output will be
A 6
E 1
H 6
I 5
L 2
M 4
O 9
R 2
W 2
I read my program so many times already, and I still can't find my wrong doings. I hope you can help me fix this problem. Your help will be very much appreciated!
EDIT:
This is what my code looks like after making the changes that were recommended in the comments section:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
char letter[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", FileName[50], SaveFile[50], print[256], stry[50], scount[50], point;
int i, j, count = 0;
FILE * readFile, *saveFile;
printf("Enter a file to read: ");
gets(FileName);
printf("Enter a filename to save results: ");
gets(SaveFile);
printf("Letter Frequency\n\n");
saveFile = fopen(SaveFile, "wb");
for(i = 0; i < strlen(letter); i++){
readFile = fopen(FileName, "r");
while(fgets(print, 256, readFile) != NULL)
{
fgets(print, 256, readFile);
for(j = 0; j <= strlen(print); j++)
{
if(toupper(print[j]) == toupper(letter[i]))
{
count++;
}
}
point = letter[i];
stry[0] = point;
sprintf(scount, "%d", count);
if(feof(readFile) && count > 0)
{
printf("%s %d\n", stry, count);
fprintf(saveFile, stry);
fprintf(saveFile, " ");
fprintf(saveFile, scount);
fprintf(saveFile, "\n");
}
}
count = 0;
}
fclose(readFile);
return 0;
}

Selection sort not working as expected (C language)

I have to sort an array of structs with selection sort, after I read them from a file.txt.
My algorithm is not working as expected, but it always avoid to sort them and it print the struct in decreasing order.
Example of file.txt :
P0 "ANTONIO" 2000 4
P1 "BARTOLOMEO" 1995 6
P2 "CARLO" 2020 1
P3 "DEMETRIO" 1960 2
P4 "ETTORE" 1920 3
P5 "FRANCESCO" 1950 5
Input: 2 5 3 1 6 4
Output: 4 6 1 3 5 2
What am I doing wrong?
Code below:
#include <stdio.h>
#include <stdlib.h>
#define N 7
struct persona
{
char codice[10];
char nome[30];
int anno[10];
int reddito[10];
};
int main()
{
FILE* fp;
fp = fopen("Testo.txt", "r");
struct persona* persona = malloc(sizeof(struct persona) * N);
int i = 0;
int j = 0;
if (fp != NULL)
{
while (i < N-1)
{
fscanf(fp, "%s %s %s %s",
persona[i].codice,
persona[i].nome,
persona[i].anno,
persona[i].reddito);
i++;
}
}
else
{
perror("Errore");
}
fclose(fp);
for(i=0; i<N-2; i++)
{
int min = persona[i].reddito;
for(j=i+1; j<N-1; j++)
{
if(persona[j].reddito < persona[i].reddito)
{
min = persona[j].reddito;
}
persona[N] = persona[j];
persona[j] = persona[i];
persona[i] = persona[N];
}
}
for(i=0; i<N-1;i++)
{
printf("%s\t %s\t %s\t %s\n",
persona[i].codice,
persona[i].nome,
persona[i].anno,
persona[i].reddito);
}
}
You have 6 lines in the file, but you have defined N as 7. It should be updated to 6.
while (i < N-1)
You are reading the first N-2, that is, 5 lines from the file. The 6th line is not being read. Same goes for other loops in the code using N.
int anno[10];
int reddito[10];
You do not need integer array to read the numeric fields in file, an integer should suffice.
As mentioned by #WhozCraig in the comments, the selection sort algorithm is incorrect. Here's the updated code for reference:
#include <stdio.h>
#include <stdlib.h>
#define N 6
typedef struct persona
{
char codice[10];
char nome[30];
int anno;
int reddito;
} PERSONA;
int main()
{
FILE *fp;
if ((fp = fopen("file.txt", "r")) == NULL)
{
perror("\nFile not found");
exit(1);
}
PERSONA *persona = malloc(sizeof(struct persona) * N);
int i = 0, j;
while (i < N)
{ if (fscanf(fp, "%s %s %d %d", persona[i].codice, persona[i].nome, &persona[i].anno, &persona[i].reddito) == EOF) {
break;
}
i++;
}
fclose(fp);
PERSONA temp;
/* selection sort */
for (i = 0; i < N - 1; i++)
{
int jMin = persona[i].reddito;
for (j = i + 1; j < N; j++)
{
if (persona[j].reddito < persona[jMin].reddito)
{
jMin = j;
}
}
if (jMin != i)
{
temp = persona[i];
persona[i] = persona[jMin];
persona[jMin] = temp;
}
}
for (i = 0; i < N; i++)
{
printf("\n%s\t %s\t %d\t %d", persona[i].codice, persona[i].nome, persona[i].anno, persona[i].reddito);
}
}
Further improvements:
You could also calculate the number of lines in the file in the code instead of relying on a hardcoded value N.
The statement to check sets only the min only if this statement is true
if(persona[j].reddito < persona[i].reddito)
try using the qsort function
int cmpfunc (const void * a, const void * b) {
struct persona *p1 = (struct persona *)a;
struct persona *p2 = (struct persona *)b;
if(p1->reddito < p2->reddito) return -1;
if(p1->reddito > p2->reddito) return 1;
return 0;
}
and instead of the for loop, use
qsort(persona, N, sizeof(struct persona), cmpfunc);

Array issue in C

I have an university project in C programming. I ran into a problem with the following task. My program should order numbers in two arrays. In the first array i must save (the biggest of every fifth element) and that is my problem. I am not sure how to make the loop which reads five elements compare them, take the biggest one, and then continue doing this with the other elements. I am hoping someone to help because I blocked.
#define A 100
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
void show(int x[], int nx); //функция за показване на масивите
float vavedi(int x[], int nx); //функция, чрез която ръчно въвеждаме числата и ги обработваме
FILE* readFile(char* fname); //функция която чете файл и представя съдържанието му като масиви
int main()
{
int call, a = 0, b = 0, mode = 0, i = 0;
int check = 0;
char fail[A];
char* menu[] = {
"PROGRAM STARTED!",
"Enter an option:",
"1 : Write the numbers.",
"2 : Choose from a file.",
"0 : Exit."
};
do {
for (i = 0; i < 5; i++)
printf("%s\n", menu[i]);
check=scanf("%d", &mode);
if (check != 1)
printf("ERROR! Try again!");
switch (mode)
{
case 1: {
//в случай 1 числата се въведждат от потребителя
call = vavedi(a, b);
break;
}
case 2: {
//в случай 2 потребителя използва съществуващ файл
printf("Enter the path of the file you want to open:\n");
scanf("%s", fail);
call = readFile(fail);
if (call == NULL) {
printf("The file doesn't exist! Try again!\n");
}
break;
}
case 0:
break;
default:
{
printf("ERROR! Try again!\n");
}
}
} while (mode != 0);
printf("\nThe program ended!\n");
return 0;
}
void show(int x[], int nx)
{
int k;
for (k = 0; k < nx; k++)
{
printf("\n Element[%d]= %d", k, x[k]);
}
}
float vavedi(int x[], int nx)
{
int call=0;
int enter=0;
int imin, max;
int b[A], c[A];
int i, j, j1, count;
j = 0;
do {
printf("\nCount of the elements:");
scanf("%d", &count);
if (count <= 0 || count > 100)
printf("Invalid input! Try again!\n");
} while (count <= 0 || count > 100);
for (i = 0; i < count; i++)
{
printf("\nEnter an element:");
scanf("%d", &c[i]);
}
printf("\n");
return enter;
}
Update : Including header file mentioned by #pmg.
If i understand correctly, your problem is to find largest element for every five elements:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <limits.h> // Put this after your header files
..
.. //Rest of the code.
..
for (i = 0; i < count; i++)
{
printf("\nEnter an element:");
scanf("%d", &c[i]);
}
size_t size = ceil(count/5.0);
memset(b , INT_MIN , size);
for(int i = 0 ; i < count ; i++)
{
b[i/5] = b[i/5] > c[i] ? b[i/5] : c[i];
}
// Print b like this:
for(i = 0 ; i < size; i++)
printf("%d" , b[i] );
Let's see how this works for array of size 9. array's indices will go from 0 to 8 . If I divide each of them by 5, I get 0 for i = 0 to 4 and 1 for i = 5 to 8. Now we can take max over elements in buckets of 5. You seem to be a beginner, hope this helps you in creating better understanding.
The other problem is the following:
{
int c[A], b[A];
int i = 0, j = 0, k = 0, num;
FILE* fp= NULL; //указател за файл
fp = fopen(fname, "r");
if (fp)
{
while (fscanf(fp, "%d", &c[i]) != EOF)
i++;
num=i;
size_t size = ceil(num/5.0);
memset(b , INT_MIN , size);
for(i = 0 ; i < num ; i++)
{
b[i/5] = b[i/5] > c[i] ? b[i/5] : c[i];
}
printf("\nARRAY1:\n");
for(i = 0 ; i < size; i++)
{
buble(b, i);
printf(" Element[%d]=%1d\n", i, b[i]);
}
printf("\nARRAY2:");
buble(c, num);
show(c, num);
printf("\n");
}
fclose(fp);
return fp;
}
It doesn't calculate the rigth way.

concatinating even and odd places in a string

I'm learning basics in coding. Can any one say what went wrong with my code
Prob:Given a string, S, of length N that is indexed from 0 to N-1 , print its even-indexed and odd-indexed characters as 2 space-separated strings on a single line
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
char input[100], final[100];
int main()
{
int num, i, j;
char even[50], odd[50], space[] = " ";
scanf("%d", &num);
for (i = 0; i < num; i++)
{
int k = 0, p = 0;
scanf(" %[^\n]s", input);
for (j = 0; input[j] != '\0'; j++)
{
if (j % 2 == 0)
{
even[k] = input[j];
k++;
}
else
{
odd[p] = input[j];
p++;
}
}
strcat(final, even);
strcat(final, space);
strcat(final, odd);
}
printf("%s", final);
}

C fork and pipe add numbers from a file

Totals different for same file when executed.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_FILE_NAME 100
#define RUNS 1
int main() {
int num,i;
FILE *fp;
char*s, buf[1024];
int count =0;
char c;
char filename[MAX_FILE_NAME];
printf("Enter filename: ");
scanf ("%s",filename);
if ((fp =fopen(filename, "r")) == NULL) {
printf("Error");
exit(1);
}
fscanf(fp,"%d",&num);
for (c = getc(fp); c!= EOF; c = getc(fp))
{
if (c == '\n'){
count = count+1;
}
}
printf("%s has %d numbers \n", filename, count);
int f;
printf("Choose from the options how many processes you want to use [1,2,4]: ");
scanf("%i", &f);
printf("%i processes \n", f);
int fds[f+1][2];
int numb[count];
int x,k;
time_t start, finish;
start = time(NULL);
for(i = 0; i < RUNS; i++)
{
pipe(fds[f]);
for( x = 0; x<f; x++)
{
pipe(fds[x]);
int ind[2];
ind[0] = ((x)*(count/f));
ind[1] = ((x+1)*(count/f));
write(fds[x][1], &ind, 2* sizeof(int));
if (fork() ==0)
{
int t =0;
int ind2[2];
read(fds[x][0], &ind2, 2*sizeof(int));
for( k = ind2[0]; k<ind2[1]; k++)
{
t += numb[k];
}
write(fds[f][1], &t, sizeof(int));
exit(0);
}
}
int m, tmp, total;
total = 0;
for( m = 0; m < f; m++)
{
for( m = 0; m < f; m++)
{
read(fds[f][0], &tmp, sizeof(int));
sleep(5);
total += tmp;
}
printf("DOne calc \n");
printf("Total: %i \n", total);
}
finish = time(NULL);
float runtime = (float)((finish-start)/RUNS);
printf("runtime: %f \n", runtime);
fclose(fp);
return 0;
}
You get random result for the same input because the calculation based on uninitialized int numb[count]; values.
According to the C99 standard, section 6.7.8.10:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.
Because of it int numb[count]; contains some random junk from memory. To get predictive results use explicit initialization:
#include <string.h> // memset
int numb[count];
memset (numb, 0, sizeof(numb)); // Zero-fills
Use the code bellow to put numbers from filename file into numb:
int i = 0;
char line[1024];
fseek(fp, 0, SEEK_SET);
while(fgets(line, sizeof(line), fp) )
{
if( sscanf(line, "%d", &numb[i]) == 1 ) // One number per line
{
++i;
}
}

Resources