File display error C - c

I am trying to display a file with in the command prompt window, but the problem is that the output has random 0s in it, however, it always has the right formatting and right amount of rows and spaces. The problem is not the file. If you have any ideas, I'll greatly appreacite it. I have no leads at the moment.
void one (void)
{
FILE *fptr;
fptr = fopen("C:\z.txt","r+");
int j, h;
printf("How many elements?");
scanf("%d",&h);
if (fptr==NULL)
{
printf("Error!");
exit(1);
}
//fread(a, sizeof(struct book),1,fptr);
for (j = 0 ; j < h ; j++)
{
//fprintf(stdout, "%s\t%s\t%s\t%.2f\t%.2f\t%.2f\t%d\t%d\t%.2f\t\n",a[j].company,a[j].model,a[j].colour,a[j].cost,a[j].price,a[j].value,a[j].stock,a[j].sold,a[j].profit);
fscanf(fptr,"%s\t%s\t%s\t%.2f\t%.2f\t%.2f\t%d\t%d\t%.2f\t\n",
a[j].company,
a[j].model,
a[j].colour,
&a[j].cost,
&a[j].price,
&a[j].value,
&a[j].stock,
&a[j].sold,
&a[j].profit
);
}
fclose(fptr);
//getch();
for (j = 0 ; j < h ; j++)
{
printf("%s\t%s\t%s\t%.2f\t%.2f\t%.2f\t%d\t%d\t%.2f\t\n",
a[j].company,
a[j].model,
a[j].colour,
a[j].cost,
a[j].price,
a[j].value,
a[j].stock,
a[j].sold,
a[j].profit
);
}
}

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.

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.

C Bubble Sort Integer Array - Output Issue

Newbie Here.
For my C programming class, I'm required to use bubble sort to sort a list that's read from an input .txt file. Each line on the .txt file has a year, name, and states affected by a hurricane [year] [name] [states].
Ex:
1999 Floyd NC
2003 Isabel NC, VA
2004 Charley FL, SC, NC
2004 Frances FL
...etc.
The program needs to sort the list by year while keeping all the data lines correct (keep the relative array elements together). My integer array bubble sort works fine except for one issue- one line of data is off to the side of the list. Here's an example output of this issue:
1960 Donna FL, NC
1969 Camille MS 1972 Agnes FL
1983 Alicia TX
2004 Charley FL, SC, NC
The 1972 Agnes FL line is almost correct, but for some reason prints off to the side rather than right under the previous line.
Code:
#include <stdio.h>
#include <string.h>
#define MAX_HURCS 30
int main() {
FILE *hurricaneData;
int year[MAX_HURCS];
char name[MAX_HURCS][50];
char states[MAX_HURCS][50];
int i = 0, j;
int count = 0;
int sort;
int tempYear;
char tempName[50];
char tempStates[50];
if ((hurricaneData = fopen("hurricanes2.txt", "r")) == NULL) {
printf("Error: Could not open file");
}
while ((fscanf(hurricaneData, "%d %s", &year[i], &name[i]) != EOF)
&& (fgets(states[i], 50, hurricaneData) != NULL)) {
i++;
count++;
}
for (i = 0; i < count - 1; i++) {
for (j = 0; j < count - 1 - i; j++) {
if (year[j] > year[j + 1]) {
tempYear = year[j];
year[j] = year[j+1];
year[j+1] = tempYear;
strcpy(tempName, name[j]);
strcpy(name[j], name[j+1]);
strcpy(name[j+1], tempName);
strcpy(tempStates, states[j]);
strcpy(states[j], states[j+1]);
strcpy(states[j+1], tempStates);
}
}
}
for (i = 0; i < count; i++) {
printf(" \t%d\t%s\t%s ", year[i], name[i], states[i]);
}
return 0;
}
I've also tried this for the sorting algorithm, but I come across this same issue:
for (i = 0; i < count; i++) {
for (j = 0; j < count; j++) {
if (year[j] > year[i]) {
tempYear = year[i];
year[i] = year[j];
year[j] = tempYear;
strcpy(tempName, name[i]);
strcpy(name[i], name[j]);
strcpy(name[j], tempName);
strcpy(tempStates, states[i]);
strcpy(states[i], states[j]);
strcpy(states[j], tempStates);
}
}
}
I think the error is that your last line in your file does not have a end of line character so it reads upto end of file and when it print the same line it does not move to next line so either go to last line in your text file and put a endl in the last line or print a endl manually for each line. Another or more generic way would be to remove new line from your input, that can be done like this, while reading text do this
int len = strlen(states[i]);
if(len>0 && states[i][len-1] == '\n')
{
states[i][len-1] = '\0';
}
this will remove all new line and then you can print them manually in printf

How I can sum columns of different files in C?

