How to properly use fscanf and fgets to read from file - c

I'm new at programming in C (it's my first language) and I'm not so good at english, so sorry for the grammar... By the way, I was wondering if you could help me with this:
I have to read from file the components of the array, setting them as part of it and see them as output in the screen.
I created a file with this informations:
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 trying to coding I ended up with this:
#include <stdio.h>
#include <stdlib.h>
struct dati_giocatori {
char cognome[20];
char nome[20];
char genere[20];
char email[20];
int telefono;
char ruolo[20];
};
typedef struct dati_giocatori GIOCATORE;
void lettura(FILE *file, GIOCATORE *vettore, int dim);
void stampa(GIOCATORE *vettore, int dim);
int main (){
FILE *file;
GIOCATORE *vettore;
int dim;
vettore=(GIOCATORE*)malloc(dim*sizeof(GIOCATORE));
printf("how many players do you want to see?");
scanf("%d",&dim);
file=fopen("Giocatori.txt","r");
lettura(file,vettore,dim);
stampa(vettore,dim);
system("pause");
return 0;
}
void lettura(FILE *file, GIOCATORE *vettore, int dim){
int i=0;
if(file){
while(!feof(file) && i<dim){
fscanf(file,"%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],[^\n]", vettore[i].cognome,vettore[i].nome,vettore[i].genere,vettore[i].email,&vettore[i].telefono,vettore[i].ruolo);
i++;
}
}
else{
printf("Error.");
}
}
void stampa(GIOCATORE *vettore, int dim){
int i=0;
while(i<dim){
printf("%s,%s,%s,%s,%d,%s\n", vettore[i].cognome,vettore[i].nome,vettore[i].genere,vettore[i].email,vettore[i].telefono,vettore[i].ruolo);
i++;
}
}
but it does not work very well. I know I have some problems with the fscanf (probabily), and I wanted to know if the malloc is used correctly... Could you help me? Where are the errors I make? How can I solve them? How should the code be using a fgets instead of fscanf? Am I using the delimitators in the right way?
Ok, thank you very much for replying, I'll treat the 10-digit phone number with a long variable, but I still don't get how I should correctly use the fscanf. It's the first time with delimitators, and this confuse me. My format specifiers are "%s,%s,%s,%s,%ld,%s", right? but how should I put them in the fscanf? What have I to write after the parameter "file" in the fscanf?

