Trouble Finding Where I'm Going Wrong While Reading this Text File - c

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.

Related

In C, how can I pass the strings from a file into a string array. Notice that main objective is to order the students with respect to their id

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);
}

c: Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

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 */
}

How do I cast /copy from a char array so that I may store it in a char pointer array?

I'm working on a project that involves reading and /or writing from a text file. Currently the only data I'm attempting to extract from the text file are names. My goal is to be able to store specific names in a character pointer array such that Char[n] will have a name assigned to it for any given n in the array.
The problem I seem to be having is that I'm setting my character pointer element to another character array where I'm storing the read value from the text file.
For example, if I read a name from the text file and set Name[] equal to that name then later set Char[0] = Name then Char[0] will always change when Name does.
I've attempted to write the string directly to Char[0], for example, but then my program crashes just after I attempt to read and store the value. Therefore, I've resorted to this convoluted route of assigning a separate character array to the name I scan and setting one of my elements to it.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
FILE * inf = fopen("UserNames.txt", "r");
char User[125];
int err, TopNameNumber = 10;
char *UserNames[TopNameNumber];
if (inf == NULL)
{
printf("ERROR: No name file detected.");
return 0;
}
for(int i = 0; i < TopNameNumber i++)
{
//This reads from my .txt file
err = fscanf(inf, " %s", User);
if(err == EOF)
break;
//This shows me what user was read from the text file
printf("User read %d: %s\n", i+1, User);
//Program assigns the pointer address of User to Names[i]
//This is where I'm having trouble
UserNames[i] = User;
}
for(int c = 0; c < 3; c++)
{
// This always just prints out the last name read from the .txt file
for every name
printf("Name #%d: %s\n", c, UserNames[c]);
}
return 0;
}
I've been at this for a few days and I've found some interesting avenues which could possibly solve my problem, such as copying the string with strcpy() function, or perhaps casting User to something. All to no avail so far, however.
I would appreciate any advice as to what you think is the best solution to pursue if the solution isn't obvious here. I would like to avoid doing everything character by character, but I suppose I would be willing to in the long run.
I apologize for perhaps an unclear question, this is my first time asking one, and I'm just trying to give as much context as possible :)
My code compiles with no warnings or errors as of right now.
the blatant error I see is here:
//Program assigns the pointer address of User to Names[i]
//This is where I'm having trouble
UserNames[i] = User;
reusing the same buffer for all usernames isn't going to fly. On the other hand, you cannot use strcpy because no memory is allocated. You can use strdup which allocates & copies the string.
UserNames[i] = strdup(User);
or for the purists (since strdup isn't strictly in the standard):
UserNames[i] = malloc(strlen(User)+1);
strcpy(UserNames[i],User);
As a security side-note, since the buffer is 125 bytes long, I suggest limiting the input it can accept to 124+nul-termination:
err = fscanf(inf, " %124s", User);
Of course, you need to deallocate the strings when no longer used, or you'll get memory leaks if your program doesn't quit or is part of a bigger code.
free(UserNames[i]); // in a loop in the end, when no longer needed
You need to allocate memory for a separate char[] for each name you read from the file.
For example:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main() {
FILE *inf = fopen("UserNames.txt", "r");
if (inf == NULL) {
printf("ERROR: No name file detected.");
return 0;
}
int err, c = 0;
const int TopNameNumber = 10;
char UserNames[TopNameNumber][125];
for(int i = 0; i < TopNameNumber; i++) {
err = fscanf(inf, " %124s", UserNames[c]);
if (err == EOF)
break;
printf("User read %d: %s\n", c+1, UserNames[c]);
++c;
}
fclose(inf);
for(int i = 0; i < c; i++) {
printf("Name #%d: %s\n", i, UserNames[i]);
}
return 0;
}
Alternatively:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main() {
FILE *inf = fopen("UserNames.txt", "r");
if (inf == NULL) {
printf("ERROR: No name file detected.");
return 0;
}
char User[125];
int err, c = 0;
const int TopNameNumber = 10;
char* UserNames[TopNameNumber];
for(int i = 0; i < TopNameNumber; i++) {
err = fscanf(inf, " %124s", User);
if (err == EOF)
break;
printf("User read %d: %s\n", c+1, User);
UserNames[c] = malloc(strlen(User) + 1);
if (UserNames[c] == NULL) {
printf("ERROR: Memory allocation failed.");
break;
}
strcpy(UserNames[c], User);
++c;
}
fclose(inf);
for(int i = 0; i < c; i++) {
printf("Name #%d: %s\n", i, UserNames[i]);
}
for(int i = 0; i < c; i++) {
free(UserNames[i]);
}
return 0;
}

How do I get the file to print to the screen?

I am trying to get the data from quiz_scores.txt to print to the screen so I can scan it into an array but I don't know how. Do I need to hard-code the file into my program and if so how?
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
int main(void)
{
//initializing variables
FILE *es;
FILE *hs;
int num=0;
int i;
int j;
int cols=10;
int rows=10;
int qid, s;
int quizarray[0][0];
int MAX_LENGTH=15;
char *result0;
char line[MAX_LENGTH];
FILE *qs="C:\\quiz_scores.txt";
qs = fopen("quiz_scores.txt", "r");
/*for (i=0; i<cols; i++){
for (j=0; j<rows; j++){
quizarray[i][j]=0;
fscanf(qs, "%d%d", quizarray[i][j]);
}
}
*/
while(fgets(line, MAX_LENGTH, qs))
{
printf("%s", line);
}
if(qs == NULL)
{
printf("Error: Could not open file\n");
return -1;
}
/*for (i=0;i<n;i++)
{
fprintf(qs, "%d\n");
}
fclose(qs);*/
return 0;
}
OK I think I know what you want to happen, read numbers from the file quiz_scores.txt into your 2d array and print them,correct?. I hope these corrections will allow you to do just that and also that you will understand why it wouldn't work before. The rest of the program is for you to do yourself, good luck!!
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
int main(void)
{
//initializing variables
int num=0,i,j,cols=10,rows=10;//just smooshed all onto the same line cause it was annoying me
int quizarray[10][10];//You declared a 2d array with 0 elements(you wanted one with ten rows and columns I presume 10 teams 10 rounds)
FILE *qs = fopen("quiz_scores.txt", "r");//Your declaration of the file pointer was incorrect
if(qs == NULL)//This if needs to go before you read anything from the file otherwise its kind of redundant
{
printf("Error: Could not open file\n");
return -1;
}
for (i=0; i<cols; i++)
{
for (j=0; j<rows; j++)
{
quizarray[i][j]=0;
fscanf(qs,"%d", &quizarray[i][j]);//Them scanfs need &s mate
\\and don't try to scan in two integer into one array element
printf("%d",quizarray[i][j]);
if(j<rows-1)
printf("-");
}
printf("\n");
}
fclose(qs);//Dont comment fclose out bad things will happen :P
return 0;
}

copying text to a character array from a text file in C?

Hey there, How do I go about copying text inside a text file into a multidimensional character array?
supposing the text file( text_file.txt) contained
this is the first line
this is the second line
this is the third line
#include <stdio.h>
int main(void){
FILE *f;
f=fopen("text_file.txt","r");
if (f==NULL){
printf("invalid!");
return 1;
}
else {
printf("successful");
}
char copied_text[80][80];
while (!feof(f)){
int i=0,j=0;
fgets(copied_text[i][j],"%s",f);
i++;
}
return 0;
}
-thank you.
I think your code almost work.
Just move the declaration of int i out of the loop.
Change the first parameter of fgets to copied_text[i] because it needs a pointer here.
Change the second parameter of fgets to 80 because it should be a int indicates the acceptable string length.
#include <stdio.h>
int main(void){
FILE *f;
f=fopen("text_file.txt","r");
if (f==NULL){
printf("invalid!\n");
return 1;
}
else {
printf("successful\n");
}
char copied_text[80][80];
int i=0;
while (!feof(f)){
fgets(copied_text[i],80,f);
++i;
}
for(int i = 0; i <3; ++i)
printf("%s\n", copied_text[i]);
return 0;
}

Resources