allocate memory and read input from file to arrays of structures - c

I have question about reading data from file to structures
when I tried to run this code i get unhandled exception Access violation reading location 0xcccccce0, The error occur inside the getData function, Why am I getting this error, how Should I fix the code ?
this is my input file
4
A,10
B,12
C,60
D,120
tutorY
my intention in the getData function was to first read the first line to get then number 4, then use that number to allocate for student structure and then read the next four lines of the file in to student structure fields and then read the last line into tutorname feild in the TUTOR structure.
thank in advance
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "queue.h"
#include "stack.h"
#define RECORDS_SIZE 100
#define NAME_SIZE 20
typedef struct Student
{
char nameStudent[NAME_SIZE];
int TimeIn;
int TimeUpdate;
}STUDENT;
typedef struct TUTOR
{
char nameTutor[NAME_SIZE];
int TutorTIme;
STUDENT *ptr;
}TUTOR;
QUEUE *queue1;
STACK *stack1;
void getData(STUDENT *studentArr[RECORDS_SIZE], TUTOR tutorArr[1]);
int main (void)
{
STUDENT *studentArr[RECORDS_SIZE];
TUTOR tutorArr[1];
FILE *fp = NULL;
getData(studentArr, tutorArr);
return 0;
}
void getData(STUDENT *studentArr[RECORDS_SIZE], TUTOR tutorArr[1])
{
FILE *fp;
char fileName[NAME_SIZE];
char buffer[RECORDS_SIZE];
int first = 0;
int count = 1;
printf("Enter file name: ");
gets(fileName);
fp = fopen(fileName, "r");
if (fp == NULL)
{
printf("Error! The file does not exist!\n");
}
fscanf(fp,"%d",&first);
*studentArr = (STUDENT*) malloc(first*sizeof(STUDENT));
while( fgets(buffer, first +1, fp) != NULL)
{
if (count <= first)
{
sscanf(buffer, "%[,]%d", studentArr[count]->nameStudent, studentArr[count]->TimeIn);
printf("%s,%d", studentArr[count]->nameStudent, studentArr[count]->TimeIn);
}
else
sscanf(buffer, "%s", tutorArr[count].nameTutor);
count++;
}
return;
}

There's a couple of problems I have spotted.
The first fscanf reading first will read the first number then leave the rest of the line ("\n") to be picked up by the first call to fgets
More importantly, studentArr is an array of pointers, presumably one element for each student, but the malloc allocates only the first pointer in sudentArr, all the others contain garbage, which is causing the access violation.

fix like this
void getData(STUDENT **studentArr, TUTOR tutorArr[1]);//change
int main (void)
{
STUDENT *studentArr;//change
TUTOR tutorArr[1];
FILE *fp = NULL;//not use
getData(&studentArr, tutorArr);//change
return 0;
}
void getData(STUDENT **studentArr, TUTOR tutorArr[1])
{
FILE *fp;
char fileName[NAME_SIZE];
char buffer[RECORDS_SIZE];
int first = 0;
int count = 1;
printf("Enter file name: ");
gets(fileName);//has risk
fp = fopen(fileName, "r");
if (fp == NULL)
{
printf("Error! The file does not exist!\n");
return;//add, can't continue
}
fscanf(fp,"%d\n",&first);//add, consumption '\n'
*studentArr = (STUDENT*) malloc(first*sizeof(STUDENT));
while( fgets(buffer, RECORDS_SIZE, fp) != NULL)//change buffer size
{
if (count <=first)//
{
sscanf(buffer, "%[^,],%d", (*studentArr)[count-1].nameStudent, &(*studentArr)[count-1].TimeIn);//add, `,` and -1 to count is 1 origin, `&` need for "%d"
printf("%s,%d\n", (*studentArr)[count-1].nameStudent, (*studentArr)[count-1].TimeIn);
++count;//need count up
}
else
sscanf(buffer, "%s", tutorArr[0].nameTutor);
}
return;//need allocate record size return to main
}