fscanf(file,"%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],[^\n]",...
Your format specifiers are not correct; if you tell fscanf that the data to read is comma-separated, which you do with the commas outside the brackets, you don't need to specify what you put inside ([^,]), and you're missing format specifiers. Try to provide fscanf the same format you gave to printf in the stampa function. Be careful: an integer variable would not hold correctly a 10-digit phone number, use a long variable or treat it like a string as well.
On the other hand, fgets would read the whole line into a string buffer as it does not accepts a format specifier, so you would end up having a one string only, containing the entire line, then you should parse it with something like sscanf in the same way you should use fscanf.

Related

How do I properly call the function I created to the main?

So I suck with functions and need to debug this. Im pretty sure the function ToPigLating does its job well at converting. However I just need help calling the function ToPigLatin inside of my main function. But when I try doing that I just get a bunch of error codes.
#include <stdlib.h>
#include <string.h>
#define LEN 32
char* ToPigLatin(char* word[LEN]){
char word[LEN];
char translation [LEN];
char temp [LEN];
int i, j;
while ((scanf ("%s", word)) != '\0') {
strcpy (translation, word);
//just pretend I have all the work to convert it in here.
} // while
}
int main(){
printf("Enter 5 words: ");
scanf("%s", word);
ToPigLatin();
}```
Roughly, variables only exist within the function they're declared in. The word in ToPigLatin exists only within ToPigLatin. It is not available in main. This lets us write functions without worrying about all the rest of the code.
You need to declare a different variable in main, it can also be called word, to store the input and then pass that into ToPigLatin.
Let's illustrate with something simpler, a function which doubles its input.
int times_two(int number) {
return number * 2;
}
We need to give times_two a number.
int main() {
// This is different from "number" in times_two.
int number = 42;
// We have to pass its value into time_two.
int doubled = times_two(number);
printf("%d doubled is %d\n", number, doubled);
}
Your case is a bit more complicated because you're working with input and memory allocation and arrays. I'd suggest just focusing on arrays and function calls for now. No scanf. No strcpy.
For example, here's a function to print an array of words.
#include <stdio.h>
// Arrays in C don't store their size, the size must be given.
void printWords(const char *words[], size_t num_words) {
for( int i = 0; i < num_words; i++ ) {
printf("word[%d] is %s.\n", i, words[i]);
}
}
int main(){
// This "words" variable is distinct from the one in printWords.
const char *words[] = {"up", "down", "left", "right"};
// It must be passed into printWords along with its size.
printWords(words, 4);
}
ToPigLatingToPigLating function expects to have a parameter like ToPigLating("MyParameter");
Hello there icecolddash.
First things first, there are some concepts missing. In main section:
scanf("%s", word);
You're probably trying to read a string format and store in word variable.
In this case, you should have it on your declaration scope. After some adjustment, it will look like this:
int main(){
char word[LEN];
As you defined LEN with 32 bytes maximum, your program will not be allowed to read bigger strings.
You're also using standard input and output funcitions as printf, and so you should ever include stdio.h, thats the header which cointains those prototypes already declared, avoiding 'implicit declaration' compiling warnings.
Next issue is how you're declaring your translation function, so we have to think about it:
char* ToPigLatin(char* word[LEN])
In this case, what you wrote:
ToPigLatin is a funcion that returns a char pointer, which means you want your function to probably return a string. If it makes sense to you, no problem at all. Although we got some real problem with the parameter char* word[LEN].
Declaring your variable like this, assume that you're passing an array of strings as a parameter. If I got it right, you want to read all five words in main section and translate each one of them.
In this case I suggest some changes in main function, for example :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 32
#define MAX_WORDS 5
char *globalname = "translated";
char* ToPigLatin(char* word){
char *translation = NULL;
//Translation work here.
if ( !strcmp(word, "icecolddash") ){
return NULL;
}
translation = globalname;
return translation;
}
int main(){
char word[LEN];
char *translatedword;
int i;
printf("Enter 5 words: \n");
for ( i=0; i < MAX_WORDS; i++ ){
fgets(word, sizeof(word), stdin);
strtok(word, "\n"); // Just in case you're using a keyboard as input.
translatedword = ToPigLatin(word);
if ( translatedword != NULL ){
//Do something with your translation
//I'll just print it out as an example
printf("%s\n", translatedword);
continue;
}
// Generic couldn't translate message
printf("Sorry, I know nothing about %s\n", word);
}
return 0;
}
The above code translate every word in a fixed word "translated".
In case of reading the exact input "icecolddash", the program will output a generic error message, simulating some problem on translation process.
I hope this help you out with your studies.
There are a few things that I see.
#include <stdio.h>
#include <stdlib.h>
char* ToPigLatin(char* word){
printf(word);
return word;
}
int main(){
printf("Enter 5 words: ");
// declare the variable read into by scanf
char * word = NULL;
scanf("%s", word);
//Pass the variable into the function
ToPigLatin(word);
// Make sure you return an int from main()
return 0;
}
I left some comments in the code with some specific details.
However, the main thing that I would like to call out is the style of the way you're writing your code. Always try to write small, testable chunks and build your way up slowly. Try to get your code to compile. ALWAYS. If you can't run your code, you can't test it to figure out what you need to do.
As for the char ** comment you left on lewis's post, here is some reading you may find useful in building up your intuition:
https://www.tutorialspoint.com/what-does-dereferencing-a-pointer-mean-in-c-cplusplus
Happy coding!

C writing to string (specific function asked)

I am kind of in a pinch with searching one specific function with return type int which changes the values of a char array (string) by taking exactly 5 parametres whereas the function must not be imported from any other library with an exception of stdio.h maybe.
The source looks like in following:
#include <stdio.h>
int main() {
char buffer [50];
int n;
n= // some function here ;
printf("%s",buffer,n);
return 0;
}
I have been looking into many functions, but none I knew of or found match the above requirement such that I'd appreciate the help of more knowledgeable people now. Thanks in advance.
You have to go with functions with variable argument lists.
Two such ones in stdio.h are:
int sprintf(char * restrict s, const char * restrict format, ...);
int snprintf(char * restrict s, size_t n, const char * restrict format, ...);
Note: These functions do not exactly take five arguments as you specified in your question. They take a minimum number of arguments (2 & 3 respectively) but can go way beyond 5 arguments.
which changes the values of a char array (string)
The following does what you want to char array (info):
char info[60];
char name[] = "Christopher Westburry";
char designation[] = "Learner";
int reputation = 72;
sprintf(info, "Welcome %s to StackOverflow!\nDesignation: %s\nReputation: %d",
name, designation, reputation);
printf("%s", info);
Skimming Appendix B of the C Standard, I don't see anything that takes exactly 5 arguments and returns an int.
OTOH stdio.h is full of functions that return an int and take a variable number of arguments in the scanf and printf family. Once can contrive something. Since buffer is uninitialized, and the code wants to print it, presumably we're going to read something into it from stdin. That probably means some contrived scanf call.
#include <stdio.h>
int main() {
char buffer [50];
int n;
// Same as
// n = scanf("%40s", buffer);
n = scanf(
"%10s%10s%10s%10s",
buffer,
&buffer[10],
&buffer[20],
&buffer[30]
);
// printf("%s",buffer,n);
printf("'%s' %d\n",buffer,n);
return 0;
}
If that's the answer they expect, this exercise is pretty pointless.
Note that the printf in the original code has a bug where it's passed in too many arguments. Maybe that's a clue and this is supposed to be some clever use of Undefined Behavior?

Reading in char from file into struct

For my assignment, I have to read in a text file with a varying amount of lines. They follow the following format:
AACTGGTGCAGATACTGTTGA
3
AACTGGTGCAGATACTGCAGA
CAGTTTAGAG
CATCATCATCATCATCATCAT
The first line is the original line I will testing the following ones against, with the second line giving the number of remaining lines.
I'm having trouble trying to save these to a struct, and can't even get the first line to save. I tried using the void function with an array and it seems to work, but can't seem to transfer it over to structs.
Here's my code so far:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LENGTH 25
struct dna {
char code[LENGTH];
};
int main(){
char filename[] = "input1.txt";
FILE *input = fopen("input1.txt","r");
char firstDna[LENGTH]="";
struct dna first;
struct dna first.code[]= "";
makeArray(input,first);
// printf("%s",filename);
system("pause");
return 0;
}
void makeArray(FILE *input,struct dna first){
int i=-1;
//nested for loops to initialze array
//from file
while(i != '\n'){
fscanf(input,"%c",first[i].code);
printf("%c", first[i].code);
i++;
}//closing file
fclose(input);
}
Since this is for a class assignment, I want to preface this by saying that a good way to tackle these types of assignments is to break it up into tasks, then implement them one by one and finally connect them. In this case the tasks might be something like:
parse the first line into a (struct containing a) char array.
parse the number into an int variable
parse each remaining line in the file like you did with the first line
test the first line against the other lines in the file (except the number)
You also mentioned in a comment that the struct is for extra credit. For that reason, I'd recommend implementing it using just a char array first, then refactoring it into a struct once you have the basic version working. That way you have something to fall back on just in case. This way of developing might seem unnecessary at this point, but for larger more complicated projects it becomes a lot more important, so it's a really good habit to get into as early as possible.
Now, let's look at the code. I'm not going to give you the program here, but I'm going to identify the issues I see in it.
Let's start with the main method:
char filename[] = "input1.txt";
FILE *input = fopen("input1.txt","r");
This opens the file you're reading from. You're opening it correctly, but the first line is in this case unnecessary, since you never actually use the filename variable anywhere.
You also correctly close the file at the end of the makeArray function with the line:
fclose(input);
Which works. It would, however, probably be better style if you put this in the main method after calling the makeArray function. It's always a good idea to open and close files in the same function if possible, since this means you will always know you didn't forget to close the file without having to look through your entire program. Again, not really an issue in a small project, but a good habit to get into. Another solution would be to put the fopen and fclose functions in the makeArray function, so main doesn't have to know about them, then just send the char array containing the filepath to makeArray instead of the FILE*.
The next issue I see is with how you are passing the parameters to the makeArray function. To start off, instead of having a separate function, try putting everything in the main method. Using functions is good practice, but do this just to get something working.
Once that's done, something you need to be aware of is that if you're passing or returning arrays or pointers to/from functions, you will need to look up the malloc and free functions, which you may not have covered yet. This can be one of the more complex parts of C, so you might want to save this for last.
Some other things. I won't go into detail about these but try to get the concepts and not just copy paste:
struct dna first.code[]= ""; should probably be first.code[0] = \0;. \0 is used in C to terminate strings, so this will make the string empty.
Passing %c to fscanf reads a single character (you can also use fgetc for this). In this case, it will probably be easier using %s, which will return a word as a string.
Assuming you do use %s, which you probably should, you will need to call it twice before the loop - once to get the first DNA sequence and another time to get the number of other DNA sequences (the number of iterations).
Each iteration of the loop will then test the original DNA sequence against the next DNA sequence in the file.
I hope that helps!
sample to fix
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LENGTH 25
struct dna {
char code[LENGTH];
};
struct dna *makeArray(FILE *input, int *n);//n : output, number of elements
int main(void){
char filename[] = "input1.txt";
FILE *input = fopen(filename,"r");
struct dna first = { "" };
fscanf(input, "%24s", first.code);//read first line
printf("1st : %s\n", first.code);
int i, size;
struct dna *data = makeArray(input, &size);//this does close file
for(i = 0; i < size; ++i){
printf("%3d : %s\n", i+1, data[i].code);
}
free(data);//release data
system("pause");
return 0;
}
struct dna *makeArray(FILE *input, int *n){//n : output, number of elements
int i;
fscanf(input, "%d", n);//read "number of remaining lines"
struct dna *arr = calloc(*n, sizeof(struct dna));//like as struct dna arr[n] = {{0}};
for(i = 0; i < *n; ++i){
fscanf(input, "%24s", arr[i].code);
}
fclose(input);
return arr;
}
a simple fix might be :
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LENGTH 25
struct dna {
char code[LENGTH];
};
void makeArray(FILE *input,struct dna *first){
int i=0;
fscanf(input,"%c",&first->code[i]);
printf("%c",first->code[i]);
while(first->code[i] != '\n' && i < LENGTH){
i++;
fscanf(input,"%c",&first->code[i]);
printf("%c",first->code[i]);
}
}
int main() {
struct dna first;
char filename[] = "input1.txt";
FILE *input = fopen(filename,"r");
makeArray(input,&first);
fclose(input);
printf("%s",first.code);
return 0;
}
PS: i tried to not change your original code
in order to change the code[Length] in the makeArray function you will have to pass it's adresse this is why i call mkaeArray function this way : makeArray(input,&first);.

Searching A File For Specific Names in C?

I'm a relatively new programmer and I'm working on a school project. Right now what I'm trying to do is read through a file and get it to check if two characters interact(i.e they appear on the same line).
Right now I haven't too much done and I'm really asking more for ideas rather than code. How would one go about doing something like this? I had a few ideas but none of them actually worked in practise so as of now, this is all I really have done and working:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Characters{
char names[65][50]; //This is the names array
char compnames[65][50]; //This is a duplicate to compare the arrays of characters
int relations;
};
void NameFun();
int main(){
NameFun();
}
void NameFun(){
int i=0, choice;
struct Characters c;
FILE *fp = NULL;
fp = fopen("MisNames.txt", "r");
for(i=0; i<65; i++){
fgets(c.names[i], sizeof(c.names[i]), fp); //Gets each name and stores it as an element of an array
strcpy(c.compnames[i], c.names[i]); //For the duplicate, copying the elements
}
/*The rest of this was for testing purposes and has no real relevance
printf("What number name would you like to know about?\n");
scanf("%d", &choice);
choice = choice--;
printf("\t\t\t%s\n\n", c.names[choice]);
fclose(fp);
}*/

Reading data from an Ubuntu terminal and storing it in different variables in C

I am writing a program that stores information of the iwscan Ubuntu command. I am actually reading properly the file that is created with the information; however, when trying to store data(ESSID in a string, Channel in an int and Quality in a double), I have several problems treating the strings to extract the data...
The code is as following:
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
char *tratarEssid(char *cadena);
int tratarCanal(char *cadena);
double tratarCalidad(char *cadena);
int tratarCanal(char *cadena){
char resultado[2];
strncpy(resultado,cadena+9,2);
int canal;
canal=atoi(resultado);
return canal;
}
double tratarCalidad(char *cadena){
char resultado[6];
strncpy(resultado,cadena+8,6);
char num[2];
char den[2];
strncpy(num,resultado,2);
if(strlen(resultado)==5)
strncpy(den,resultado+3,2);
else
strncpy(den,resultado+2,2);
double numerador=atof(num);
double denominador=atof(den);
double calidad=numerador/denominador;
return calidad;
}
char *tratarEssid(char *cadena){
char *essid;
essid=(char *)malloc(sizeof(char)*10);
strncpy(essid,cadena+7,10);
return essid;
}
int main(){
int i;
const char *CHECKCANAL = "Channel:";
const char *CHECKQUALITY = "Quality=";
const char *CHECKESSID = "ESSID:";
double calidad;
int canal;
char *essid;
char cadena[20];
system("iwlist wlan0 scan | egrep \"(Channel|Signal level|ESSID)\">/home/wein/Escritorio/basic/bin/Debug/Lista.txt");
printf("Lista hecha\n");
lista=fopen("Lista.txt","r");
printf("Lista abierta\n");
while (!feof(lista)){
fgets(cadena,20,lista);
printf("%s",cadena);
if (strncmp(CHECKCANAL,cadena,strlen(CHECKCANAL))==0){
canal=tratarCanal(cadena);
printf("CANAL: %d\n",canal);
}
else if (strncmp(CHECKQUALITY,cadena,strlen(CHECKCANAL))==0){
calidad=tratarCalidad(cadena);
printf("CALIDAD: %f",calidad);
}
else if(strncmp(CHECKESSID,cadena,strlen(CHECKESSID))==0){
essid=tratarEssid(cadena);
printf("ESSID: %s\n",essid);
}
}
return 0;
}
So I know that my problem is in the conditionals made to filterig and treating the useful strings, just I don't know why the strncmp doesn't work properly (It should compare the beginning of the line with content of the String, or that's the idea) and thus, the functions don't work properly (Maybe I messed up in the functions as well...). Is there any other chance for treating the strings I receive correctly??
The output of the printf of the char[] cadena is just like this
Channel:11
Frequency:2.462 GH
z (Channel 11)
Quality=57/70 Sig
nal level=-53 dBm
ESSID:"eduroam"
And I should be able to extract from there the ESSID, Quality and Channel.
Thanks for any idea/suggestion/help received.
use strtok() on cadena[] to divide the string into tokens as,
token[0]=strtok(cadena,"\n") //considering the output you gave each date is in newline
token[1]=strtok(NULL,"\n")
token[2]=strtok(NULL,"\n")
token[3]=strtok(NULL,"\n")
token[4]=strtok(NULL,"\n")
token[5]=strtok(NULL,"\n")
then use sscanf() to get the required data from the token as,
sscanf(token[5],"ESSID:%s",ESSID);
sscanf(token[3],"Quality=%d/%d",&q1,&q2 ) //quality=q1/q2
sscanf(token[0],"Channel:%d",&channel)
this will give the required values from the string cadena[].
Your strncpy function calls don't add the terminator to the strings you copy to. Besides, they are to small to contain the terminator.
That means that when you call functions such as atoi on an unterminated string it will cause undefined behavior, as the function continues beyond the end of the allocated memory.

Resources