How can I merge N files - c

I have N files, in each lines of every file there are unique words and the word count, for example
file1 file2 file3
the 2 black 3 red 4
apple 4 tree 2 crab 6
snake 3 mantle 8 puppet 1
How can I merge these files in sorted order into a one file, thanks in advance, really need an idea.
void *doMerge(void* arg){
int i,j,p = 0, k = 0;
char*min = malloc(sizeof(char)*256);
FILE *f = fopen("fileFinal","w+");
char **StringBuffer = (char **)malloc(sizeof(char*)*R);
int *IntBuffer = malloc(sizeof(int)*R);
for(i=0; i < R; i++){
rewind(temp2[i]);
StringBuffer[i] = (char *)malloc(sizeof(char)*256);
if(fscanf(temp2[i],"%s %d",StringBuffer[i],&IntBuffer[i]) == 1)
printf("String is %s and int is %d\n",StringBuffer[i],IntBuffer[i]);
}
while(1){
strcpy(min, StringBuffer[0]);
for(j=0 ; j < R-1; j++){
if(strcmp(StringBuffer[j+1],StringBuffer[j]) <= 0){
strcpy(min,StringBuffer[j+1]);
p = j+1;
}
}fprintf(f,"%s %d\n",min, p);
if(fscanf(temp2[p],"%s %d",StringBuffer[p],&IntBuffer[p]) == 1){}
k++;
}
};

while(1)
{
strcpy(min, StringBuffer[0]);
for(j=0 ; j < R-1; j++){
if(strcmp(StringBuffer[j+1],StringBuffer[j]) <= 0)
{
strcpy(min,StringBuffer[j+1]);
p = j+1;
}
}
fprintf(f,"%s %d\n",min, p);
if(fscanf(temp2[p],"%s %d",StringBuffer[p],&IntBuffer[p]) == 1)
{}
k++;
}
That while loop has a number of different problems
1) p needs to be initialized to 0 before the for loop
2) the strcmp should compare min to StringBuffer[j], which also means that
2a) the for loop should be for(j=1;j<R;j++), and
2b) strcpy(min,StringBuffer[j+1]); should be strcpy(min,StringBuffer[j]);, and
2c) the line p=j+1 should be p=j
3) k is not used for anything and should be removed
But the most important thing is the fscanf. You should be checking that fscanf returns 2. If not then the file is done, and you need to keep track of the fact that the file is done, and that file should not be checked in the for loop any more.

Related

Not able to print this 2D array (weird output) in C

