I am making a program that can make an array from user input and save it inside a csv files. Then the user is able to perform matrix and vector operations with the stored arrays. When i started working with csv files(initially on clion) i started getting the error: "Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)" After debugging i found the error "EXC_BAD_ACCESS (code=2, address=0x7ff7b202dff8)" . However the program still worked when ran in replit. Sadly though after i wrote lines 60 -65 in order to make a different csv file every time the function is ran i started getting the error: "signal: segmentation fault (core dumped) " on replit. What could be causing these errors? Here is my code on replit:
"https://replit.com/#iasonaszak/the-matrix#main.c"
Thank you in advance for your help!!
and here is my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "time.h"
#include <math.h>
#include <stdbool.h>
int a;
char c[20];
int num;
bool b = true;
int main() {
while (b ==true){
void create_array();
void delete_array();
int user_answer;
time_t t;
srand((unsigned) time(&t));
printf(
" 1.create an array\n 2.load an array\n 3.Show available arrays\n 4.Delete array\n 5.Vector operations \n 6.Matrix operations"
) ;
printf("Please choose one of the following options!\n");
scanf("%d" , &user_answer);
if (user_answer == 1){
create_array( );
}
else if (user_answer == 4){
delete_array();
}
return 0;
}
}
void create_array(){
int rows;
int cols;
int i;
int j;
int matrix[i][j];
printf("how many columns would you like your array to have");
scanf("%d" ,&cols );
printf("how many rows would you like your array to have");
scanf("%d" ,&rows );
char filename[80];
FILE *fout = fopen(filename, "wt");
FILE *last = fopen("lastnum.csv" , "w");
fgets(c , 20 , last);
num = atoi(c);
snprintf(filename, sizeof(filename), "prefix.%d.csv", num);
for (i = 0 ; i < rows; i ++){
printf("\n");
fprintf(fout , "\n");
for (j = 0 ; j < cols; j ++){
scanf("%d", &matrix[i][j]);
char str[(int)((ceil(log10(matrix[i][j]))+1)*sizeof(char))];
sprintf(str , "%d " , matrix[i][j]);
fprintf(fout ,"%s" , str);
}
}
printf("Your array was saved successfuly inside a csv file");
num++;
}
void delete_array(){
remove("prefix.0.csv");
remove("prefix.1.csv");
remove("prefix.2.csv");
remove("prefix.3.csv");
remove("prefix.4.csv");
remove("prefix.5.csv");
remove("prefix.6.csv");
remove("prefix.7.csv");
remove("prefix.8.csv");
remove("prefix.9.csv");
printf("all arrays were deleted");
}
void preview_arrays(){
FILE *F0 = fopen("prefix.0.csv" , "r");
}
These three lines will cause a problem:
char str[(int)((ceil(log10(matrix[i][j]))+1)*sizeof(char))];
sprintf(str , "%d " , matrix[i][j]);
fprintf(fout ,"%s" , str);
The expression (int)((ceil(log10(matrix[i][j])) + 1 will produce 1 from a matrix value of 1, but char str[1]; won't be enough for the nul-terminated string.
And when the matrix value is <= 0 the logarithm is undefined. In my test with 0 it attempted to define char str[-2147483648];
You don't use str for anything else, so I suggest you remove those three lines and use this one simple line instead:
fprintf(fout,"%d ", matrix[i][j]);
Update
Another fault is in the file opening: wrong mode
FILE *last = fopen("lastnum.csv" , "w");
should be
FILE *last = fopen("lastnum.csv" , "r");
and always check that fopen() succeeds!
if(fout == NULL) {
/* handle error */
}
if(last == NULL) {
/* handle error */
}
and always check that fgets() succeeds too.
if(fgets(c , sizeof c , last)) == NULL) { // changed the 'magic' 20
/* handle error */
}
Related
The program given below is equalize all name and surname with last ones. The contents of the students.dat ;
2020102054 Name1 Surname1
2021202051 Name2 Surname2
2020302057 Name3 Surname3
2020802053 Name4 Surname4
2020602059 Name5 Surname5
2019452065 Name6 Surname6
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *stdFptr, *orderFptr;
int student_id ,temp_id[20],ordered_id[20], a=0,i,j;
char student_name[32], student_surname[32];
char *ordered_name[32],*ordered_surname[32],*temp_string[32];
stdFptr = fopen("students.dat","r");
orderFptr = fopen("order.dat","w");
if(!stdFptr || !orderFptr){
puts("File Error, Exiting The Program");
exit(0);
}
else{
puts("Before ordering");
fscanf(stdFptr, "%d %s %s ",&student_id,student_name,student_surname);
while(!feof(stdFptr)){
ordered_name[a] = student_name;
ordered_surname[a] = student_surname;
ordered_id[a] = student_id;
a++;
fprintf(stdout,"%d %s %s\n",student_id,student_name,student_surname);
fscanf(stdFptr, "%d %s %s ",&student_id,student_name,student_surname);
}
ordered_name[a] = student_name;
ordered_surname[a] = student_surname;
ordered_id[a] = student_id;
fprintf(stdout,"%d %s %s\n",student_id,student_name,student_surname);
for(i=0;i<a;i++){
for(j=i+1;j<=a;j++){
if(ordered_id[i]>ordered_id[j]){
temp_string[i] = ordered_name[i];
ordered_name[i] = ordered_name[j];
ordered_name[j] = temp_string[i];
temp_string[i] = ordered_surname[i];
ordered_surname[i] = ordered_surname[j];
ordered_surname[j] = temp_string[i];
temp_id[i] = ordered_id[i];
ordered_id[i] = ordered_id[j];
ordered_id[j] = temp_id[i];
}
}
}
rewind(stdFptr);
fclose(stdFptr);
}
stdFptr = fopen("students.dat","r");
if(!stdFptr || !orderFptr){
puts("File Error, Exiting The Program");
exit(0);
}
else{
puts("After ordering");
i=0;
while(i<=a){
fprintf(orderFptr,"%d\t%s\t\t\t%s\n",ordered_id[i],ordered_name[i],ordered_surname[i]);
fprintf(stdout,"%d %s %s\n",ordered_id[i],ordered_name[i],ordered_surname[i]);
i++;
}
fclose(stdFptr);
fclose(orderFptr);
}
return 0;
}
You have multiple errors in your program.
Errors:
ordered_name[a] = student_name;
You only have pointers in your array. And you only have one single array for the name. That means you just assign the address of the same array to each of your entries in ordered_name. Same for the other fields.
while(!feof(stdFptr)){
Just don't do this. See Why is “while ( !feof (file) )” always wrong? why this is wrong.
temp_id[i] = ordered_id[i];
You use array temp_id to swap your array entries.
First of all, that is very inefficient as you only need a single variable, not an array.
Second, this is wrong because you only have 20 elements in temp_id and ordered_id but 32 elements in the other ordered* arrays.
Also you do not care about the number of entries in your file and might overflow both arrays.
Bad practice:
int student_id ,temp_id[20],ordered_id[20], a=0,i,j;
char student_name[32], student_surname[32];
char *ordered_name[32],*ordered_surname[32],*temp_string[32];
You are using corresponding arrays to store each field of your data sets. That is terrible to maintain.
Use a struct instead:
#define NAME_LENGTH 32
#define MAX_NUMBER 50
struct student {
int id;
char name[NAME_LENGTH];
char surname[NAME_LENGTH];
};
fscanf(stdFptr, "%d %s %s ",&student_id,student_name,student_surname);
You do not check the result of fscanf which you should always do.
Even better, use fgets followed by sscanf to parse your content.
stdFptr = fopen("students.dat","r");
You open the file again after you already read all the content. That's not needed.
Your sorting is also inefficient:
for(i=0;i<a;i++){
for(j=i+1;j<=a;j++){
if(ordered_id[i]>ordered_id[j]){
This can be used to fully sort an unsorted array.
You do this for each new line. Therefore you can rely on the array being sorted. You onle need to find the place where to put the new entry. For this, a single loop would be sufficient.
Or you can move that sorting after you have finished reading the file.
You exit your program in case of an error but you don't report an error to the calling environment
exit(0);
That is same as exit(EXIT_SUCCESS);. If terminate due to an error, you should also indicate that condition.
An improved version could look like this:
#include <stdio.h>
#include <stdlib.h>
#define NAME_LENGTH 32
#define MAX_NUMBER 50
struct student {
int id;
char name[NAME_LENGTH];
char surname[NAME_LENGTH];
};
int main(void)
{
struct student students[MAX_NUMBER];
int count = 0;
FILE *infile = fopen("students.dat","r");
if (infile == NULL) {
fprintf(stderr, "Input file cannot be openend.");
exit(EXIT_FAILURE);
}
// PART 1: Read the file content
puts("Before ordering");
char line[2*NAME_LENGTH + 20];
while (fgets(line, sizeof (line), infile) != NULL
&& count < MAX_NUMBER)
{
int result = sscanf(line, "%d %31s %31s", &students[count].id, students[count].name, students[count].surname);
if (result != 3)
{
fprintf(stderr, "Invalid line ignored: <%s>", line);
}
else
{
fprintf(stdout,"%d %s %s\n", students[count].id, students[count].name, students[count].surname);
count++;
}
}
fclose(infile);
// PART 2: Sort the array
struct student temp;
for (int i = 0; i < count-1; i++) {
for (int j = i+1; j < count; j++) {
if (students[i].id > students[j].id) {
temp = students[i];
students[i] = students[j];
students[j] = temp;
}
}
}
// Note: You could also just use qsort() function from standard library.
// PART 3: Write to output file
FILE *outfile = fopen("order.dat","w");
if (outfile == NULL) {
fprintf(stderr, "Output file cannot be openend.");
exit(EXIT_FAILURE);
}
puts("After ordering");
for (int i=0; i < count; i++) {
fprintf(outfile,"%d\t%s\t\t\t%s\n", students[i].id, students[i].name, students[i].surname);
fprintf(stdout,"%d %s %s\n", students[i].id, students[i].name, students[i].surname);
}
fclose(outfile);
}
I am new to C and need some help, when I execute this code, the output shows "Floating point exception (core dumped)" instead of a number which I don't know what it could be. I don't really know what is wrong with my code since I am a total beginner with Linux and C. Every help is appreciated.
Here is my functions.c:
#include "header.h"
int count(FILE *file){
int count=0,n;
char word[WORDS];
while(fscanf(file,"%s",word)==1 ){
count++;
};
return count;
};
int total(FILE *file){
int numbers, sum=0;
int token;
while(token!=EOF){
token=fscanf(file,"%d",&numbers);
sum+=numbers;
};
return sum;
};
and here is my main.c:
#include "header.h"
int main(){
char word[WORDS];
char theFile[WORDS];
FILE *fileptr;
printf("Enter the file name: ");
scanf("%s",theFile);
printf("Reading file %s...\n", theFile);
fileptr=fopen(theFile,"r");
if(fileptr==NULL){
fprintf(stderr,"ERROR: The file '%s' does not exist\n", theFile);
return 1;
};
int theSum=total(fileptr);
int theCount=count(fileptr);
int theMean= theSum/theCount;
printf("Average weight: %d \n", theMean);
return 0;
};
The main reason for getting Floating point exception is that you are accessing the file beyond its size.
In function total and count you are using the same pointer, so when done with total the file pointer is at the end of file, and you are using the same in count also.
you need to do fseek(file,SEEK_SET,0);, to make the pointer point at the beginning.
and all of you block statements and functions are end by ;, thats wrong.
I have corrected the program as a whole assuming that the contents of the file are just numbers like this 1 2 3 4 5 6
#include <stdio.h>
#define WORDS 100
int count(FILE *file){
int count = 0,n;
char word[WORDS];
// you need this to access the elements from start of the file
// comment below line causes sigfpe, Floating point exception
fseek(file,SEEK_SET,0);
printf(" position of fptr in count = %d\n",ftell(file));
while(fscanf(file,"%s",word)==1 ){
count++;
}
return count;
}
int total( FILE *file ){
int numbers, sum = 0;
int token;
// This is checked after number is read, will add the last number 2 times
//while(token != EOF){
while(1)
{
token = fscanf(file,"%d",&numbers);
printf("N = %d, token = %d\n", numbers, token);
if(token == EOF )
break;
sum += numbers;
}
printf(" position of fptr in total at the end = %d, sum = %d\n",ftell(file), sum);
return sum;
}
int main(){
char word[WORDS];
char theFile[WORDS];
FILE *fileptr;
printf("Enter the file name: ");
scanf("%s",theFile);
printf("Reading file %s...\n", theFile);
fileptr=fopen(theFile,"r");
if(fileptr == NULL){
fprintf(stderr,"ERROR: The file '%s' does not exist\n", theFile);
return 1;
}
int theSum = total(fileptr);
int theCount = count(fileptr);
//make sure to add a check that `theCount` is not zero
int theMean = theSum/theCount;
printf("Average weight: %d \n", theMean);
return 0;
}
In this statement
int theMean= theSum/theCount;
when theCount is 0 you are dividing by zero, which is undefined behavior and is probably causing the FPE.
I have this function that saves in an integer variable all the numbers from a text file. But I want to make a change so that I can save just the second number in each line into a vector and then print the whole vector. Here is an example of the file.txt:
123 19
321 18
432 9
876 16
875 17
And here is the code that must be changed:
void LerVetor(int *V, int *N)
{
FILE *fp;
int marks;
fp = fopen("dados3.txt", "r");
if (fp == NULL)
printf("Falha ao abrir ficheiro\n");
rewind(fp);
do
{
fscanf(fp, "%d", &marks);
printf("%d\n", marks);
} while (!feof(fp));
fclose(fp);
}
The output is the same as the file.txt because the code just prints the content of the file.
Resume: Save just the second numbers of each line, ex: 19, 18, 9..., in a vector and then print the vector.
the following proposed code:
cleanly compiles
groups the variables with where they are used
properly checks and handles I/O errors
read/displays the second number from each line of the file
performs the desired functionality
and now, the proposed code:
#include <stdio.h>
#include <stdlib.h>
void LerVetor( void )
{
FILE *fp = fopen("dados3.txt", "r");
if( !fp )
{
perror("fopen to read: dados3.txt failed");
exit( EXIT_FAILURE );
}
int marks;
int dummy;
while( fscanf(fp, "%d %d", &dummy, &marks) == 2 )
{
printf("%d\n", marks);
}
fclose(fp);
}
One way you can do it is to pass a pointer to the vector (array of ints) where you need to store the values as a parameter of the function.
To dispose the first value in every line you can use a discard specifier %*d:
Live sample
#include <stdio.h>
void LerVetor(int* vector)
{
FILE *fp;
if (!(fp = fopen("dados3.txt", "r"))){
perror("Falha ao abrir ficheiro"); //print eventual open file error
return;
}
// keep reading lines discarding first value with %*d avoiding container overflow
for(int i = 0; fscanf(fp, "%*d %d", &vector[i]) == 1 && i < 100; i++)
printf("%d\n", vector[i]); //printing vector values
fclose(fp);
}
int main(void)
{
int vector[100];
LerVetor(vector);
return 0;
}
I'm currently working on a program that simulates various CPU scheduling methods. Currently I have the program asking for input:
printf("Enter type of CPU scheduling algorithm (SJF, RR, PR_noPREMP, PR_withPREMP): ");
scanf("%s", typeOf);
printf("Enter number of processes: ");
scanf("%d", &numPro);
struct processStruct structs[numPro];
int burstTimes[numPro];
for (i = 0; i < numPro; i++) {
printf("Enter process number: ");
scanf("%d", &structs[i].pNum);
printf("Enter arrival time: ");
scanf("%d", &structs[i].arTime);
printf("Enter CPU burst time: ");
scanf("%d", &structs[i].cpuBur);
printf("Enter priority: ");
scanf("%d", &structs[i].prio);
}
In addition to the two variables typeOf (an int) and numPro (a char array) I am also using a data structure.
Here is the data structure that is holding the various parameters:
struct processStruct {
int pNum;
int arTime;
int cpuBur;
int prio;
int waitTim;
};
Instead of manual input I could like to use a text file with the same information as input for the program. The text file would look something like this:
SJF
4
1 0 6 1
2 0 8 1
3 0 7 1
4 0 3 1
First line is the name of the scheduling algorithm.
Second line is the number of processes.
The following lines consists of information for each process. So 1 0 6 1 = Process = 1, 0 = Arrival Time, 6 = CPU burst time, 1 = Priority
I unfortunately have little experience using text file input with C. Does anyone have ideas about how I could read in the data from the text file into the variables and data structure?
Thank you
Edit: One of the issues I am having is that the data is not the same for each line. If it was just the rows of 4 numbers then it would be relatively easy. I need the program to read the first line into a char array (string), the second into the numPro variable then the subsequent lines into multiple instances of the data structure (one for each process).
The file can be read fairly simply with fscanf() because everything except the first line identifier is a number. But you do need to check the validity of what is read from the file. I have just used exit(1) on error for illustration, it could be more sophisticated than that (for example an error message).
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
struct processStruct {
int pNum;
int arTime;
int cpuBur;
int prio;
int waitTim;
};
struct processStruct structs[MAX];
int main(int argc, char** args)
{
FILE *fil;
char typeOf[4];
int numPro, i;
if ((fil = fopen("myfile.txt", "rt")) == NULL)
exit(1);
if(fscanf(fil, "%4s", typeOf) != 1)
exit(1);
if(fscanf(fil, "%d", &numPro) != 1)
exit(1);
if(numPro > MAX)
exit(1);
for(i=0; i<numPro; i++) {
if(fscanf(fil, "%d%d%d%d", &structs[i].pNum, &structs[i].arTime,
&structs[i].cpuBur, &structs[i].prio) != 4)
exit(1);
}
fclose(fil);
// test the result
printf("Type: %s\n", typeOf);
printf("Num: %d\n", numPro);
for(i=0; i<numPro; i++) {
printf("%d %d %d %d\n", structs[i].pNum, structs[i].arTime,
structs[i].cpuBur, structs[i].prio);
}
return 0;
}
Program output:
Type: SJF
Num: 4
1 0 6 1
2 0 8 1
3 0 7 1
4 0 3 1
You will want to use fscanf and fprintf instead of scanf and printf to do I/O from/to files instead of standard input/output.
These are widely documented. You will use FILE * variables and fopen & fclose. You can even use stdin, stdout, and stderr as handles for the console.
The best way to read lines in a file with C is to use the getline() function. It is much more reliable than scanf() and can allocate the needed memory automagically.
Here is the code I suggest:
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char **argv)
{
FILE *inputfile;
if (argc < 2)
{
fprintf (stderr, "error: missing file name in the arguments\n");
exit (EXIT_FAILURE);
}
inputfile = fopen (argv[1], "r");
if (!inputfile)
{
perror ("myprogram");
exit (EXIT_FAILURE);
}
/* Getting first line */
char *line = NULL;
size_t line_size = 0;
if (!getline(&line, &line_size, inputfile))
{
fprintf (stderr, "error: failed to read first line\n");
exit (EXIT_FAILURE);
}
/* Getting the size of the matrix */
unsigned int size; /* Size of the matrix */
if (sscanf (line, "%zd", &size) != 1)
{
fprintf (stderr, "error: first line has wrong format\n");
exit (EXIT_FAILURE);
}
/* Getting the content of the matrix */
int matrix[size][size];
for (unsigned int i = 0; i < size; i++)
{
if (!getline (&line, &line_size, inputfile))
{
fprintf (stderr, "error: input file has wrong format\n");
exit (EXIT_FAILURE);
}
/* Copying the items of the line to the matrix */
char *ptr = line;
for (unsigned j = 0; j < size; j++)
{
matrix[i][j] = atoi(strtok(ptr, " "));
ptr = NULL;
}
}
free(line);
return EXIT_SUCCESS;
}
Beware, I didn't tried this code... So, if something is not working properly, I'll fix it.
I wrote this code to read in the following line from a text file:
1019*/passed// 56.)100,/ 82//10 however when I print it afetr the sscanf function I only get the 1019 and the number 10 correctly , rest have garbage values , any idea why? I'd appreciate if someone could correct me, I even tried putting %d instead of just %[..] in the sscanf function but stil doesnt print out the desired values.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ()
{
char buffer[100];
char status[20];
int grades[4]= {0};
int id;
int j;
int k;
int temp;
FILE *pointer = fopen ("testing5.txt", "r");
if((pointer = fopen("testing5.txt", "r"))!= NULL)
{
printf("No error, file successfully opened\n you may contine :)\n");
}
else
{printf("file could not be opened\nterminating program,...\n");
return 0;}
fgets(buffer,100,pointer);
printf("%s\n", buffer);
sscanf(buffer,"%[^*/]*/%[^//]//%[^.).)]%[^,/],/ %[^//]//%d",&id,status, &grades[0],&grades[1],&grades[2],&grades[3]);
printf("%d\n%s\n%d\n%d\n%d\n%d",id,status, grades[0],grades[1],grades[2],grades[3]);
for (j =0; j<3; j++)
for(k =j+1; k<4;k++)
{
if(grades[j]<grades[k] )
{
temp = grades[j];
grades[j] = grades[k];
grades[k] = temp;
}
}
printf("\nthe grades in ascending order is \n");
for (j =0; j<4; j++)
{
printf("%d\n", grades[j]);
}
return 0;
}
sscanf("1019*/passed// 56.)100,/ 82//10\n", "%d*/%[^/]// %d.)%d,/ %d//%d",
&id, status, &grades[0],&grades[1],&grades[2],&grades[3]);
Change
int grades[4]= {0}
to
char grades[4] = { 0 };
The warning output is pointing out the problem, don't ignore it. You are passing the wrong data types to sscanf.