Some more problems:
count should be initialised to 0 not 1 because your array is zero-indexed.
You're not incrementing count in your loop
Allocate memory for each student inside the loop with studentArr[count] = new Student();
Prefer strtok to sscanf` to split the buffer into fields. Much easier to deal with the comma following the string.

Related

Using a struct and dynamically allocated memory to write all the lines from a text file in C

I have written a program in C to represent a quiz game. Each question is an individual line of a text file. I am using a struct to represent the array of questions. It begins by taking some user input, then counts the amount of text lines in the file. It then allocated the amount of memory needed for the structs before reading each line of the file into the struct. When I print out the elements in the struct it prints out 20 lines of errors instead of the file values. What am I doing incorrectly? I have included a screenshot of some of lines of the file also.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define filepath "Questions_Answers"
#define CAPACITY 120
typedef struct
{
char* questions;
} Lines;
int setupGame(int *difficulty);
int main() {
int difficulty; //Set difficulty out of ten of the quiz
int numberOfLines = 0; //Set the number of lines counted in the file initially to zero
int question_length;
char answer[20];
char c;
//Calls setup game function which sets the difficulty
difficulty = setupGame(&difficulty);
FILE* fPointer = fopen(filepath, "r"); //Points to the address of a File not yet known
//If the file has no content, print error and end program
if (fPointer == NULL) {
perror("Error opening file");
return -1;
}
// Extract characters from file and store in character c
for (c = getc(fPointer); c != EOF; c = getc(fPointer)) {
if (c == '\n') // Increment count if this character is newline
numberOfLines++;
}
numberOfLines = numberOfLines + 1;
printf("Number of questions in quiz - %d\n", numberOfLines);
Lines *lines = malloc(sizeof(Lines) * numberOfLines); // allocate memory for questions
for (int i = 0; i < numberOfLines; i++) {
int lengthOfQuestion = 150;
lines[i].questions = malloc(sizeof(char) * (lengthOfQuestion + 1));
fscanf(fPointer, "%s", lines[i].questions);
printf("%s\n", lines[i].questions);
}
fclose(fPointer);
for (int i = 0; i < numberOfLines; i++) {
free(lines[i].questions);
}
free(lines);
return 0;
}
You have to fclose(fPointer); then reopen before you want to get questions from the file.
fclose(fPointer);
fPointer = fopen("input.txt", "r");
fscanf reads word by word not whole the line. You should use fgets() or getline().
I see in your code, you init the length of all questions by 150
int lengthOfQuestion = 150;
So, i think, it's easier when you declare the struct (you can use pointer if you want):
typedef struct
{
char questions[150];
} Lines;
You should use one loop for storing and increasing the number of lines. The code will be more readable. For example:
char line[150];
lines = malloc(sizeof(Lines));
if(!lines) {// handle the error}
while (fgets(fPointer, sizeof(line), line)) {
strcpy(lines[numberOfLines].question, line);
numberOfLines++;
lines = realloc(lines, sizeof(Lines) * numberOfLines);
if(!line) {// handle the error}
}

strstr() causing a segmentation fault error

The objective here is to take a whole text file that I dump into a buffer and then use the strcasestr() function to find the pointer of the word I am looking for within my buffer. It constantly gives me the segmentation fault error. At first, I thought it may be size so I tried with smaller sizes but it doesn't work either. The function only works with strings I create inside the actual code (ex : char * bob = "bob"; char * bobsentence = "bob is cool"; strstr(bobsentence, bob);). Which leads me to believe it has something to do with the fgets(). Any help is appreciated, really stuck on this one.
#define _GNU_SOURCE //to use strcasestr
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void textEdit(char *path, char *word){
printf("%s\n", path);
FILE *textFile;
//FILE *locationFile;
//FILE *tempFile;
char counter[1024];
int count = 0;
textFile = fopen(path, "r+");
//locationFile = fopen(path, "r+");
//opens file to read and write and opens temp file to write
if( textFile == NULL){ //|| tempFile == NULL || locationFile == NULL) ) {
printf ("\nerror\n");
return;
}
// SECTION : ALLOCATES MEMORY NEEDED FOR COPY TEXT IN ARRAY
// finds number of lines to estimate total size of array needed for buffer
while((fgets(counter, sizeof(counter), textFile)) != NULL){
count++;
}
fclose(textFile);
FILE *tempFile = fopen(path, "r+");
count *= 1024;
printf("%d %zu\n",count, sizeof(char));
char *buffer = malloc(count); //1024 is the max number of characters per line in a traditional txt
if(buffer == NULL){ //error with malloc
return;
}
// SECTION : DUMPS TEXT INTO ARRAY
if(fgets(buffer, count, tempFile) == NULL){
printf("error");
} //dumps all text into array
printf("%s\n", buffer);
char * searchedWord;
while((searchedWord = strcasestr(buffer, word)) != NULL){
}
fclose(tempFile);
//fclose(locationFile);
free(buffer);
}
It looks that you forgot to initialize count variable to 0:
int count = 0;
You increment it and it can contain any random value, even negative.
Also, note that your utilization of strstr doesn't look correct. The function returns the pointer to first occurrence that matches. Note, that it doesn't remember already found matches, so if match exists it should loop forever in this loop. Instead it should look like:
char *pos = buffer;
while((pos = strcasestr(pos, word)) != NULL){
searchedWord = pos;
/* do something with searchedWord but remember that it belongs to
allocated buffer and can't be used after free() */
pos++;
}

Script reads only even lines of file

I have a script in C that reads a file structured in lines like this:
1,example,2,3;
2,exampl,3,5;
3,examp,7,4;
4,exam,9,1;
And the script is here:
while(fscanf(fptr,"%d,%[^/,],%d,%s", &m[i].id,m[i].nojm,&m[i].salar,m[i].phon) != EOF) {
fscanf(fptr,"%d,%[^/,],%d,%s;", &m[i].id,m[i].nojm,&m[i].salar,m[i].phon);
printf("%d,%s,%d,%s\n", m[i].id,m[i].nojm,m[i].salar,m[i].phon);
i++;
}
The problem I have is, that it reads only even lines of the file (2nd, 4th, 6th, 8th)...
How should I edit the code so it would read all lines?
Thanks for any help.
UPDATE1:
void nacti(emp *p,int n)
{
FILE *fptr;
fptr=fopen("ulozka.txt","r");
if(fptr==NULL){
printf("Error opening file!");
getchar();
}
typedef struct
{
int id;
char nojm[32];
int salar;
char phon[32];
} data_t;
int i = 0;
data_t m[4];
while(fscanf(fptr,"%d,%[^/,],%d,%s", &m[i].id,m[i].nojm,&m[i].salar,m[i].phon) != EOF) {
printf("%d,%s,%d,%s\n", m[i].id,m[i].nojm,m[i].salar,m[i].phon);
i++;
}
printf("%d,%s,%d,%s\n", m[4].id,m[4].nojm,m[4].salar,m[4].phon);
//printf("%d",pocet);
}
If there is only m[4], the code will only read 4 lines of the file? How should I edit it to read "indefinit" number of lines?
Your code should be replaced with the following:
while(fscanf(fptr,"%d,%[^/,],%d,%s", &m[i].id,m[i].nojm,&m[i].salar,m[i].phon) != EOF) {
printf("%d,%s,%d,%s\n", m[i].id,m[i].nojm,m[i].salar,m[i].phon);
i++;
}
The fscanf call in the while loop condition will be executed every loop iteration, so you don't need to call it again inside the loop.
UPDATE:
The following solution works for me. You can try it here.
#include <stdio.h>
typedef struct
{
int id;
char nojm[32];
int salar;
char phon[32];
} data_t;
int main(void) {
int i = 0;
data_t m[4];
while(fscanf(stdin,"%d,%[^/,],%d,%s", &m[i].id,m[i].nojm,&m[i].salar,m[i].phon) != EOF) {
printf("%d,%s,%d,%s\n", m[i].id,m[i].nojm,m[i].salar,m[i].phon);
i++;
}
return 0;
}
I'm guessing the reason you're receiving a runtime error is that the character arrays you're using for strings (nojm and phon) are not long enough to process some of the entries in your text file, so memory is getting overwritten. Try increasing whatever length you're using to make sure it's greater than the longest string you'll encounter in your text file.
Another possibility is that you don't have enough items in your array to read in all the data from the text file. Here, I have a static array of 4 items to support the 4 from the text file. If your text file contains, say, 10,000 items you need to make sure you've properly allocated memory to store all of that.
You have
while(fscanf(fptr,"%d,%[^/,],%d,%s", &m[i].id,m[i].nojm,&m[i].salar,m[i].phon) != EOF) {
fscanf(fptr,"%d,%[^/,],%d,%s;", &m[i].id,m[i].nojm,&m[i].salar,m[i].phon);
printf("%d,%s,%d,%s\n", m[i].id,m[i].nojm,m[i].salar,m[i].phon);
i++;
}
So you:
read with fscanf()
read with fscanf()
print what you read
As a result you print only what the second fscanf read. Delete the second one and you should be fine.
So, your code should be like this:
while(fscanf(fptr,"%d,%[^/,],%d,%s", &m[i].id,m[i].nojm,&m[i].salar,m[i].phon) != EOF) {
printf("%d,%s,%d,%s\n", m[i].id,m[i].nojm,m[i].salar,m[i].phon);
i++;
}
I see that you have problems compiling your code. I suspect that your code is relevant to my example, it might help.
#include <stdio.h>
#include <string.h>
/* Define the struct before main. */
struct person {
char phon[20];
int id;
};
// Give a synonym. Now struct person is the same with person_t.
typedef struct person person_t;
int main(void) {
person_t array[3]; // can hold 3 persons
FILE* fptr = NULL;
fptr = fopen("test.txt", "r");
int i = 0;
while (fscanf(fptr, "%d, %s", &array[i].id, array[i].phon) != EOF) {
printf("%d, %s\n", array[i].id, array[i].phon);
i++;
}
return 0;
}
and the test.txt
1, 697555555
2, 697888888
3, 694777777

Issues with structs in C

I have an array in a struct. I'm reading from a file into a string. I use strtok to get the first few characters, and i want to pass the rest of the line into the struct, to eventually be passed into a thread. I'm getting the following error:
incompatible types when assigning to type char[1024] from type char *
Referring to the line indicated below with the comments. It probably has to do with how i'm trying to copy character arrays, but i'm not sure on a better way.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <linux/input.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
typedef struct
{
int period; //stores the total period of the thread
int priority; // stores the priority
char pline[1024]; // stores entire line of text to be sorted in function.
}PeriodicThreadContents;
int main(int argc, char* argv[])
{
//opening file, and testing for success
//file must be in test folder
FILE *fp;
fp = fopen("../test/Input.txt", "r");
if (fp == NULL)
{
fprintf(stderr, "Can't open input file in.list!\n");
exit(1);
}
char line[1024];
fgets(line, sizeof(line), fp);
//getting first line of text, containing
char *task_count_read = strtok(line," /n");
char *duration_read = strtok(NULL, " /n");
//converting char's to integers
int task_count = atoi(task_count_read);
int i = 0;
PeriodicThreadContents pcontents;
printf("started threads \n");
while (i < task_count)
{
fgets(line, sizeof (line), fp);
strtok(line," ");
if (line[0] == 'P')
{
char *period_read = strtok(NULL, " ");
pcontents.period = atoi(period_read);
printf("%d",pcontents.period);
printf("\n");
char *priority_read = strtok(NULL, " ");
pcontents.priority = atoi(priority_read);
printf("%d",pcontents.priority);
printf("\n");
printf("\n%s",line);
memcpy(&(pcontents.pline[0]),&line,1024);
printf("%s",pcontents.pline);
}
}
return 0;
}
C cannot handle strings as other languages do. C doesn't have string assignments or comparisons without using auxiliary functions.
In order to copy a string in a buffer you can use:
strcpy(pcontents.pline, line);
Or even (to have a warranty that your string is not longer than 1024 bytes):
memcpy(pcontents.pline, line, 1024);
pcontents.pline[1023] = '\0';
For other string operations check: http://www.gnu.org/software/libc/manual/html_node/String-and-Array-Utilities.html#String-and-Array-Utilities
You need to copy the chars from the buffer into pcontents.pline (assuming pcontents is a PeriodicThreadContents).
strcpy(pcontents.pline, strtok(NULL, " "));

read data from file into array of structures

Hi I'm trying to read data from file into array of structures I tried to use fgets but got the error saying that RECORD type cannot be convert to char* this is what i have so far
#include <stdio.h>
#include <stdlib.h>
#define MAX_NAME 20
#define FILE_NAME 50
#define LIST_SIZE 50
//void getData(RECORD name[], RECORD score)
typedef struct RECORD
{
char *name;
float score;
}RECORD;
int main (void)
{
// Declarations
FILE *fp;
char fileName[FILE_NAME];
RECORD list[LIST_SIZE];
int count = 0;
// Statements
printf("Enter the file name: ");
gets(fileName);
fp = fopen(fileName, "r");
if(fp == NULL)
printf("Error cannot open the file!\n");
while (fgets(list[count], LIST_SIZE, fp) != NULL)
{
count++;
}
return 0;
}
the error occurs in the fgets statement inside while loop, how can i fix this and read data into array of structures?
thank in advance
fgets is used to input a string from a text file one line as a unit.
e.g.)
char input_line_buff[128];
fgets(input_line_buff, 128, fp);
read-in
input_line_buff:(contents eg) "name 66.6\n"
you do split , memory alloc and copy, and convert .
e.g.)
list[count].name = strdup("name");
list[count].score= atof("66.6");
count++;
Try this,
while(fgets((char *)list[count], SIZE/* data size to be read */, fp) != NULL)
{...}

Resources