I am trying to read a text file with 100 numbers like 1 2 45 55 100 text file here (all on a single line) and then put them in a 10x10 array (2D array).
736.2 731.6 829.8 875.8 568.3 292.2 231.1 868.9 66.7 811.9 292.0 967.6 419.3 578.1 322.5 471.7 980.0 378.8 784.1 116.8 900.4 355.3 645.7 603.6 409.1 652.1 144.1 590.6 953.1 954.0 502.0 689.3 685.6 331.9 565.1 253.9 624.1 796.2 122.8 690.7 608.0 414.8 658.3 27.3 992.9 980.8 499.0 972.8 359.7 283.1 89.7 260.1 638.4 735.4 863.6 47.5 387.5 7.7 638.1 340.6 961.7 140.1 29.8 647.3 471.9 594.9 901.2 96.0 391.1 24.0 786.7 999.1 438.7 445.0 26.4 431.6 425.9 525.4 404.4 785.6 808.5 494.1 45.7 447.0 229.5 909.3 494.4 617.0 917.0 132.5 957.5 878.8 272.6 987.4 526.1 744.5 582.3 427.3 840.5 973.3
Here is my code:
#include <stdio.h>
#define NR 10
#define NC 10
int main(void) {
int numbers[9][9];
int i = 0;
int count;
int j = 0;
FILE *file;
file = fopen("numbers.txt", "r");
for (count = 1; count < 101; count++) {
fscanf(file, "%d", &numbers[i][j]);
j++;
if ((count != 1) && (count % 10 == 0)) {
i++;
j = 0;
}
}
fclose(file);
int p = 0;
int q = 0;
for (p = 0; p < NR; p++) {
for (q = 0; q < NC; q++) {
printf("%d", numbers[p][q]);
}
printf("\n");
}
return 0;
}
As SparKot noted in a comment, to read a 10x10 matrix, you need to define the matrix with 10x10 elements:
int numbers[10][10];
That has to be one of the weirder ways of reading a 10x10 matrix that I've ever seen. Why not go for a simple approach of nested loops. Since the data contains floating-point numbers, you need to read them as double (or perhaps float) values.
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
double double_val;
if (fscanf(file, "%lf", &double_val) != 1)
{
fprintf(stderr, "failed to read matrix[i][j]\n", i, j);
exit(EXIT_FAILURE);
}
numbers[i][j] = double_val;
}
}
The mess with double_val works around the data containing floating point numbers and your original code trying to read integers. You'll get one valid value; thereafter, fscanf() will return 0 because the . is not a part of a valid integer. This highlights the importance of checking the return value from fscanf() and its relatives.
Frankly, you should be using double numbers[10][10]; for the data from the file. Then you could read directly into the array:
if (fscanf("%lf", &numbers[i][j]) != 1)
But you'd need to check (and probably change) all the rest of the code too.
There are multiple issues in your code:
the matrix is too small, make it numbers[NR][NC].
you do not check for fopen failure: you will have undefined behavior if the file numbers.txt is not in the current directory or cannot be open for reading.
you read the file contents as integers, but the file contains floating point numbers with a . decimal separator: the second and subsequent fscanf() will get stuck on the . and keep returning 0 without modifying the destination number, leaving the matrix mostly uninitialized. Make the matrix double numbers[NR][NC], read the numbers with %lf and test for conversion failure.
the counting method in the reading loop is weird. Just use 2 nested for loops with proper counter and tests.
printing the matrix contents, you should output at least a space between numbers so the output is readable.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define NR 10
#define NC 10
int main() {
double numbers[NR][NC];
FILE *file;
file = fopen("numbers.txt", "r");
if (file == NULL) {
fprintf(stderr, "cannot open numbers.txt: %s\n", strerror(errno));
return 1;
}
for (int i = 0; i < NR; i++) {
for (int j = 0; j < NC; j++) {
if (fscanf(file, "%lf", &numbers[i][j]) != 1) {
fprintf(stderr, "error reading number at row %d, col %d\n",
i + 1, j + 1);
fclose(file);
return 1;
}
}
}
fclose(file);
for (int p = 0; p < NR; p++) {
for (int q = 0; q < NC; q++) {
printf(" %5g", numbers[p][q]);
}
printf("\n");
}
return 0;
}
Clear all a common condition that causes programs to crash; they are often associated with a file named core.
code is showing segmentation fault.

Brain**** implementation in C

