So I created an array which is saved in a file. I have the number 4 printed out 100 times in the file. Now everytime the an element in the array is accessed it the value will decrease by 1. So if A[1] = 4 is accessed then it will become A[1] = 3 and be saved on the file. The thing is I can't save the modified array to the file.
I already tried moving the placement of FILE pointer.
void buildingB4()
{
system("CLS");
FILE *input, *output;
int i, B4[100], room;
input = fopen("B4.txt", "r");
if (input == NULL)
{
output = fopen("B4.txt", "w");
for (i = 1; i <= 100; i++)
{
B4[i] = 4;
fprintf(output, "%d\n", B4[i]);
}
fclose(output);
for (i = 1; i <= 100; i++)
{
if (i % 10 == 0)
{
printf("\n\n");
}
printf("B-4-%d(%d)\t", i, B4[i]);
}
}
else
{
for (i = 1; i <= 100; i++)
{
fscanf(input, "%d\n", &B4[i]);
if (i % 10 == 0)
{
printf("\n\n");
}
printf("B-4-%d(%d)\t", i, B4[i]);
}
fclose(input);
printf("\nPlease choose a room:B-4-");
scanf("%d", &room);
B4[room] = B4[room] - 1;
output = fopen("B4.txt", "a");
fprintf(output, "%d\n", B4[i]);
studentDetails();
}
}
say if A[1] = 4
and when user input is 1, 1 is saved in a variable called room.
so A[room] = A[room] -1
so the result would be A[1] = 3 and it modify the A[1] saved in the file.
Use fclose after the line
fprintf(output, "%d\n", B4[i]);
I've found little mistakes in your code and here is your fixed code:
#define HOME_SIZE 100
void show_rooms(int B[]){
for (int i = 0; i < HOME_SIZE; i++){
if (i % 10 == 0){
printf("\n\n");
}
printf("B-4-%3d(%d) ", i + 1, B[i]);
}
}
void buildingB4()
{
FILE *input, *output;
input = fopen("B4.txt", "r");
unsigned int B[HOME_SIZE], room;
if (input == NULL){
fclose(input);
// Setting all homes to 4.
for (int i = 0; i < HOME_SIZE; ++i){
B[i] = 4;
}
output = fopen("B4.txt", "w");
for(int i = 0; i < HOME_SIZE; ++i)
fprintf(output, "%d\n", B[i]);
fclose(output);
show_rooms(B);
}
else{
for (int i = 0; i < HOME_SIZE; ++i){
fscanf(input, "%d", &B[i]);
}
fclose(input);
show_rooms(B);
printf("\nPlease choose a room:B-4-");
scanf("%d", &room);
if (room > 0 && room <= HOME_SIZE)
B[room - 1] -= 1;
output = fopen("B4.txt", "w");
for(int i = 0; i < HOME_SIZE; ++i)
fprintf(output, "%d\n", B[i]);
}
}
Notice that :
In C index starts from 0 not 1.
close using file after your work in order to save it properly.
Don't use '%d\n' format for scanf, it will ignore ' ' and '\n' automatically.
Tips for future development :
Try using feof function to know if your file is ended or not instead of using constant size for your inputs.
Related
I'm trying to scan integers from a file, then add them to an array. But every time I run the program I get a segmentation fault. Why is this?
int main(void) {
FILE *file;
int num_in;
int numbers[10000];
file = fopen("/Users/foo/aa/extra/sort/rand10k", "r");
if (file == NULL)
{
perror("Error opening and reading file\n");
return 1;
}
int i = 0;
while (fscanf(file, "%d", &num_in))
{
numbers[i] = num_in;
i++;
}
for (int i = 0; i < 10000; i++)
{
printf("%d\n", numbers[i]);
}
}
The file in question has 10,000 integers in random order:
The condition in the while loop is incorrect
while (fscanf(file, "%d", &num_in))
It is evaluated to true even when EOF occurs.
Instead you need to write
while ( i < 10000 && fscanf(file, "%d", &num_in) == 1 )
After that you should write for example
for (int j = 0; j < i; j++)
{
printf("%d\n", numbers[j]);
}
I need to sort my 2 text files for my project. One of the text files is in student id, course id and score format and the other is in student id's format. I wrote the values in both of them with fprintf, so I am using fscanf while reading, but my function is not working correctly, can you tell me where is my mistake?
(I deleted the old code that didn't work because I continued on a different code)
Edit :I tried to create a code snippet based on the solution below, but when I enter the while loop, fscanf starts to get the wrong numbers. Can you look for where my mistake is?
Edit :After editing here, I did the fopen checks. There is no problem with them. The while loop closes after it runs once, I think, in the if fscanf parts, fscanf does not read the number correctly, so it exits the loop with break.
most likely broken part:
FILE *index = fopen("index.txt", "r");
FILE *record = fopen("record.txt", "r");
if (!index)
return;
if (!record)
return;
int array[n][3];
//int *array = (int *)malloc(n *3 sizeof(int));???
int count = 0;
int i=0,temp,id,course,score;
while (1)
{
if(count==n) break;
if (fscanf(record, "%d", &id) != 1) break;
if (fscanf(record, "%d", &course) != 1) break;
if (fscanf(record, "%d", &score) != 1) break;
array[count][0] = id;
array[count][1] = course;
array[count][2] = score;
count++;
}
the rest of the function for you to browse if the error is elsewhere:
void sort_for_bin_search(int n)
{
FILE *index = fopen("index.txt", "r");
FILE *record = fopen("record.txt", "r");
if (!index)
return;
if (!record)
return;
int array[n][3];
//int *array = (int *)malloc(n *3 sizeof(int));???
int count = 0;
int i=0,temp,id,course,score;
while (1)
{
if(count==n) break;
if (fscanf(record, "%d", &id) != 1) break;
if (fscanf(record, "%d", &course) != 1) break;
if (fscanf(record, "%d", &score) != 1) break;
array[count][0] = id;
array[count][1] = course;
array[count][2] = score;
count++;
}
for (i = 1; i < n - 1; i++)
{
for (int j = 0; j < n - 1; j++)
{
if(array[i][0] > array [j][0])
{
temp=array[j][0];
array[j][0] = array[i][0];
array[i][0] = temp;
temp=array[j][1];
array[j][1] = array[i][1];
array[i][1] = temp;
temp=array[j][2];
array[j][2] = array[i][2];
array[i][2] = temp;
}
else if((array[i][0]==array[j][0])&&(array[i][1]>array[j][1]))
{
temp=array[j][0];
array[j][0] = array[i][0];
array[i][0] = temp;
temp=array[j][1];
array[j][1] = array[i][1];
array[i][1] = temp;
temp=array[j][2];
array[j][2] = array[i][2];
array[i][2] = temp;
}
}
}
fclose(record);
fclose(index);
FILE *index2 = fopen("index.txt", "w");
FILE *record2 = fopen("record.txt", "w");
for (i = 0; i < n; i++)
{
fprintf(index2,"%d\n",array[i][0]);
fprintf(record2,"%d %d %d\n",array[i][0],array[i][1],array[i][2]);
//printf("%d %d %d\n",array[i][0],array[i][1],array[i][2]);
}
//free(array);
fclose(record2);
fclose(index2);
}
It looks like you are doing a bubble sort, and in each iteration you read/write from disk. Disk operations are very slow. It is much easier and faster if you read once in to array. And then sort that single array.
Example:
void sort_for_bin_search(int n)
{
//assumes that `n` is the number of lines in this file
if (n < 1) return;
FILE* fin = fopen("index.txt", "r");
if (!fin)
return;
FILE* fout = fopen("record.txt", "w");
if (!fout)
return;
int* arr = malloc(n * sizeof(int));
if (!arr) return;
int count = 0;
while (1)
{
if (count == n)
break;
int id, course, score;
if (fscanf(fin, "%d", &id) != 1) break;
if (fscanf(fin, "%d", &course) != 1) break;
if (fscanf(fin, "%d", &score) != 1) break;
arr[count] = id;
count++;
}
//add code for sorting arr
for (int i = 0; i < count; i++)
fprintf(fout, "%d\n", arr[i]);
free(arr);
fclose(fin);
fclose(fout);
}
Then you can sort, for example using bubble sort.
Use printf to print the data on screen at each step, this will help with debugging.
void sort_for_bin_search(int n)
{
FILE* fin = fopen("input_file.txt", "r");
if (!fin)
{
printf("input error\n");
return;
}
int array[n][3];
int count = 0;
while (1)
{
int id, course, score;
if (count == n) break;
if (fscanf(fin, "%d", &id) != 1) break;
if (fscanf(fin, "%d", &course) != 1) break;
if (fscanf(fin, "%d", &score) != 1) break;
array[count][0] = id;
array[count][1] = course;
array[count][2] = score;
count++;
}
n = count;
printf("reading:\n");
for (int i = 0; i < n; i++)
printf("%d %d %d\n", array[i][0], array[i][1], array[i][2]);
printf("\nsort\n");
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n - 1 - i; j++)
{
if (array[j][0] > array[j + 1][0])
{
int temp;
temp = array[j][0];
array[j][0] = array[j + 1][0];
array[j + 1][0] = temp;
temp = array[j][1];
array[j][1] = array[j + 1][1];
array[j + 1][1] = temp;
temp = array[j][2];
array[j][2] = array[j + 1][2];
array[j + 1][2] = temp;
}
}
}
fclose(fin);
printf("sorted\n");
for(int i = 0; i < n; i++)
printf("%d %d %d\n", array[i][0], array[i][1], array[i][2]);
printf("write to file\n");
FILE* fout = fopen("output_file.txt", "w");
if(!fout)
{
printf("output error\n");
return;
}
for (int i = 0; i < n; i++)
fprintf(fout, "%d %d %d\n", array[i][0], array[i][1], array[i][2]);
fclose(fout);
}
A text file with names and results is put to a c program to be sorted by results. How do ignore false inserts like number 8 in the file below?
.txt code looks like this
Paul 35.6
Peter 53.4
Jack 23.0
8
Steph 0.0
Amanda 43.5
First array is arrayName[], second is arrayResult[], arrayFail[] is for 0.0 points.
#define ARRAYSIZE 15 // THIS IS THE MACRO FOR DEFINING THE ARRAY SIZE
#define STRSIZ 40 // THIS IS THE MACRO FOR DEFINING THE STRING SIZE
int main(){
/* Declaration of variables */
int i, j, n, f = 0;
float a, m =0;
char c;
/* Defining the arrays for names and results */
char arrayName[ARRAYSIZE][STRSIZ];
char arrayTemp[ARRAYSIZE][STRSIZ];
char arrayFail[ARRAYSIZE][STRSIZ];
float arrayResults[ARRAYSIZE];
n = ARRAYSIZE;
/* Code to open file and check list for validation */
FILE *fp;
fp = fopen("List.txt", "r"); //Opens the file
while ((c = fgetc(fp)) != EOF){
if (c == '\n')
m = m +1;
}
n = m;
// Close the file
fclose(fp);
/* Validates the name list */
while( n <= 0 || n > 15){
printf("\nThe list is invalid. It must be atleast one name and a maximum of 15 names. Please edit List.txt and re-run the program\n");
return 0;
}
/* Here the program scans the list from the text file */
for(i = 0; i < n; i++){
scanf("%s %f", arrayName[i], &arrayResults[i]);
}
/* Printing out the competitors list */
printf("The competitors: ");
for(i = 0; i < n - 1; i++){
printf("%s, ", arrayName[i]);
}
for(i = n - 1; i < n; i++){
printf("%s.", arrayName[i]);
}
/* The array is ordered */
for(i = 0; i < n; i++){
for(j = i + 1; j < n; j++){
if( arrayResults[i] < arrayResults[j]){
a = arrayResults[i];
strcpy(arrayTemp[i], arrayName[i]);
arrayResults[i] = arrayResults[j];
strcpy(arrayName[i], arrayName[j]);
arrayResults[j] = a;
strcpy(arrayName[j], arrayTemp[i]);
}
}
}
/* Printing out the Top 3 */
printf("\n\nThe Top 3:\n");
for(i = 0; i < 3; i++)
printf("No%d: %s with %.1f\n", i+1, arrayName[i], arrayResults[i]);
/* Failed competitors and their names are detected and stored */
for(i = 0; i < n; i++){
if( arrayResults[i] == 0 ){
strcpy(arrayFail[f], arrayName[i]);
f++;
}
}
/* Printing out the failed competitors */
printf("\nThe failed competitors were: ");
for(i = 0; i < f - 1; i++){
printf("%s, ", arrayFail[i]);
}
printf("%s.", arrayFail[f - 1]);
printf("\n");
return 0;
}
You could test the validity of each entry during the collection and bypass it when the test fails (you could adjust the test to your own goal, here we just test that the string is not empty) :
int countEntry = 0;
for(i = 0; i < n; i++){
scanf("%s %f", arrayName[i], &arrayResults[i]);
// If name or score is null, decrease i to ignore that entry
if (arrayName[i][0] == 0 || arrayResults[i][0] == 0) i--;
// Else counts the entry
else countEntry++;
}
Then you should control that there is at least one valid entry :
if(countEntry == 0) {
printf("\nThe list is invalid. It must be atleast one name. Please edit List.txt and re-run the program\n");
return 0;
}
When I execute my code I keep getting the right answers but it is printed multiple times? I want it display a table with with 5 columns and 3 rows and there should be 4 of these tables but I get three times too many and I don't know why?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(){
int w;
int n = 1;
int i;
for(w = 1; w < 5; w++){
FILE *myFile;
float numberArray[1];
if(n == 4){
myFile = fopen("input4.txt", "r");
n++;
}
if(n == 3){
myFile = fopen("input3.txt", "r");
n++;
}
if(n == 2){
myFile = fopen("input2.txt", "r");
n++;
}
if(n == 1){
myFile = fopen("input1.txt", "r");
n++;
}
if (myFile == NULL)
{
printf("Error Reading File\n");
exit (0);
}
printf("Enter 3 numbers between 0 and 9.999:\n");
printf("Number sin cos tan atan\n");
printf("-------------------------------------------\n");
for (i = 0; i < 3; i++)
{
fscanf(myFile, "%f,", &numberArray[i] );
}
for (i = 0; i < 3; i++)
{
printf("%.6f %.4f %.4f %.4f %.4f\n",numberArray[i], sin(numberArray[i]), cos(numberArray[i]), tan(numberArray[i]), atan(numberArray[i]));
}
fclose(myFile);
}
return 0;
}
You are reading and writing in unallocated memory space when accessing numberArray.
You defined numberArray[1] with a size of 1, yet you are accessing numberArray[1..2] in your loops here :
for (i = 0; i < 3; i++)
{
fscanf(myFile, "%f,", &numberArray[i] );
}
for (i = 0; i < 3; i++)
{
printf("%.6f %.4f %.4f %.4f %.4f\n",numberArray[i], sin(numberArray[i]), cos(numberArray[i]), tan(numberArray[i]), atan(numberArray[i]));
}
I have not tested your code, but this seems to be the most obvious culprit.
I have been working on this function for the past two days and I cant seem to figure it out. The function displayBoard() opens up a text file, in this case "board.txt" and places it into a 1D array. The code was provided by my professor. I made it into a function and tried to return the array board[] so I can manipulate it in main but I am unable to do it, What am I missing?
void displayBoard ()
{
FILE *pInputFile; // file pointer
char board[64]; // the 8x8 board
int i=0; // loop counter
char inputFileName[] = "board.txt";
// Associate the actual file name with file pointer and try to open it
pInputFile = fopen(inputFileName, "r");
// Verify input file was found
if (pInputFile == NULL) {
printf("Attempt to open file %s failed. Exiting ... \n", inputFileName);
exit( -1);
}
// Read from the file into the board. Space in front of %c is important!
while (fscanf(pInputFile, " %c", &board[i]) != EOF) {
i++;
}
fclose(pInputFile); // close input file
// show contents of board
printf("Board is: ");
for (i=0; i<64; i++) {
if (i%8 == 0) {
printf("\n");
}
printf("%c ", board[ i]);
}
printf("\n\n");
return board;
}
int main ()
{
printf(" %s", board); // This is my printf statement to see if I am able to access
// board[] from the function
}
You need to make the method return a char * by declaring the function
char * displayBoard {
...
}
You can not. You have to pass the array you want to modify using pointers and modify it inside the function.
#include <stdio.h>
void function(int b[][10], int m, int n){
int i = 0, j = 0;
for(i = 0; i < m; ++i){
for(j = 0; j < n; ++j){
b[i][j] = i + j;
}
}
}
int main(){
int board[10][10] = {0};
int i = 0, j = 0;
for(i = 0; i < 10; ++i){
for(j = 0; j < 10; ++j){
printf("%d ", board[i][j]);
}
printf("\n");
}
function(board, 10, 10);
for(i = 0; i < 10; ++i){
for(j = 0; j < 10; ++j){
printf("%d ", board[i][j]);
}
printf("\n");
}
return 0;
}
Ok I decided to part my function into 2, one to generate the board and one to to display the board, so I can just use displayBoard() whenever I want to re-display it in main.
void generateBoard (char board[]){
FILE *pInputFile; // file pointer
int i=0; // loop counter
char inputFileName[] = "board.txt";
// Associate the actual file name with file pointer and try to open it
pInputFile = fopen(inputFileName, "r");
// Verify input file was found
if( pInputFile == NULL) {
printf("Attempt to open file %s failed. Exiting ... \n", inputFileName);
exit( -1);
}
// Read from the file into the board. Space in front of %c is important!
while( fscanf(pInputFile, " %c", &board[ i]) != EOF) {
i++;
}
fclose( pInputFile); // close input file
}
void displayBoard (char board[]){
// show contents of board
printf("Board is: ");
int i;
for( i=0; i<64; i++) {
if( i%8 == 0) {
printf("\n");
}
printf("%c ", board[ i]);
}
printf("\n\n");
}
I have an update on my function, I am a first time user of this site so im not sure if I should be posting it here or on my OP. This is what I came up with
char* displayBoard (char board[]){
FILE *pInputFile; // file pointer
int i=0; // loop counter
char inputFileName[] = "board.txt";
// Associate the actual file name with file pointer and try to open it
pInputFile = fopen(inputFileName, "r");
// Verify input file was found
if( pInputFile == NULL) {
printf("Attempt to open file %s failed. Exiting ... \n", inputFileName);
exit( -1);
}
// Read from the file into the board. Space in front of %c is important!
while( fscanf(pInputFile, " %c", &board[ i]) != EOF) {
i++;
}
fclose( pInputFile); // close input file
// show contents of board
printf("Board is: ");
for( i=0; i<64; i++) {
if( i%8 == 0) {
printf("\n");
}
printf("%c ", board[ i]);
}
printf("\n\n");
return board;
}
When you write code returning results in an array, it is better to let the caller provide the array in which the code should return its results than to let the code allocate itself an array.
The reason for this is that pointer ownership transfers make it hard to reason about memory management, so it is better to keep their amount at a minimum.