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
Related
I am a beginner in c so I have a problem with get the user to input last name, a comma & then first name. However it will pass to the function call
int get_name(FILE *fp)
in my main function. I have a problem either if I have to use the arguments parameters.
Example, main (int argc, char *argv[])) or just main (void))
and from what I have been searching so far, FILE*fp cannot get the user to enter from stdin it only use to open the file(?) BUT I am required to get the user to input from keyboard and pass to the function. I have written some codes. but they don't seem to work but I am going to put down on here the one I am sure that I need a few changes most.
#define LINESIZE1024
int main(void){
FILE *fp;
char line[LINESIZE];
char first;
char last;
char comma;
while(1){
if(!fgets(line,LINESIZE,stdin)){
clearerr(stdin);
break;
}
if(fp = (sscanf(line,"%s %s %s",&last,&comma,&first)==3))
get_name(fp);
if(get_last_first(fp)== -1)
break;
printf("Please enter first name a comma and then last name");
}
BUT I got an error saying I can't use pass it from pointer to an integer. and many MORE but I accidentally closed my concolse and all the errors that appeared while I was trying to fix are gone. So please give me some ideas.
What about seconde code
while(1){
if(!fgets(line,LINESIZE,fp)){
clearerr(stdin);
break;
}
if(sscanf(line,"%s %s %s",last,comma,first)==3)
get_last_first(fp);
return 0;
}
It gave me errors too. fp,last,first,comma used uninitialized in this function
OK so I think I have fixed the previous problem now. However it doesn't print the name back if the name is given correctly. Here is my fixed main code.
int main(void){
FILE *fp = stdin;
char line[LINESIZE];
char first[16];
char last[16];
while(1){
if(!fgets(line,LINESIZE,stdin)){
clearerr(stdin);
break;
}
if(sscanf(line,"%s ,%s",last,first)==2)
if(get_name(fp)==2)
printf("Your name is: %s %s\n", first, last);
}
return 0;
}
here is my function.
int get_name(FILE *fp){
char line[LINESIZE];
char last[16], first[16];
int n;
/* returns -1 if the input is not in the correct format
or the name is not valid */
if(fgets(line, LINESIZE, fp) == NULL) {
return -1;
}
/* returns 0 on EOF */
if((n = sscanf(line, " %[a-zA-Z-] , %[a-zA-Z-]", last, first)) == EOF) {
return 0;
}
/* prints the name if it's valid */
if((n = sscanf(line, " %[a-zA-Z-] , %[a-zA-Z-]", last, first)) == 2) {
return 2;
}
return 1;
}
I thank you people so much for taking time to read and help me. Please don't be mean :)
Seems that you are making it more complicated than needed. Don't call fgets and scanf in main. Only do that in the function get_name.
It can be something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINESIZE 1024
int get_name(FILE *fp)
{
char line[LINESIZE];
char* t;
if(!fgets(line, LINESIZE,fp))
{
printf("Error reading input\n");
return 0;
}
t = strstr(line, ",");
if (t)
{
*t = '\0';
++t;
printf("First: %s - Last: %s\n", line, t);
return 2;
}
printf("Illegal input\n");
return 0;
}
int main(int argc, char **argv)
{
get_name(stdin);
return 0;
}
If you later decide that you want to read from a file, you can reuse the function get_name without changing it at all. All you need is to change main. Like:
int main(int argc, char **argv)
{
FILE* f = fopen("test.txt", "r");
if (f)
{
get_name(f);
fclose(f);
}
else
{
printf("Open file failed\n");
}
return 0;
}
If you want to read from the keyboard, read from stdin or use scanf, which internally reads from stdin. If you want to read from a file instead, use FILE *fp, but don't forget to open the file and check if it was successful (you'll find lots of tutorials for this).
Further, when reading in strings, you need an array of characters, not a single one. Note further, that scanf can already deal with formats like "everything that is not a ',' then a ',' then a string. Note that format "[^,]" means "any character except a ',':
So you could adapt the code as follows:
#define LINESIZE 1024
int main(void){
char line[LINESIZE];
char first[LINESIZE];
char last[LINESIZE];
while(fgets(line,LINESIZE,stdin)) {
if(sscanf(line,"%[^,],%s",last,first)==2) {
printf("Read in %s ... %s\n",last,first);
}
else {
printf("Please enter first name a comma and then last name");
}
}
return 0;
}
And if your professor is picky concerning the "use FILE*", you could write:
FILE *fp = stdin;
...
while(fgets(line,LINESIZE,fp)) {
...
Edit: as requested I've included the code in 'ledic'. However, it never ran - any of it, not even a hello world printf as first line, so I am relatively sure the problem would never be withinit.
Edit2: ironically enough, it was within the 'ledic' function. Looks like I understand even less about this than I previously thought.
I am writing for my current project at Uni and no one around me can figure out this segmentation fault. It should be pretty straightforward so I appreciate your help.
Code as follows:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void ledic(FILE *fp){
printf("Hello world\n");
int len;
int j, i, k;
char palavra[30];
char dictionary[30][10000][30];
int VecOcorrencias[30];
for (j=0; j<30; j++)
VecOcorrencias[j]=0;
printf("Hello world\n");
while ( fscanf(fp, "%s", palavra) == 1 ) {
len = strlen(palavra);
k = VecOcorrencias[len];
strcpy (dictionary[len][k], palavra);
VecOcorrencias[len]++;
}
for (i=0; i<1000; i++)
printf("%s %d\n", dictionary[5][i], VecOcorrencias[5]);
}
}
FILE *OpenFile( char *nome, char *mode){
FILE *fp;
fp = fopen (nome, mode);
if( fp == NULL){
printf(" Cant open file\n");
exit(1);
}
return (fp);
}
int main( int argc, char *argv[]){
FILE * fp;
fp = OpenFile( argv[1], "r");
ledic(fp);
return(0);
}
The code breaks when it enters the void ledic(FILE *fp) function, and says it cannot access the referenced memory (I suppose *fp).
I cannot for the life of me figure out why. Any thoughts?
The declaration char dictionary[30][10000][30]; creates a 9Mb variable 30*30*1000 = 9'000'000. As it is a local variable it is created on the stack and the default stack size on a typical Linux machine is only 8Mb (on Windows it's even only 1Mb).
If you declare it as static, the variable is not on the stack and therefore it can take more memory than the stacksize.
See this SO article for more details on the static keyword.
I am trying to write a program for some classwork that reads in a file using fscanf, and then stores each word into an array with one word in each element. Then I need to print each element of the array out on to a new line on the console.
The getty.txt file has the Gettysburg address in it with appropriate spacing, punctuation, and is multiline.
What I think is happening is that the entire text is being stored in the first element of the array, but I am not 100% sure as I am still learning to debug and write in C.
Any advice as to what I am doing wrong would be great! I currently only seem to be getting the last word and some extra characters.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void readFile();
void writeFile(char* buffer, int bufferlen);
FILE *fpread;
FILE *fpwrite;
char filebuffer[1000];
int filebufferlen = 0;
int main(int argc, char *argv[]) {
fpwrite = fopen("csis.txt", "w");
readFile();
writeFile(filebuffer, filebufferlen);
fclose(fpwrite);
return 0;
}
void readFile() {
char c;
filebufferlen = 0;
if(!(fpread = fopen("getty.txt", "r"))){
printf("File %s could not be opened. \n", "getty.txt");
fprintf(fpwrite,"File %s could not be opened. \n", "getty.txt");
exit(1);
}
while (!feof(fpread)) {
fscanf(fpread, "%s", filebuffer);
filebufferlen++;
}
}
void writeFile(char* filebuffer, int filebufferlen) {
for (int i = 0; i < filebufferlen; ++i){
printf("%c\n", filebuffer[i]);
}
}
After fixing the compile problems:
the code does not contain any code nor data declarations to contain an array of 'words.' So naturally, nothing but the last word is actually saved so it can be printed out.
I am trying to read name and password from a file into a structure in c, but clearly my code does not work as expected. Is there anyone can help me to figure out the problem with the codes attached below? Thanks a lot!
(Basically the file has several names and passwords, and I want to read them into a structure accounts[]`)
#include <stdio.h>
#include <stdlib.h>
struct account {
char *id;
char *password;
};
static struct account accounts[10];
void read_file(struct account accounts[])
{
FILE *fp;
int i=0; // count how many lines are in the file
int c;
fp=fopen("name_pass.txt", "r");
while(!feof(fp)) {
c=fgetc(fp);
if(c=='\n')
++i;
}
int j=0;
// read each line and put into accounts
while(j!=i-1) {
fscanf(fp, "%s %s", accounts[j].id, accounts[j].password);
++j;
}
}
int main()
{
read_file(accounts);
// check if it works or not
printf("%s, %s, %s, %s\n",
accounts[0].id, accounts[0].password,
accounts[1].id, accounts[1].password);
return 0;
}
and the name_pass.txt file is a simple file like this (name+password):
hello 1234
lol 123
world 123
You are reading file two times. So you need to fseek(), or rewind() to first char before second loop starts.
try with:
fseek(fp, 0, SEEK_SET); // same as rewind()
or
rewind(fp); // s
this code you need to add between two loops (after first and before second loop)
Additionally, you are to allocate memory for id, password filed in account struct:
struct account {
char *id;
char *password;
};
or do allocate memory statically as #Adrián López suggested in his answer.
EDIT I corrected you code:
struct account {
char id[20];
char password[20];
};
static struct account accounts[10];
void read_file(struct account accounts[])
{
FILE *fp;
int i=0; // count how many lines are in the file
int c;
fp=fopen("name_pass.txt", "r");
while(!feof(fp)) {
c=fgetc(fp);
if(c=='\n')
++i;
}
int j=0;
rewind(fp); // Line I added
// read each line and put into accounts
while(j!=i-1) {
fscanf(fp, "%s %s", accounts[j].id, accounts[j].password);
++j;
}
}
int main()
{
read_file(accounts);
// check if it works or not
printf("%s, %s, %s, %s\n",
accounts[0].id, accounts[0].password,
accounts[1].id, accounts[1].password);
return 0;
}
and its working as follows:
:~$ cat name_pass.txt
hello 1234
lol 123
world 123
:~$ ./a.out
hello, 1234, lol, 123
You need to malloc() the content of the pointers in your struct or declaring then with an static size:
struct account {
char id[20];
char password[20];
};
You should probably first allocate memory for the stuff you're scanfing in. Keyword is malloc, a bit too long to lecture right here.
#include <stdio.h>
#include <stdlib.h>
typedef struct aluno{
char cabecalho[60];
char info[100];
int n_alunos;
char dados[100];
char curso[100];
int numero;
char nome[100];
char e_mail[100];
int n_disciplinas;
int nota;
}ALUNO;
void cabclh(ALUNO alunos[],int a){
FILE *fp;
int i;
for(i=0;i<100;i++){
fp=fopen("trabalho.txt","r");
if(fp==NULL){
printf("Erro ao abrir o ficheiro\n");
}
while(!feof(fp)){
fgets(alunos[i].cabecalho,60,fp);
printf("%s\n",alunos[i].cabecalho);
}
}
fclose(fp);
}
what is wrong here?
main:
int main(int argc, char *argv[]){
ALUNO alunos[100];
int aluno;
int b;
cabclh(aluno,b);
system("PAUSE");
return 0
Quite a few issues here.
The first parameter passed to cabclh is of the wrong type:
void cabclh(ALUNO alunos[],int a);
: :
int aluno;
cabclh(aluno,b);
You should probably exit the function (or some other error handling) if you can't open the file:
if (fp==NULL){
printf("Erro ao abrir o ficheiro\n");
return; // <- Added
}
There's no need to open the file a hundred times. If a regular file doesn't open the first time, it probably won't open at all (although there are cases where this may happen). This particular segment will result in wasted file handles:
for(i=0;i<100;i++){
fp=fopen("trabalho.txt","r");
}
In addition it will reset the file pointer to the start of the file each time.
If your intent is to read up to 100 items from that file for storage into your array, I would suggest you start with:
#include <stdio.h>
#include <stdlib.h>
typedef struct aluno{
char cabecalho[60];
char info[100];
int n_alunos;
char dados[100];
char curso[100];
int numero;
char nome[100];
char e_mail[100];
int n_disciplinas;
int nota;
} ALUNO;
void cabclh (ALUNO alunos[]) {
FILE *fp;
int i;
// Initialise all elements to indicate no data.
for (i = 0; i < 100; i++)
alunos[i].cabecalho[0] = '\0';
// Open the file, returning if not there.
fp = fopen ("trabalho.txt","r");
if (fp == NULL) {
printf("Erro ao abrir o ficheiro\n");
return;
}
// Only allow up to 100 elements.
for (i = 0; i < 100; i++) {
// Only read and load if more to go.
if (!feof(fp)) {
// Read the line and strip off newline character.
fgets (alunos[i].cabecalho,60,fp);
if (alunos[i].cabecalho[strlen(alunos[i].cabecalho)-1] == '\n')
alunos[i].cabecalho[strlen(alunos[i].cabecalho)-1] = '\0';
printf ("%s\n", alunos[i].cabecalho);
}
}
// Close the file.
fclose (fp);
}
int main (int argc, char *argv[]) {
ALUNO alunos[100];
cabclh(alunos);
system("PAUSE");
return 0;
}
It successfully reads a test file I created. Now it may be that your input file is more complicated that just 100 strings to be loaded into cabecelho but the code above is a good start, showing the controlling logic. Ad different line format would only change the way each line is read, not the loop around it.
And, if you want to be able to handle arbitrary numbers of lines, I would move away from arrays to more expandable data structures. But, for a first attempt, you're making the right choice keeping it simple.
It looks like you're opening the file 100 times, then using a while loop with [i] that's never changing. i = 100 because it's never changed inside your while loop.
I see at least one thing wrong:
char cabecalho[60];
// ... and later ...
fgets(alunos[i].cabecalho,100,fp);
Last I checked, 100 is bigger than 60, so you have a buffer overflow error.
I don't understand why are you doing an fopen 100 times:
for(i=0;i<100;i++){
fp=fopen("trabalho.txt","r");
}
Just do:
fp=fopen("trabalho.txt","r");
Besides all the other errors, you have an extra brace above the fclose(fp), which is likely causing a compilation issue due to unmatched braces.
void cabclh(ALUNO alunos[],int a){
FILE *fp;
int i=0;
fp=fopen("trabalho.txt","r");
if(fp==NULL){
printf("Erro ao abrir o ficheiro\n");
return;
}
while(!feof(fp) && i<100){
fgets(alunos[i].cabecalho,60,fp);
printf("%s\n",alunos[i++].cabecalho);
}
fclose(fp);
}