I'm trying to run a hello world program with the brainfuck implementation that I made this week but I'm getting a strange output.
This is the hello world file that I'm trying to run.
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.-------
-.>>+.>++.
I have saved it to hello.txt, and am parsing it in the main function of the program.
The output is
1 -3 4 4 7 0 -1 7 10 4 -4 1 2
which, when you add 72, and convert to character , gives
I E L L O H G O R L D I J
So it seems like there is something I'm missing, even though its sort of close to the right solution.
But I'll go into the structure of the thing anyhow, the general idea is as followed:
We have two 'tapes', a program to follow which I label 'parsed' which has a pointer 'attached' to it, and an empty tape to write into, which I label 'mem', which also has a pointer 'attached' to it. We also have a list of structures that we can use to jump between bracket locations.
In the main function, there are three parts: first I parse the program and store it in an array. Then I run through this parsing and match brackets, then I start the brainfuck loop and write the output onto the empty array, until the final character has been reached.
In the brainfuck loop, when we find a bracket, we run through the list of pairs to find its match, and then jump to that location.
Maybe it's a bit clunky, but I hope it makes sense.
#include <stdio.h>
#include <stdlib.h>
#define MAX 30000
//input tape
char parsed[MAX];
char * ptr;
//bracket matching
struct bracketlinks{
char * bracket_1;
char * bracket_2;
};
struct bracketlinks * pairslist;
int bracket_count;
//output tape
char mem[MAX] = {0};
int * mptr;
int main(){
mptr = malloc(sizeof(int));
//parse text file and make list of tokens
FILE * parsecode;
parsecode = fopen("helloworldbf.txt", "r");
int count = 0;
char buffer;
while(!feof(parsecode)){
buffer = fgetc(parsecode);
if(buffer == 10){break;}
if(buffer == 32){continue;}
else{
parsed[count] = buffer;
if(buffer == 91 || buffer == 93){
bracket_count++;
}
count++;
}
}
fclose(parsecode);
pairslist = malloc(bracket_count * sizeof(char*));
//creates array of structures which match brackets so we can perform memory jumps
int reset_count;
int list_counter = 0;
for(int i = 0; i < count; i++){
if(parsed[i] == '['){
reset_count = 0;
for(int j = 0; j < count - i + 1; j++){
if(parsed[i + j] == '['){reset_count++;}
if(parsed[i + j] == ']'){reset_count--;}
if(reset_count == 0){
struct bracketlinks new;
new.bracket_1 = &parsed[i];
new.bracket_2 = &parsed[i + j];
pairslist[list_counter] = new;
list_counter++;
break;
}
else{continue;}
}
}
else{continue;}
}
//runs through the input tape and performs operations on the output tape
ptr = parsed;
char final_token = ptr[count];
while(ptr[0] != final_token){
if(ptr[0] == '['){
if(mem[mptr[0]]){++ptr;}
if(!mem[mptr[0]]){
for(int i = 0; i < bracket_count/2; i++){
if(pairslist[i].bracket_1 == &ptr[0]){
ptr = ++pairslist[i].bracket_2;
}
if(pairslist[i].bracket_2 == &ptr[0]){
ptr = ++pairslist[i].bracket_1;
}
else{continue;}
}
}
}
if(ptr[0] == ']'){
if(!mem[mptr[0]]){
for(int i = 0; i < bracket_count/2; i++){
if(pairslist[i].bracket_1 == &ptr[0]){
ptr = ++pairslist[i].bracket_2;
}
if(pairslist[i].bracket_2 == &ptr[0]){
ptr = ++pairslist[i].bracket_1;
}
else{continue;}
}
}
if(mem[mptr[0]]){++ptr;}
else{continue;}
}
if(ptr[0] == '+'){++ptr;++mem[mptr[0]];}
if(ptr[0] == '-'){++ptr;--mem[mptr[0]];}
if(ptr[0] == '>'){++ptr; mptr[0]++;}
if(ptr[0] == '<'){mptr[0]--;++ptr;}
if(ptr[0] == '.'){++ptr; printf("%c %d \n", mem[mptr[0]] + 72, mem[mptr[0]]);}
else{continue;}
}
free(pairslist);
free(mptr);
return 0;
}
Any help would be massively appreciated,
Cheers..
OK so here's the fix for the main bug: basically just switch the exclamation marks and don't be a numpty.
if(ptr[0] == ']'){
if(mem[mptr[0]]){
for(int i = 0; i < bracket_count/2; i++){
if(pairslist[i].bracket_1 == &ptr[0]){
ptr = ++pairslist[i].bracket_2;
}
if(pairslist[i].bracket_2 == &ptr[0]){
ptr = ++pairslist[i].bracket_1;
}
else{continue;}
}
}
if(!mem[mptr[0]]){++ptr;}
else{continue;}
}
Still working on the !feof thing but will update with that too

Trying to debug program

