I need to scan 3 strings and an integer from an already existing file, and save them each as an element in an array of structures. The file is formatted as such:
string1 string2 integer string3
string1 string2 integer string3
... and so on.
when fscanf-ing for them, it correctly scans string1, the integer, and string3. However, string2 always appears to create an error when scanning it, and when any of the string2's are printed, they are either cut off short, or have some odd ASCII symbol, like a question mark in a box; it also sometimes triggers the system "bell" sound.
I've tested collecting the strings through fscanf for each different one, and it is only the second one that ever messes up.
A stripped-down version of my code, highlighting the issue
struct carinfo
{
char name[10];
char make[15];
int number;
char color[10];
}car[4];
filepointer = fopen("file.txt", "r");
while(!feof(filepointer))
{
for(i=0;i<4;i++)
{
fscanf(filepointer, "%s %s %d %s", &car[i].name[10],
&car[i].make[15], &car[i].number, &car[i].color[10]);
printf("%s\n", &car[i].make[15]);
}
}
my expected result is that the second string will scan properly, and be stored in its entirety to its element in the array of structures; instead, the value is usually cut off (at around 2-3 characters instead of 15) and contain weird ASCII symbols.
Changing fscanf() function to this, will solve your issue.
Code
fscanf(filepointer, "%s %s %d %s", car[i].name,
car[i].make, &car[i].number, car[i].color);
You can find true way of using fscanf() in cplusplus.com:
char str [80];
FILE * pFile;
pFile = fopen ("myfile.txt","w+");
fscanf (pFile, "%s", str);
But as chris-dodd stated at comment section using feof(filepointer) inside while loop not correct.
This code below i correct it by using fscanf() return value.
I obtain this way in a stack overflow answer by lio
Complete version of your program
main.c
#include <stdio.h>
struct carinfo
{
char name[10];
char make[15];
int number;
char color[10];
}car[4];
int main(){
int i=0;
FILE* filepointer = fopen("file.txt", "r");
if(!filepointer){
printf("can't open file\n");
}
int ret=0;
do {
for(i=0;i<4;i++){
ret=fscanf(filepointer, "%s %s %d %s", &car[i].name,
&car[i].make, &car[i].number, &car[i].color);
printf("%s\n", &car[i].make);
}
} while (ret != EOF);
return 0;
}
file.txt
salam beshoma 10 daram
kee innak 15 inomikhonid!
Related
Could you help me with the creation of a text file as right now the *fp pointer to the file is returning NULL to the function fopen ?
Using the library errno.h and extern int errno I get "Value of errno: 22".
if (!fp)perror("fopen") gives me "Error opening file: Invalid argument".
In my main function I enter the name of the file:
void main()
{
float **x;
int i,j;
int l,c;
char name_file[30];
FILE *res;
/* some lines omitted */
printf("\nEnter the name of the file =>");
fflush (stdin);
fgets(name_file,30,stdin);
printf("Name of file : %s", name_file);
res=creation(name_file,l,c,x);
printf("\nThe created file\n");
readfile(res,name_file);
}
The function to create the text file:
FILE *creation(char *f_name,int l, int c, float **a) // l rows - c colums - a array
{ FILE *fp;
int i,j;
fp = fopen(f_name,"wt+"); // create for writing and reading
fflush(stdin);
/* The pointer to the file is NULL: */
if (!fp)perror("fopen"); // it's returning Invalid argument
printf("%d\n",fp); //0 ??
if(fp==NULL) { printf("File could not be created!\n"); exit(1); }
fflush(stdin);
for(i=0;i<l;i++)
{
for(j=0;j<c;j++)
{
fprintf(fp,"%3.2f",a[i][j]); // enter every score of the array in the text file
}
fprintf(fp,"\n");
}
return fp;
}
Function to read the file and check if it is correct:
**void readfile(FILE *fp,char *f_name)**
{
float a;
rewind(fp);
if(fp==NULL) { printf("File %s could not open\n",f_name); exit(1); }
while(fscanf(fp,"%3.2f",&a)!= EOF)
printf("\n%3.2f",a);
fclose(fp);
}
There are quite a few wrong things your code.
1.
The correct signatures of main are
int main(void);
int main(int argc, char **argv)
int main(int argc, char *argv[])
See What are the valid signatures for C's main() function?
2.
The behaviour of fflush(stdin) is undefined. See Using fflush(stdin).
fflush works with output buffers, it tells the OS that is should write
the buffered content. stdin is an input buffer, flushing makes no sense.
3.
Use fgets like this:
char name_file[30];
fgets(name_file, sizeof name_file, stdin);
It's more robust using sizeof name_file because this will give you always
the correct size. If you later change the declaration of name_file to
an char array with less than 30 spaces, but forget to change the size parameter in fgets, you
might end up with a buffer overflow.
4.
You are passing to creation the uninitialized pointer p that is pointing
to nowhere. In said function you cannot read nor write with the pointer a.
You need to allocate memory prior to the call of creation. At least judging
from the code you posted.
5.
fgets preserves the newline ('\n') character, so
name_file is containing the newline character. I really don't know if newline
is allowed in file names. I did a google search but found conflicting answers.
I don't think that you want to have newlines in your file names, anyway. It's
best to remove it before passing it to fopen (which might be the reason for
the error 22):
char name_file[30];
fgets(name_file, sizeof name_file, stdin);
int len = strlen(name_file);
if(name_file[len - 1] == '\n')
name_file[len - 1] = 0;
I have to write a program that will read text from a file, break it up into a struct, validate the sections to a certain criteria, then produce two new files; one with the clean data and one with the errors. So far i am up to the stage of breaking up the data from a file and storing it into a struct but it will only work for the first two variables.
the text is separated by colons and i need to put each section into the variables bellow
an example of the text file
0001:0002:0003:0021:CLS
here is my struct
struct packet{
int source;
int destination;
int type;
int port;
char data[50];
};
Bellow is whatworks fine, however as soon as i add another section to add data to the type variable, the program does not work.
fscanf(inFile, "%[^:]: %[^:]:", records[i].source, records[i].destination);
printf("%d - %s _ %s", i+1, records[i].source, records[i].destination);
However this does not work and i need it to. Well i need to expand upon it.
fscanf(inFile, "%[^:]: %[^:]: %[^:]:", records[i].source, records[i].destination, records[i].type);
printf("%d - %s _ %s _ %s", i+1, records[i].source, records[i].destination, records[i].type);
}
if i printf without inputting anything to the struct it displays null as i would expect because nothing is being stored so im thinking that there is something wrong with the fscanf function. As it works for the first two, i dont think that it is a syntax issue so it must be a memory issue. I have used malloc and realloc but ive gotten confused with it and im sure that i have not done it right.
Full Code Listing
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//declaration of function which will print my name and student number
const char * myname();
//declaration of a function that will prompt a user to enter a file and open it if it exists
int openfile();
struct packet{
int source;
int destination;
int type;
int port;
char data[50];
};
int main()
{
int recordCount = 0;
struct packet *records;
records =malloc(sizeof(struct packet));
// printing the my name and student number via the myname function
printf("%s\n", myname());
//executing the openfile function that will open a function
openfile(recordCount, records);
return 0;
}
const char * myname()
{
const char *x = "*************************\nUSERNAME\nUSER NUMBER\nCONTACT NUMBER\n*************************\n";
return x;
}
int openfile(int rCount, struct packet *records)
{
//file pointer which will keep track of the file being accessed
FILE *inFile ;
//creating variable that will hold what the user has entered for a filename to open
char inFileName[100] = { '\0'};
printf("Please Enter the File to open:");
//getting the users input and storing it into the variable just created
scanf("%s", inFileName);
//if the file does not exist, display an appropriate error message
if ((inFile = fopen(inFileName, "r")) == NULL)
{
printf("Cannot Open File **%s**\n", inFileName) ;
exit(1) ;
}
else {
//if the file does exist, process the data
while(fgets(inFileName, 100, inFile)!=NULL)
{
int i =0;
for (i=0; i<30;i++)
{
fscanf(inFile, "%[^:]: %[^:]: %[^:]:", records[i].source, records[i].destination, records[i].type);
printf("%d - %s _ %s _ %s", i+1, records[i].source, records[i].destination, records[i].type);
}
}
//close the file
fclose(inFile);
return 0;
}
};
You're doing it wrong:
fscanf(inFile, "%[^:]: %[^:]:", records[i].source, records[i].destination);
The %[] conversion specifier is for string, but you're passing the values of integers as if they were character pointers. Undefined behavior!
You should be getting heaps of warnings for this from any modern compiler, i.e. one that validates formatting strings.
There's no point in parsing integers as if they were strings, I don't understand why you're not just doing
fscanf(inFile, "%d:%d", &records[i].source, &records.destination);
for the first case.
Also, do note that it's much better to read in whole lines using fgets(), then parsing the line once read using sscanf(), than trying to combine the two steps with fscanf().
Last, you should check the return value of the conversion call to know how many conversion succeeded.
I want to a linked list in C using file operations. I want to get a line and split it and storage in structers. But I cant split two strings.
My File like this:
1#Emre#Dogan2#John#Smith3#Ashley#Thomasetc...
I want to read one line from file using fscanf.
fscanf(file,"%d#%s#%s",&number,name,surmane);
But the result is
Number : 1Name : Emre#Dogan
How can get rid of that # element in the name and split it to name and surname;
#include <stdio.h>
#include <string.h>
int main(void) {
FILE *fptr;
fptr = fopen("Input.txt", "r");
int number;
char *name;
char *surname;
char line_data[1024];
fgets(line_data, 1024, fptr);
number = atoi(strtok(line_data, "#"));
name = strtok(NULL, "#");
surname = strtok(NULL, "#");
printf("%d %s %s", number, name, surname);
}
Output:
1 Emre Dogan
EDIT:
Coverted the variable "number" from string to integer.
It's better to read a full line using fgets(), then parsing that line. This is more robust, using fscanf() directly on the input stream can be confusing due to the way fscanf() skips whitespace.
So, you could do:
char line[1024];
if(fgets(line, sizeof line, file) != NULL)
{
int age;
char name[256], surname[256];
if(sscanf(line, "%d#%255[^#]#%255s", &age, name, surname) == 3)
{
printf("it seems %s %s is %d years old\n", name, surname, age);
}
}
This uses the %[] format specifier to avoid including the # separator in the parsed strings. I think this is cleaner than strtok(), which is a scary function best avoided.
I'm attempting to read a data file and to store the information into an array of course structures (or an array of pointers to course structures). This assignment requires maintaining a database using an array of pointers to the student structures.
I'm getting a segmentation fault when I attempt to scan the data file into the array. How can I properly store the information from the file into the array?
#define SIZE 30
#define fieldLength 300
#define diskFile "diskFile.dat"
#define courseFile "course.dat"
struct student
{
char name[fieldLength];
int age[fieldLength];
char course1[fieldLength];
char course2[fieldLength];
char remarks[fieldLength];
}*sp[SIZE];
struct course
{
char name[fieldLength];
char number[fieldLength];
char instructor[fieldLength];
char date[fieldLength];
char starting[fieldLength];
char ending[fieldLength];
char location[fieldLength];
};
int main(int argc, char *argv[])
{
int i, count;
struct course course_arr[SIZE]; // an array of ten structs
FILE * in; /*FILE pointer to do the stream IO*/
in = fopen(courseFile, "r+");
count = 0;
while ((fscanf(in, "%s %s %s %s %s %s %s",
&course_arr[count].name,
&course_arr[count].number,
&course_arr[count].instructor,
&course_arr[count].date,
&course_arr[count].starting,
&course_arr[count].ending,
&course_arr[count].location)) != EOF)
{
count++;
}
/* print the menu */
printf("\n-----------------------------------------------------------------\n");
printf("|\t%-20s","(N)ew record");
printf("%-20s","(U)pdate record");
printf("Swa(p) records\t|\n");
printf("|\t%-20s","(S)ort database");
printf("%-20s","(C)lear database");
printf("(D)isplay db\t|\n");
printf("|\t%-20s","(L)oad disk");
printf("%-20s","(W)rite disk");
printf("(E)mpty disk\t|\n");
printf("|\t%-20s", "(V)iew courses");
printf("%-20s","(R)emove record");
printf("(Q)uit \t|\n");
printf("-----------------------------------------------------------------\n");
printf("choose one: ");
Routine fscanf never returns EOF.
Test fscanf to be less than the number of expected fields:
count = 0;
while((fscanf(in, "%s %s %s %s %s %s %s", &course_arr[count].name, &course_arr[count].number, &course_arr[count].instructor, &course_arr[count].date, &course_arr[count].starting, &course_arr[count].ending, &course_arr[count].location)) < 7){
count++;
}
i think that it is better to work with
while(getline(string_variable,,)!=EOF).(look on the net on which argumentsto put in the getline)
Then work with the string_variable. Look at the format that the data is stored into the txt file. eg: name(blank)number(blank)instructor(blank)date(blank)starting(blank)endinglocation
Start looking for blanks in the string_variable. when you see the first blank copy the substring from position 1 to position blank-1 to the course_arr[count].name variable.then delete the substring from position 1 to position blank. Look again for the first blank and store the substring to course_arr[count].number and so on.
Sorry for my English hope u got the meaning
You should loose all the &s in the fscanf call. The char arrays are already passed as pointers. If you'd used the -Wall option on gcc (or a similar option for any other compiler) it will warn you for this as well.
Have you checked the file what you are reading is present or not.
add bellow
in = fopen(courseFile, "r+");
if(in == NULL)
{
printf("exit");
exit(0);
}
I guess it might be the problem.
I'm trying to open a file and pass to struct, I'm using fscanf() with a loop, but it only saves one the struct the last read:
Imagine a file:
JR John Rambo 24353432
JL John Lennon 6435463
I'm using this code:
typedef struct people{
char code[10];
char name[100];
long telephone;
}PEOPLE;
int read(PEOPLE people[], int n_p){
char temp;
FILE *fp;
fp=fopen("example.txt","r");
if(fp==NULL){
printf("Error\n");
return -1;
}
while(!feof(fp)){
fscanf(fp,"%s %s %s %d\n", people[n_p].code,people[n_p].name,
&people[n_p].telephone);
}
}
The Problem is that he only saves the last line of the file...Should I do a if cicle??
Another question is how can I separate a similar file but with ";"
First of all, you are scanning for 3 strings (%s) and one int (%d) when you pass only 3 parameters in your fscanf(). You could add a char first_name[50]; in your struct and then do:
fscanf(fp,"%s %s %s %d\n", people[n_p].code,people[n_p].first_name,
people[n_p].name, &people[n_p].telephone);
You always fscanf() the file until you have nothing more to read (due to the !feof(fp) because of the while. So in the last people[n_p] variable the last line of the file will be saved.
You could remove the while from read() and also add the FILE * as a parameter to the function so that you don't open the file each time you call read().
Something like this maybe:
main()
{
FILE* fp = fopen("example.txt", "r");
int i = 0;
while (!feof(fp)) {
read(people, i, fp);
i++;
}
}
int read(PEOPLE people[], int n_p, FILE* fp){
char temp;
if(fp==NULL){
printf("Error\n");
return -1;
}
fscanf(fp,"%s %s %s %d\n", people[n_p].code,people[n_p].first_name,
people[n_p].name, &people[n_p].telephone);
}
For using the ; as a separator you can change fscanf() to this:
fscanf(fp, "%[^;]; %[^;]; %d\n", people[n_p].code,people[n_p].name,
&people[n_p].telephone);
EDIT I wrote the above code which can be found here and it works fine with this example.txt file as input.
It looks like you're not changing the n_p variable. You need some sort of variable to keep track of which index of the people[] array you're updating.
Additionally, hopefully you've got a large enough people array to hold all the entries in the file.