Related
#define max 5
typedef struct
{
char tar[20];
int trab[31];
}data;
int main()
{
int i,j, aux;
char fname[25];
data inf[max];
/*for(i=0;i<max;i++)
{
strcpy(inf[i].tar,inf[i-1].tar);
}*/
printf("File name?");
scanf(" %s", fname);
FILE *f=fopen("fname","r");
if(f== NULL)
{
printf("Cannot find\n");
return 1;
}
I try to read a file I'm very certain is in the same dir, however each time the FILE pointer returns NULL.
I would appreciate any help :(
Although you've tagged this as C++, your code looks more like C, so I'm using a C signature for main. The main problem you have is quotes around fname. Your code is ignoring the path that was entered and trying to open a file with the literal name fname.
int main(void)
{
int i,j, aux;
char fname[25];
printf("File name? ");
scanf(" %24s", fname); /* Always use width specifier on %s */
FILE *f=fopen(fname, "r"); /* No quotes around fname */
if( f == NULL ){
perror(fname);
return 1;
}
...
I am currently learning about to how to data structures in C and I need a little help. I am supposed to take information about classes from a .txt file and store the information in a data structure; but I am having trouble doing so. I am also sure that I am also screwing up a lot of other things in my program, so feel free to bash on my program and tell me what I am doing wrong so I can learn from my mistakes.
Here is one line of information that I am trying to store:
M273 Multivariable Calculus :MWF 0900-0950 2
where the first part is the course number, the second part is the course name, the third part is the days and time the course is available and the last number represents what year you should be in to take the course (2 translates to sophomore).
Below is my code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define EMAX 250
typedef struct class{
char *classNumber[EMAX];
char *className[EMAX];
char *classTime[EMAX];
char *classStanding[EMAX];
}class;
void menu(class*info, char buffer[], FILE*file);
void setInformation(class*info, char buffer[], FILE*file);
int main(void)
{
class info[EMAX];
char buffer[EMAX];
File *file;
setInformation(info, buffer, file);
menu(info, buffer, file);
return(0);
}
void menu(class*info, char buffer[], FILE*file)
{
int user_input=0;
do {
printf("\nSelect one of the following options: \n");
printf("1) Print all information about all classes in order of the class number\n");
printf("5) Quit\n");
scanf("%d", &user_input);
if(user_input==1)
{
//getInformation(info, buffer, file);
}
}while(user_input!=5);
}
void setInformation(class*info, char buffer[], FILE*file)
{
size_t count = 0;
char line[50];
char *token;
file = fopen("classes.txt", "r");
while(fgets(line, sizeof(line), file)!=NULL)
{
token=strtok(line, " "); //Only gets the course number
strncpy(info[count].classNumber, token, strlen(token));
count++;
}
fclose(file);
}
As you can tell, I can only extract the course number with this code. I would prefer to store all the data in one while loop and I have tried to extract more information by adding another token to stop as soon as it reaches the ":" before the day and time but I can't figure out how to get it to work. I also get a lot of warnings when I compile this, so I welcome any advice to help my trash code. I appreciate any help
*scanf() is great:
#include <stdlib.h>
#include <stdio.h>
#define EMAX 250
#define STRING(X) #X
#define STRINGIFY(X) STRING(X)
typedef struct class_tag {
char classNumber[EMAX + 1];
char className[EMAX + 1];
char classTime[EMAX + 1];
char classStanding[EMAX + 1];
char foo[EMAX + 1];
} class;
int main(void)
{
char const *input_filename = "test.txt";
FILE *input = fopen(input_filename, "r");
if (!input) {
fprintf(stderr, "Couldn't open \"%s\" for reading :(\n\n", input_filename);
return EXIT_FAILURE;
}
class c;
class *classes = NULL;
size_t classes_size = 0;
while (fscanf(input, "%"STRINGIFY(EMAX)"s %"STRINGIFY(EMAX)"[^:] %"STRINGIFY(EMAX)"s "
"%"STRINGIFY(EMAX)"s %"STRINGIFY(EMAX)"s",
c.classNumber, c.className, c.classTime, c.classStanding, c.foo) == 5)
{
class *tmp = realloc(classes, ++classes_size * sizeof(*classes));
if (!tmp) {
fputs("Not enough memory :(\n\n", stderr);
fclose(input);
free(classes);
return EXIT_FAILURE;
}
classes = tmp;
classes[classes_size - 1] = c;
}
fclose(input);
for (size_t i = 0; i < classes_size; ++i)
printf("%s %s %s %s\n", classes[i].classNumber, classes[i].className, classes[i].classTime, classes[i].classStanding);
free(classes);
}
I have to read from a file multiple records(each components of the records are separated by a comma), and I can't understand what's the problem, so here's my file:
Rossi,Mario,M,mariorossi#gmail.com,3923333332,Portiere Bianchi,Giuseppe,M,giuseppebianchi#gmail.com,3470000021,Attaccante Ferrari,Anna,F,annaferrari#gmail.com,3466482645,Attaccante Romano,Antonio,M,antonioromano#gmail.com,3450394672,Centrocampista
and here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct dati_giocatori {
char cognome[20];
char nome[20];
char genere[20];
char email[50];
char telefono[16];
char ruolo[20];
};
typedef struct dati_giocatori GIOCATORE;
void stampa_file(FILE *pfile, GIOCATORE *vettore, int dim, char *stringa);
int main (){
FILE *pfile;
GIOCATORE *vettore;
int dim=0;
char stringa[200];
printf("Quanti giocatori vuoi visualizzare?");
scanf("%d",&dim);
vettore=(GIOCATORE*)malloc(dim*sizeof(GIOCATORE));
pfile=fopen("Giocatori.txt","r");
stampa_file(pfile,vettore,dim,stringa);
system("pause");
fclose(pfile);
pfile=fopen("Giocatoriv.txt","r");
system("pause");
free(vettore);
fclose(pfile);
system("pause");
return 0;
system("pause");
}
void stampa_file(FILE *pfile, GIOCATORE *vettore, int dim, char *stringa){
int i=0;
int j=0;
if(pfile!=NULL){
if(!feof(pfile)){
while(i<dim){
if(!feof(pfile)){
fgets(stringa,200,pfile);
sscanf(stringa,"%[^,],%[^,],%[^,],%[^,],%[^,],%s",vettore[i].cognome,vettore[i].nome,
vettore[i].genere,vettore[i].email,vettore[i].telefono,vettore[i].ruolo);
i++;
}
else{
printf("\n----- Giocatori finiti -----\n");
printf("\n");
i=dim;
}
}
}
else{
printf("\nFile finito.\n");
}
}
else{
printf("Errore nell'apertura del file.\n");
printf("\n");
}
while(j<dim){
printf("%s,%s,%s,%s,%s,%s\n",vettore[j].cognome,vettore[j].nome,
vettore[j].genere,vettore[j].email,vettore[j].telefono,vettore[j].ruolo);
j++;
}
system("pause");
}
I know the problem is with the sscanf(), because it prints on screen just the first component of every record, and five commas, but I can't figure out how to solve this problem... It does not assign the right data to the right place on the records, is the sscanf() format correct? I am not very familiar with delimiters, how should I fix this?
Thanks everyone for helping. I'm sorry you waited so long for the response but I could not edit yesterday. I'm really sorry also for the posting errors, I'm new at stack overflow and I'm also new in C (it's my first language)...(and just to make it difficult to me, I'm also not a native speaker as you can notice by my grammar errors).
Yes the email addesses are fake.
By the way, I'm gonna be honest I don't know hot to check if the file has a newline character at the end of every record...While writing the file I thought that pressing "enter" would gave to me the newline character, but reading you comments I am not sure anymore. I want to use newline character at the end of every record, but how do I do that? and, will this make my code work?
(I opened a second time the file because I was just trying other things on it, so please don't mind about that, same for the system pause).
Okay, first of all next time make your question and specially your code more readable (you must use indentation properly). I don't understand why you use so many system("pause"); also in a wrong way. You also cast the result of vettore=(GIOCATORE*)malloc(dim*sizeof(GIOCATORE)); and you should not do it. You open the file, then use it, close it and open a new file doing nothing on it so I removed this. Note that using while (!feof(file)) is always wrong. Then in your stampa_file function I made lots of changes.
Here is the code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* NOTE: I'M NOT CHECKING **ANY** RETURNING ERROR
* SUCH AS FROM FOPEN OR MALLOC.
*/
struct dati_giocatori {
char cognome[20];
char nome[20];
char genere[20];
char email[50];
char telefono[16];
char ruolo[20];
};
typedef struct dati_giocatori GIOCATORE;
void stampa_file(FILE *pfile, GIOCATORE *vettore, int dim, char *stringa);
int main (){
FILE *pfile;
GIOCATORE *vettore;
int dim=0;
char stringa[200];
printf("Quanti giocatori vuoi visualizzare?");
scanf("%d",&dim);
vettore= malloc(dim*sizeof*vettore);
pfile=fopen("Giocatori.txt","r");
stampa_file(pfile,vettore,dim,stringa);
fclose(pfile);
return 0;
}
void stampa_file(FILE *pfile, GIOCATORE *vettore, int dim, char *stringa){
int i=0;
int j=0;
size_t size = 200;
if(pfile!=NULL){
while((getline(&stringa, &size, pfile)) != -1 && i<dim) {
sscanf(stringa,"%[^,],%[^,],%[^,],%[^,],%[^,],%s",vettore[i].cognome,vettore[i].nome,
vettore[i].genere,vettore[i].email,vettore[i].telefono,vettore[i].ruolo);
i++;
}
}
printf("No more records to read\n");
while(j<i){
printf("%s,%s,%s,%s,%s,%s\n",vettore[j].cognome,vettore[j].nome,
vettore[j].genere,vettore[j].email,vettore[j].telefono,vettore[j].ruolo);
j++;
}
if(dim > i){
printf("Not enough players\n");
}
}
That's the file I used for tests:
Rossi,Mario,M,mariorossi#gmail.com,3923333332,Portiere
Bianchi,Giuseppe,M,giuseppebianchi#gmail.com,3470000021,Attaccante
Ferrari,Anna,F,annaferrari#gmail.com,3466482645,Attaccante
Romano,Antonio,M,antonioromano#gmail.com,3450394672,Centrocampista
After write data to the binary file, I changed the mode to "r" to read the file. The name of who is correct, but color and education are empty. Age is returned as a large integer number, which is I guess the address of the variable. So, what is wrong here?
Update: The answer of Retired Ninja and Thornkey almost solve my problem. The rest is if input of age is 26, but not other numbers, the program will not write correct input to file. Anyone know what is wrong here?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXLEN 100
typedef struct Person{
char name[MAXLEN];
int age;
char color[MAXLEN];
char education[MAXLEN];
} Person;
void create_person(Person *who){
printf("name: ");
fscanf(stdin, "%s", who->name);
printf("age: ");
fscanf(stdin, "%d", &(who->age));
printf("color: ");
fscanf(stdin, "%s", who->color);
printf("education: ");
fscanf(stdin, "%s", who->education);
}
void print_record(Person *who){
printf("name: %s\n", who->name);
printf("age: %d\n", who->age);
printf("color: %s\n", who->color);
printf("education: %s\n", who->education);
}
void load_db(FILE *fp, Person *who){
int result = fread(who, sizeof(who), 1, fp);
if(!result)
//printf("result%d", result);
printf("cannot load database");
}
FILE *connect_db (char *file_name, char *mode, Person *who){
FILE *fp = (FILE *)malloc(sizeof(100));
// open stream and load database from the file
if(strcmp(mode, "w") == 0){
fp = fopen(file_name, mode);
//load_db(conn); // load data from file
}else if(strcmp(mode, "r") == 0){
fp = fopen (file_name, mode);
load_db(fp, who); // load data from file
}else{
printf("incorrect mode");
}
return fp;
}
// save database to file
int save_db (FILE *fp, Person *who){
int result = fwrite(who, sizeof(who), 1, fp);
if(result){
return 0; // successfully save db
}
printf("cannot save db");
}
int main(int argc, char *argv[])
{
char answer[MAXLEN];
Person person;
Person *who = &person;
FILE *fp;
create_person(who);
fp = connect_db("record2.dat", "w", who);
save_db(fp, who);
print_record(who);
free(fp);
fclose(fp);
return 0;
}
fread() reads individual bytes. You want to read in numbers which you have printf'd.
Your files will look like this:
name: Samuel Thornkey
age: 24
colour: blue
education: PHD in computer science
But when you use fread, the program directly reads bytes from the file and fills them into the record. Your person will then contain:
char name[MAXLEN]: first MAXLEN characters i.e. "name: Samuel Thornkey\n age: 24\ncolour: blue\n" or something similar
int age: the rest of the characters, encoded as bytes, hence very large number
char color[MAXLEN]: empty
char education[MAXLEN]: empty
Instead, use fscanf:
fscanf(fp,"name:%s ",&who->name);
fscanf(fp,"age:%d ",&who->age);
and so on.
It's likely to be this:
free(fp);
fclose(fp);
You are not permitted to free memory that wasn't given to you by malloc (or realloc).
And, yes, you may think you've allocated it inside connect_db but (1) that's totally unnecessary, and (2) you overwrite the pointer when you call fopen.
In addition, save_db is using the size of the who pointer which will most likely not be the same as the type it points to.
So, make the following changes:
get rid of the call to malloc, just use FILE *fp; within connect_db.
get rid of the free(fp) within main.
in save_db, use sizeof(Person) rather than sizeof(who).
Here's a fixed version that may be of some help to you. It successfully fills in a Person, prints it, and writes it to the file. Then it reads the data back from the file into a different Person and prints it.
The structure is similar to what you had, but I made all the reading/writing explicit so you'd see the steps. In general it isn't a good idea to have functions that perform extra duties you might not always want. I also made create_person require no input for faster testing. Your input code looked okay, I just didn't want to type it every time.
One thing to keep in mind, if you plan to write binary data to a file you should open the file in binary mode ("wb" or "rb") to avoid line ending translation on systems that perform that on text files.
You might also consider that a file written on one system may not be readable on a different system if the size of the Person structure changes due to different alignment or int being a different size. Probably not an issue for you, but if it becomes one you might look into a different serialization scheme.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXLEN 100
typedef struct Person
{
char name[MAXLEN];
int age;
char color[MAXLEN];
char education[MAXLEN];
} Person;
void create_person(Person *who)
{
strcpy(who->name, "Fred Smith");
who->age = 21;
strcpy(who->color, "Red");
strcpy(who->education, "Some School");
}
void print_record(Person *who)
{
printf("name: %s\n", who->name);
printf("age: %d\n", who->age);
printf("color: %s\n", who->color);
printf("education: %s\n", who->education);
}
void load_db(FILE *fp, Person *who)
{
int result = fread(who, sizeof(*who), 1, fp);
if(!result)
printf("cannot load database");
}
FILE *connect_db(char *file_name, char *mode, Person *who)
{
FILE *fp = NULL;
if(strcmp(mode, "w") == 0)
{
fp = fopen(file_name, mode);
}
else if(strcmp(mode, "r") == 0)
{
fp = fopen(file_name, mode);
}
else
{
printf("incorrect mode");
}
return fp;
}
int save_db(FILE *fp, Person *who)
{
int result = fwrite(who, sizeof(*who), 1, fp);
if(result)
{
return 0;
}
printf("cannot save db");
return -1;
}
int main(int argc, char *argv[])
{
FILE* fp = NULL;
Person who1;
Person who2;
create_person(&who1);
print_record(&who1);
fp = connect_db("record2.dat", "w", &who1);
save_db(fp, &who1);
fclose(fp);
fp = connect_db("record2.dat", "r", &who2);
load_db(fp, &who2);
print_record(&who1);
fclose(fp);
return 0;
}
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