You are tasked to create a program that will read in a text file and compute statistics on the contents. Your program will count the number of alphabetic characters using isalpha(), the number of digits using isdigit() and the number of punctuation using ispunct(). (Zybook module 11). Your program will provide an appropriate report to display the analysis results to the user. Your program should work with any text file and the user should be able to select the file for input. You may create a test text file for testing and development. I suggest a short paragraph with punctuation and numbers that you can easily test the values with. Your array may be a VLA or FLA array. I suggest using an array of pointers and for each line of the text file allocate an array using calloc(). You may declare a static array, so long as it will hold 100 lines of 80 characters. A line length of 80 characters will be assumed.
Ive written most of the code but am getting a couple warnings and the program terminates abruptly and gives me a segmentation error.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void) {
//Declarations
char paragraphArray[100][80], filename[50];
int i = 0, puncts = 0, alphas = 0, nums = 0, line = 0;
//Ask user what file to load and assign it to filename
printf("Enter the filename to wish to load: ");
scanf("%s", filename);
//FIle pointer is tagged
FILE *fPoint;
//Opens file pointer as the user-named file in read mode
fPoint = fopen(filename, "r");
//If file not found, a NULL value is assigned and prints to screen.
if(fPoint == NULL)
printf("Cannot open file");
//Else statement that reads the file line by line starting at index i=0
else
{ i=0;
while(fgets(paragraphArray[i], 80, fPoint))
{ paragraphArray[i][(strlen(paragraphArray[i]))-1]='\0';
i++;
}
//After while loop is finished, the value of i is stored as number of lines.
line = i;
}
//Closing the file
fclose(fPoint);
//Function Calls
alphas = IsAlpha(paragraphArray, i);
nums = IsDigit(paragraphArray, i);
puncts = IsPunct(paragraphArray, i);
//Display statistics to screen.
printf("There are %d alphabet characters.\n", alphas);
printf("There are %d numerical digits.\n" , nums);
printf("There are %d punctuation marks.\n" , puncts);
}
//Function Definitions
int IsAlpha(char paragraphArray[100][80], int line){
int alphaCount = 0, i = 0, j = 0, asciiValue = 0;
//Outer loop that iterates through each line of the paragraph.
for(i = 0; i < line; i++){
//Inner loop that compares elements of the array to ASCII values
for(j = 0; j < 80; j++){
asciiValue = paragraphArray[i][j];
//if statement that does the comparison and adds to count value
if((asciiValue <= 90 && asciiValue >= 65) || (asciiValue >= 97 && asciiValue <= 122))
alphaCount++;
}
}
//Returns count of alphabet characters after all iterations.
return alphaCount;
}
int IsDigit(char paragraphArray[100][80], int line){
int digitCount = 0, i = 0, j = 0, asciiValue = 0;
//Outer loop that iterates through each line of paragraph
for(i = 0; i < line; i++){
//Inner loop that compares elements of array to ASCII values.
for(j = 0; j < 80; j++){
asciiValue = paragraphArray[i][j];
//If statement that does the comparison and adds count value.
if(asciiValue >= 48 && asciiValue <= 57)
digitCount++;
}
}
//Returns count of numbers after all iterations.
return digitCount;
}
int IsPunct(char paragraphArray[100][80], int line){
int punctCount = 0, i = 0, j = 0, asciiValue = 0;
//Outer Loop that iterates through each line of paragraph.
for(i = 0; i < line; i++){
//Inner loop that compares elements of array to ASCII Values
for(j = 0; j < 80; j++){
asciiValue = paragraphArray[i][j];
//If statement that does comparison and adds count value.
if((asciiValue >= 33 && asciiValue <= 47) || (asciiValue >= 58 && asciiValue <= 64) || (asciiValue >= 91 && asciiValue <= 96) ||(asciiValue >= 123 && asciiValue <= 126))
punctCount++;
}
}
return punctCount;
}
Your problem is in for loop condition.
You itterate with the condition i < 80, but, if your line is lower than 80,
you compare undefined value.
Instead of 80 use strlen.
You can also use valgrind or gdp to debug your program. :)

Manipulating files through C to make a top 5 leaderboard

