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
Related
Hi need a little bit of help here. I have a file with 5 lines and I want to put this lines into an array of type char *lines[5]; but I can't figure it out why the following isn't working.
#include <stdio.h>
#include <string.h>
int main(void) {
FILE *fp = fopen("name.txt", "r");
char *str;
char *list[5];
int i = 0;
while (fgets(str, 100, fp) != NULL) // read line of text
{
printf("%s", str);
strcpy(list[i], str);
i++;
}
}
As the commenters stated, you need to create an array (which is nothing more than a space in the memory) of a sufficient size to store your string. One approach to solve your problems is the following, note the comments:
#include <stdio.h>
#include <string.h>
int lines(FILE *file); //try to format the code according to some standard
int main(void) {
FILE *fp = fopen("name.txt", "r");
char list[5][100]; //make sure you allocate enough space for your message
// for loop is more elegant than while loop in this case,
// as you have an index which increases anyway.
// also, you can make sure that files with more than 5 lines
// do not break your program.
for(int i = 0; i<5 ;++i )
{
if(fgets(list[i], 100, fp) == NULL){
break;
}
//list[i] is already a string, you don't need an extra copy
printf("%s", list[i]);
}
}
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}
}
Hi first of all let me be precise, I have a data file in following format:
The first line contains a string followed by three integers and a float data type.
The second line contains string with a space followed by three integers and a float data type.
The last row contains a string followed by three integers and a float data type.
My aim is to read these data and assign to an array of structure, a structure in an array contains one row with string, 3 integers and one float number.
I tied using the following code and got succeeded to read a line where string has no space, but cannot read string with spaces:
void readFromDatabase(struct student temp[], int *no) {
FILE *filepointer;
int i = 0;
if ((filepointer = fopen("database", "r")) == NULL) {
printf("Read error");
return;
}
while (fscanf(filepointer, "%10s\t%d%d%d%f\n", temp[i].name,
&temp[i].birthday.date, &temp[i].birthday.month,
&temp[i].birthday.year, &temp[i].gpa) != EOF && i < MAX_CLASS_SIZE) {
++i;
}
*no = i;
fclose(filepointer);
}
I got the follwing output which was unexpected:
I was trying to loop through the structure array and display the data in above format.
But instead of getting 3 rows of output i got 4 rows.
I really need some help on this topic.
Thanks in advance...
And i am using gcc under ubuntu 16.04 for compiling and executing the program..
In your fscanf format string, use %10[^\t] instead of %10s. This matches each character of the name until the tabulator separator.
Unfortunately, you did not give a full example, so this is my small program to test on Ubuntu 16.04:
#include <stdio.h>
#include <stdlib.h>
#define MAX_CLASS_SIZE 4
struct student {
char name[11];
struct {
int date;
int month;
int year;
} birthday;
float gpa;
};
int main(void) {
FILE *filepointer;
int i = 0;
int no;
struct student temp[MAX_CLASS_SIZE];
if ((filepointer = fopen("data.txt", "r")) == NULL) {
printf("Read error");
return EXIT_FAILURE;
}
while (fscanf(filepointer, "%10[^\t]\t%d%d%d%f\n", temp[i].name,
&temp[i].birthday.date, &temp[i].birthday.month,
&temp[i].birthday.year, &temp[i].gpa) != EOF && i < MAX_CLASS_SIZE) {
++i;
}
no = i;
fclose(filepointer);
for(i = 0; i < no; i++) {
printf("%s: %d-%d-%d %f\n",
temp[i].name,
temp[i].birthday.date, temp[i].birthday.month, temp[i].birthday.year,
temp[i].gpa
);
}
return EXIT_SUCCESS;
}
Based on your format string, I am assuming that all values in your database are separated by tabulators.
i am trying to sipmply input some data into a struct from a file.
I have used the same excact code in a different program and it works as it should?
I dont know where i am wrong.
Shouldnt the code below work ? Maybe i am not that familiar with sscanf .I would like some help. Thank you.
The txt file is like this:
foo.var 1241
poa.org 421
aeraf.gr 5456
oiggdf.po 98843
Code:
struct filedata
{
char fname[50];
int fsize;
};
int main()
{
char line[60];
int i=0;
int numberoffiles=0;
int lines=0;
int ch=0;
FILE *fp = fopen("mytext.txt","r");
while ((ch = fgetc(fp)) != EOF)
{
if (ch == '\n')
lines++;
}
struct filedata file[lines];
numberoffiles=lines + 1;
if(fp == (FILE*)NULL)
{
fprintf(stderr,"Cannot Open File\n");
exit (-1);
}
else
{
while (fgets(line,60,fp)!=NULL)
{
sscanf(line,"%s %d",file[i].fname,&file[i].fsize);
i++;
}
}
}
Your loop that counts the number of lines reads the entire file so that the current position is at the end of the file when you begin your second loop. Consider using rewind() before your second loop to move back to the start of the file.
Also, your test to see if fp is NULL should go right after the open() call. Otherwise, your code that reads the number of lines will fail.
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.