I have 8 files (file%d-%d.dat) each with 2 columns and 1000 rows:
File1-1 File1-2 File1-3 File1-4
x1a y1a x1b y1b x1c y1c x1d y1d
x2a y2a x2b y2b x2c y2c x2d y2d
x3a y3a x3b y3b x3c y3c x3d y3d
. . . .
. . . .
File2-1 File2-2 File2-3 File2-4
x1e y1e x1f y1f x1g y1g x1h y1h
x2e y2e x2f y2f x2g y2g x2h y2h
x3e y3e x3f y3f x3g y3g x3h y3h
. . . .
. . . .
I want to sum the second column of each file File%d-1 row by row and write the sum in a new file: Filesum1; same for File%d-2 and so on, i.e.,
Filesum1 Filesum2 and so on ..
x1a+x1e y1a+y1e x1b+x1f y1b+y1f .
x2a+x3e y2a+y2e x2b+x2f y2b+y2f .
. . . .
. . . . .
I created 4 new files:
#include <stdio.h>
int main(void)
{
int numfiles=4;
int numfileread=8;
int i,yy1, yy2, x0, x1;
FILE *files[numfiles];
FILE *f[numfileread];
for (int n = 0; n < 4; n++)
{
char filename[4];
sprintf(filename, "filesum%d.dat", n);
files[n] = fopen(filename, "w");
}
Then I've tried this, but it does not work correctly:
for (int n = 0; n < 4; n++)
{
yy1=0;
yy2=0;
for(int r=1;r<4;r++)
{
char file[8];
sprintf(file, "file%d-%d.dat", r, n);
f[i] = fopen(file, "r");
fscanf(f," %d %d",&x0,&x1);
yy1+=x0;
yy2+=x1;
fclose(f);
i++;
}
fprintf(files,"%d %d\n",yy1, yy2);
fclose(files);
}
If I had the same assignment, but for reading 50 files:
readFile1, readFile2, readFile3, ......., readFile50
How can I change the code?
There are multiple issue:
This loop will only three times, I think you intended it to run 4 times.
for(int r=1;r<4;r++)
Char array file does not has sufficient space to hold string "file%d-%d.dat"
fclose(f); needs to be changed to fclose(f[i]);
You need to specify an index for files.
fprintf(files,"%d %d\n",yy1, yy2);
This is what I came up with. You can try it out.
#include <stdio.h>
int main(){
FILE *readFile1;
FILE *readFile2;
FILE *writeFile;
char inFile1[32] = {0};
char inFile2[32] = {0};
char sumFile[32] = {0};
int i,xa,xb,ya,yb;
int ret1;ret2;
for(i=0;i<4;i++){
sprintf(inFile1, "File1-%d", i);
sprintf(inFile2, "File2-%d", i);
sprintf(sumFile, "sumFile%d", i);
readFile1 = fopen(inFile1, "r");
readFile2 = fopen(inFile2, "r");
writeFile = fopen(sumFile, "w");
while(1){
ret1 = fscanf(readFile1, "%d %d", &xa, &ya);
ret2 = fscanf(readFile2, "%d %d", &xb, &yb);
if( (ret1 != 2) || (ret2 != 2) )
break;
fprintf(writeFile, "%d %d", xa+xb, ya+yb);
}
fclose(readFile1);
fclose(readFile2);
fclose(writeFile);
}
return 1;
}
Okay, so you have a large number of files and want to sum two columns of data over these files. You also know that you will have 1000 rows of data in each file. You could try to keep all files open with an array of file handles and read from them in turn, but that's too complicated. Instead:
define an array for each column and initialise it to zero;
open one file at a time, read the data, add it to the array and close that file;
write the summed data to the results file.
There will always be at most one open file with this solution.
The code would look like this:
#include <stdlib.h>
#include <stdio.h>
enum {
nData = 1000, // number of rows
nFiles = 50, // number of files per block
nBlocks = 4 // number of blocks
// nomenclature: file{file}-{block}.dat
};
int main(void)
{
for (int j = 0; j < nBlocks; j++) {
double col1[nData] = {0.0};
double col2[nData] = {0.0};
char outn[32];
FILE *out;
for (int i = 0; i < nFiles; i++) {
char fn[32];
FILE *f;
snprintf(fn, sizeof(fn), "file%d-%d.dat", i, j);
f = fopen(fn, "r");
if (f == NULL) {
fprintf(stderr, "Could not open '%s'.\n", fn);
exit(1);
}
for (int k = 0; k < nData; k++) {
char line[80];
double x, y;
if (fgets(line, sizeof(line), stdin) == NULL) break;
if (sscanf(line, "%lf %lf", &x, &y) != 2) continue;
col1[k] += x;
col2[k] += y;
}
fclose(f);
}
snprintf(outn, sizeof(outn), "filesum-%d.dat", j);
out = fopen(outn, "r");
if (out == NULL) {
fprintf(stderr, "Could not write to '%s'.\n", outn);
exit(1);
}
for (int k = 0; k < nData; k++) {
fprintf(out, " %15g %15g\n", col1[k], col2[k]);
}
fclose(out);
}
return 0;
}
Season to taste.

How can I merge N files

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.

Resources