I'm making a connect 4 game as apart of a project and I want to add extra functionality to it, however I'm struggling.
The code is a function I've written that takes a struct (lb leaderboard) and attempts to read the file for that difficulty of all its inputs into a lb array size of 6 which include the difficulty of the bot, turn count and the name of the player, then organizes it in order of turn count and reprints the top 5 back into the file.
I set the first element of the old array to the passed by struct of leaderboard data for the organise function bit.
However, when i set it up with template inputs each separated with a new line like such:
0 7 James
0 13 Jimmy
0 8 Joshua
0 6 Charly
0 9 Jack
It prints this to the file:
0 7 James
0 13 Jimmy
0 8 Joshua
0 6 Charly
(0 9 Jack 1982289408 0 ) same line
The struct looks like this as well{
int turn_count
int diff
char name[20]}
I'm really new to coding so any help is appreciated!
lb old[6];
lb temp;
FILE *file;
if (leaderboard.diff == 0){
file = fopen("leaderboard0.txt", "r+");}
else if (leaderboard.diff == 1){
file = fopen("leaderboard1.txt", "r+");}
else if (leaderboard.diff == 2){
file = fopen("leaderboard2.txt", "r+");}
fseek( file, 1, SEEK_SET );
old[0] = leaderboard;
for (int i = 1; i < 6; i++){
fscanf(file, "%i %i %s", old[i].diff, old[i].turn_count, old[i].name);}
for (int i = 0; i < 6; i++){
for (int j = i + 1; j < 6; j++)
if (old[i].turn_count > old[j].turn_count)
{
temp = old[i];
old[i] = old[j];
old[j] = temp;
}}
for (int i = 0; i < 5; i++){
fprintf(file, "%i %i %s\n", old[i].diff, old[i].turn_count, old[i].name);
fclose(file);}
}
Welcome to StackOverflow, JJewson
First of all, I strongly recommend to you to properly indent your code. One error will be obvious only by that:
lb leaderboard = { ... }; /* was missing from your source code */
lb old[6]; /* you should rename this */
lb temp;
FILE *file;
/* somthing that opens a block was missing from your example source */ {
if (leaderboard.diff == 0) {
file = fopen("leaderboard0.txt", "r+");
} else if (leaderboard.diff == 1) {
file = fopen("leaderboard1.txt", "r+");
} else if (leaderboard.diff == 2) {
file = fopen("leaderboard2.txt", "r+");
}
fseek( file, 1, SEEK_SET );
old[0] = leaderboard;
for (int i = 1; i < 6; i++) {
fscanf(file, "%i %i %s", old[i].diff, old[i].turn_count, old[i].name);
}
for (int i = 0; i < 6; i++) {
for (int j = i + 1; j < 6; j++) {
if (old[i].turn_count > old[j].turn_count) {
temp = old[i];
old[i] = old[j];
old[j] = temp;
}
}
}
for (int i = 0; i < 5; i++) {
fprintf(file, "%i %i %s\n", old[i].diff, old[i].turn_count, old[i].name);
fclose(file); /* this is the obvious error, it should go below this loop */
}
fclose(file); /* here it should be */
}
It would be probably best to rename leaderboard to leader and after that to rename old to leaderboard.
I already mentioned the need to move the fclose call outside of the loop. You close the file after your first write.
I don't understand your first use of fseek( file, 1, SEEK_SET );: Why do you skip the first character of the file? (File offsets start at 0 not 1). Also: After a successfull fopen, the file pointer always points to the beginning of the file.
After you read your leaderboard, you should fclose the file, and reopen it for (over-)writing. (Better keep a backup, if the leader board is important). So: Open "r" for reading, read, close, open "w" for writing, write, close.
You don't do any error checking in your code. You should fix that and inform the user on error and try to handle the error as gracefully as possible. (I.e. do not loose your leaderboard if writing fails.)
Concerning the added part 1982289408 0: Make sure, your new leader (struct `leaderboardĀ“) is properly initialized).
Your algorithm has a slight problem: A new player, who was exactly as good as a previous one, will move that previous one out of the leader board. To fix that, load the file into old[0..4] and put new leader into old[5] (instead of putting him in old[0] and the file content in old[1..5])
Minor imporovement: The sorting loop: for (int i = 0; i < 6; i++) for (int j = i + 1; j < 6; j++)-> thefor iloop only needs to run from 0 .. 4, sofor (int i = 0; i < 5; i++)` would suffice.

array of strings printing wrong values

I trying to make a program that calculates proper prefixes and proper suffixes , and then compare the sets , and then return the array containing values representing number of matched
pairs , This could be used later in KMP algorithm .
But the problem is prefixes and suffixes array give wrong values .
Even after appending a new element at new index, it replaces the all value in the array with the new element .
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int* lps(char *,int );
int main()
{
char *pat = "abababca";
int *ptr ;
ptr = lps(pat,strlen(pat));
printf("\n***LPS***\n");
}
int * lps (char *p,int s)
{
char *prefixes[s] ;
char *suffixes[s] ;
char tmp1[s] , tmp2[s];
int i , j , k , c1 , c2 , c;
for (i = 0 ; i < s ; i ++)
{
printf("\n\n*** --- Creating Prefixes and Suffixes for i = %d --- ***",i);
c1 = 0 ;
//create prefixes
for (j = 0 ; j < i; j++)
{
for (k =0 ; k <= j; k++)
{
tmp1[k]=*(p+k);
printf("\n *(p+%d)= %c , tmp1[%d]=%c",k,*(p+k),k,tmp1[k]);
}
tmp1[k]='\0';
printf("\nprefixes[0]:%s",prefixes[0]);
prefixes[c1] = tmp1;
//strcpy(prefixes[c1], tmp1);
printf("\ncurrently added %s to prefixes at %d and prefixes[%d]= %s\n ",tmp1,c1,c1,prefixes[c1]);
c1++;
}
//print prefixes
for (k = 0; k<c1; k++)
{
printf("\tprefixes[%d] = %s",k,prefixes[k]);
}
printf("\n");
//create suffixes
c2 = 0;
for (j = 1 ; j <= i; j++)
{
for (k = j ; k <= i; k++)
{
tmp2[k-j] = *((p+k));
printf("\n *(p+%d)= %c , tmp2[%d]=%c",k,*(p+k),k-j,tmp2[k-j]);
}
tmp2[k-j]='\0';
suffixes[c2] = tmp2 ;
// strcpy(suffixes[c2], tmp2);
printf("\ncurrently added %s to suffixes at %d and suffixes[%d]= %s\n",tmp2,c2,c2,suffixes[c2]);
c2++;
}
//prinf suffixes
for (k = 0; k<c2; k++)
{
printf("\tsuffixes[%d] = %s",k,suffixes[k]);
}
printf("\n");
//compare the prefixes and suffixes
c = 0 ;
for (j = 0; j < c1; j++)
{
for(k=0 ; k < c2 ; k++)
{
printf("\nprefixes[%d] = %s , suffixes[%d] = %s\n ",j,prefixes[j],k,suffixes[k]);
if (strcmp(prefixes[j], suffixes[k])==0)
{
c = c + 1 ;
}
}
}
}
}
OUTPUT (Some part of OUTPUT) :-
prefixes[0] = ab prefixes[1] = ab //it should be prefixes[0] = a prefixes[1] = ab
The problem is that you aren't allocating any strings. The only strings that you have in lps are tmp1 and tmp2. You then make assignments like this:
prefixes[c1] = tmp1;
That assigns a pointer but does not copy the contents of the string. You'll end up with every entry in prefixes pointing to the same string, tmp1. And likewise for suffixes.
You'll need to use malloc and strcpy to make new string instances.
In the code you have commented out calls to strcpy. I suspect you tried these and encountered runtime errors. Those runtime errors were because you did not allocate any memory. The corrected code would look like:
prefixes[c1] = malloc(strlen(tmp1)+1);
strcpy(prefixes[c1], tmp1);
And similarly for suffixes.
In production quality code you'd include error checking. And you'd want to make sure that you call free() on any pointer returned by the calls malloc(), once you had finished with it.
I'd also question the use of C variable length arrays, VLAs. In your code, prefixes, suffixes, tmp1 and tmp2 are all VLAs. Using VLAs can readily lead to stack overflow if you have large array dimensions. My instincts say that heap allocation is what you need here.

Resources