How to properly fscanf txt file in C - c

For example: #1 Tutti/Leeloo/853811356; N
And this is my code:
typedef struct{
int redni;
char prezime[50+1];
char ime[50+1];
char osobna[50+1];
char glasao[10];
} Biraliste;
int nBiraci=0;
while(fscanf(biralisteTxt, "%d %[^/]/%[^/]/%[^;];%[^\n]",
biraci[n].redni, biraci[n].prezime, biraci[n].ime, biraci[n].osobna, biraci[n].glasao ) == 5)
{
nBiraci++;
}
for(i=0;i<nBiraci;i++)
{
fprintf(statistikaTxt, "%d %s %s %s %s",
&biraci[i].redni, biraci[i].prezime, biraci[i].ime, biraci[i].osobna, biraci[i].glasao );
}
Can someone help mi with right fscanf and fprintf, and is it ok to fscanf redni with %d or it should be %s.

" #%d %[^/]/%[^/]/%[^;];%[^\n]" - this is the right answer, thank you

The following code fixes two problems.
scanf must get the address of the variable to fill, this &biraci...
the index must be nBiraci and not n, thus &biraci[nBiraci]...
there must be a # in front of %d
int nBiraci=0;
while(fscanf(biralisteTxt, " #%d %[^/]/%[^/]/%[^;];%[^\n]",
&biraci[nBiraci].redni, (char*)&biraci[nBiraci].prezime,
(char*)&biraci[nBiraci].ime, (char*)&biraci[nBiraci].osobna,
(char*)&biraci[nBiraci].glasao) == 5)
{
nBiraci++;
}

Related

fscanf not advancing pointer

I used fscanf to parse a file, but on same cases it seem that the pointer does not advance correctly, and althought I thing I am using the right format to parsing the lines, the \n is not read, the pointer is not moved forward, and next fscanf returns the same line since the pointer does not advance.
I had to do an additional fgets to get the pointer advancing to next line/record.
Particularly, I have two cases on my code below, that I do not understand:
a).- After reading the ESSID with a first fscanf, I had to do another additional fscanf to be able to advance the pointer
b).- After reading the "Signal Level" at end of the code using fscanf(filePointer, "%*[^-0123456789] %i\n", &n1); the file pointer did not advance. I had to do resultado=fgets(buffer, bufferLength, filePointer) to keep on advancing pointer.
What I am doing worng to the parsing that forces me to do new reads to advance the file pointers?
See for example, the following code:
#include <stdio.h>
#include <string.h>
#define MAXCELLS 10
#define MAXCHAR 40
#define DO_DEBUG 1
struct structCell
{
int idCell;
char MacAddress[MAXCHAR];
char Essid[MAXCHAR];
char Mode[MAXCHAR];
int Channel;
char Encrypted[MAXCHAR];
int Quality1;
int Quality2;
float Frequency;
int SignalLevel;
};
typedef struct structCell Cell;
void main()
{
Cell cell[MAXCELLS];
FILE* filePointer;
char* resultado;
char filename [MAXCHAR]="./cells/info_cell_6.txt";
int bufferLength = 255;
char buffer[bufferLength];
int cell_pos=0;
char data[20] = {0};
char ignore[20] = {0};
int n1, n2;
float f1;
if ( (filePointer = fopen(filename, "r") ) == NULL) {
printf("ERROR!! Unable to open file %s.\n", filename);
} else {
while (fscanf(filePointer, "Cell %i \n", &n1)!=EOF) {
printf ("\n\nReading Record number %d\n",cell_pos+1);
// We already have fist line of the record (idCell)
printf ("Cell %i \n", n1);
cell[cell_pos].idCell=n1;
// Address : Get address data
fscanf(filePointer, "Address: %s\n", data);
strcpy(cell[cell_pos].MacAddress, data);
printf("Address: -%s-\n", data);
// ESSID
fscanf(filePointer, "ESSID: \"%[^\"]\"\n", data);
strcpy(cell[cell_pos].Essid, data);
printf("ESSID: -%s-\n", data);
// WHY I NEED THIS NEW FSCANF TO ADVANCE TO NEXT LINE ON FILE ?
// WHY IS NOT PREVIOUS FSCANF AUTOMATICALLY MOVES THE POINTER?
fscanf(filePointer, "%[A-Za-z]: %s\n", ignore, data);
// Mode
fscanf(filePointer, "Mode:%s\n", data);
strcpy(cell[cell_pos].Mode, data);
printf("Mode: -%s-\n", data);
// Channel
fscanf(filePointer, "%*[^0123456789] %i\n", &n1);
cell[cell_pos].Channel= n1;
printf("Chanel %i \n", n1);
// Encryption
fscanf(filePointer, "Encryption key:%s\n", data);
strcpy(cell[cell_pos].Encrypted, data);
printf("Encryption: -%s-\n", data);
// Quality
fscanf(filePointer, "%*[^0123456789] %i/%i \n", &n1,&n2);
printf("Quality = %i/%i \n", n1,n2);
cell[cell_pos].Quality1=n1;
cell[cell_pos].Quality2=n2;
fscanf(filePointer, "Frequency: %f \n", &f1);
cell[cell_pos].Frequency=f1;
printf("Frequency: %f GHz\n", f1);
fscanf(filePointer, "%*[^-0123456789] %i\n", &n1);
cell[cell_pos].SignalLevel=n1;
printf("Signal level= %i dBm\n", n1);
resultado=fgets(buffer, bufferLength, filePointer); // Why is this line needed? to advance to next line?*/
cell_pos++;
}
fclose(filePointer);
}
}
The file that is read (and that I should parse into the struct array) is the following one:
Cell 6
Address: 00:11:F5:E8:A4:54
ESSID:"Miguel 3"
Mode:Master
Channel:11
Encryption key:off
Quality=27/70
Frequency:2.462 GHz
Signal level=-83 dBm
Cell 6
Address: 90:84:0D:D8:46:89
ESSID:"acrumin"
Mode:Master
Channel:11
Encryption key:on
Quality=31/70
Frequency:2.462 GHz
Signal level=-79 dBm
Cell 6
Address: 00:27:0D:56:01:60
ESSID:"WiFi-UC3M"
Mode:Master
Channel:6
Encryption key:off
Quality=48/70
Frequency:2.437 GHz
Signal level=-62 dBm

qsort gives strange characters in the output

I want to sort employee data based on names. The sorting function works but provides strange characters in the output??
The last printf statement is the culprit I guess (bottom of the code)
If someone could help, that would be appreciated.
Thanks
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct
{
char name[25];
char firstname[25];
char job;
float hrs;
float rate;
} employee;
int main()
{
FILE *fp = fopen("employee.dat", "r");
employee staff[30];
int i = 0;
if (fp == NULL){
printf("not working\n");
exit(1);
}
fscanf(fp, "%s %s %c %f %f", staff[i].name, staff[i].firstname, &staff[i].job, &staff[i].hrs, &staff[i].rate);
while(!feof(fp))
{
printf("%s %s %c %4.1f %4.1f \n", staff[i].name, staff[i].firstname, staff[i].job, staff[i].hrs, staff[i].rate);
i++;
fscanf(fp, "%s %s %c %f %f", staff[i].name, staff[i].firstname, &staff[i].job, &staff[i].hrs, &staff[i].rate);
}
fclose(fp);
// qsort struct function for comparing names
int struct_cmp_by_name(const void *a, const void *b)
{
employee *ia = (employee *)a;
employee *ib = (employee *)b;
return strcmp(ia->name, ib->name);
}
int structs_len;
structs_len = sizeof(staff) / sizeof(employee);
// sort on names
qsort(staff, structs_len, sizeof(employee), struct_cmp_by_name);
//output with strange charaters???
for(i=0; i<structs_len; i++){
printf("%s %s %c %4.1f %4.1f \n", staff[i].name, staff[i].firstname, staff[i].job, staff[i].hrs, staff[i].rate);
}
return(0);
}
I am expecting a regular output of the printf statement.
The first printf works fine but the one after the qsort provides strange characters instead??
The most likely culprit of your problem is that you sort the whole array, even when maybe not all elements are initialized.
If the file contains less than the 30 elements you have for the array, parts of the array will be uninitialized with indeterminate contents (which may sometimes seem random or like "garbage"). You should not use those when sorting, only sort the data you actually have read from the file.
You have the number of valid and initialized elements in the array in the variable i which you should use instead:
qsort(staff, i, sizeof(employee), struct_cmp_by_name);
You have the same problem when printing the data: You print the whole array, including the uninitialized parts.
I suggest you create a new variable for the number of valid elements, suitable named, instead of the generic i that you now use.

Why is my program stopping before reading the txt file?

My code keeps closing before reading the file, I made a comment where it closes. Does anyone know why it wont work? I showed it to my lecturer but she couldn't figure it out and then she had to leave so I was wondering if anyone here could figure it out!
#include <stdio.h>
#include <stdlib.h>
#define RESULT_MAX = 100;
#define RESULT_MIN = 0;
int main()
{
int studentId;
char firstName[20];
char lastName[20];
int result;
FILE *fPtr;
if ((fPtr = fopen("student.txt", "w")) == NULL)
{
printf("File could not be opened\n");
//exit(0);
}
else
{
printf("Enter the Id, first name, last name and result\n");
scanf("%d %s %s %d", &studentId, firstName, lastName, &result);
while(!feof(stdin) )
{
fprintf(fPtr, "%d %s %s %d\n", studentId, firstName, lastName, result);
scanf("%d %s %s %d", &studentId, firstName, lastName, &result);
}
fclose(fPtr);
}//else end
// MY PROGRAM ENDS HERE AND WONT CONTINUE!
if ((fPtr = fopen("student.txt", "r")) == NULL)
{
printf("File could not be opened\n");
//exit(0);
}
else
{
printf("Id, first name, last name, result ");
fscanf(fPtr, "%d %s %s %d", &studentId, firstName, lastName, &result);
while(!feof(fPtr) )
{
printf("%d %s %s %d \n", studentId, firstName, lastName, result);
fscanf(fPtr, "%d %s %s %d", &studentId, firstName, lastName, &result);
}//end while
fclose( fPtr );
}//end if
}
the problem is actually the line: 'while(!feof(stdin) )'
because feof() only becomes valid when the program
tries to read past the end of the 'stdin' file.
This is something that cannot be accomplished
suggest
modifying the program to:
1) read into a local buffer[] array, in a loop,
2) using fgets() as the loop control
3) have a leading 'q' (or similar) as an indication of having read all input
4) output a prompt for every input line
5) if going to parse the fields, parse them using
strtok()/atoi() strncpy() strncpy() atoi()
or perhaps
sscanf()
6) check first char of input buffer[] for the end marker (the 'q' above)
to exit the input loop before parsing
there is a similar problem with the
loop reading the file
I.E. do not use feof() for loop control
rather use fgets()
to differentiate each line of input written to the file, modify
the fprintf(fPtr, ... ) format string to include a trailing '\n'

Segfault - sscanf to arrays in C

I just need an extra set of eyes to help me find out why this code is segfaulting.
//------------------------Preprocessor Instructions. ------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#define NUMBER 128 //Maxmimum number of items/lines in file.
#define BUFFER 120 //Buffer length (For user input)
#define LENGTH 32 //Maximum length of lines in file.
//------------------------Global stuff. ---------------------------------------------
int iterations=0; //Will count number of times the calculation function is called.
int weight[NUMBER];
int value[NUMBER];
char object[NUMBER][LENGTH];
//------------------------Function Definitions. -----------------------------------------
void printarr();
//------------------------Printarr -- Array printing function. --------------------------
void printarr()
{
int i,j;
printf("\n");
printf("Weight \t Value \t Object \n");
for(i=0;i<4;i++){
printf("%d \t %d \t %s \n", weight[i], value[i], &object[i][0]);
}
}
//------------------------Main. ---------------------------------------------------------
int main(int argc, char **argv)
{
FILE *fp; //File pointer.
char buffer[BUFFER]; //Temporary storage
int result; //sscanf return value.
int capacity; //User input.
int i,j=0; //Loop counters.
//Command Line Argument Parsing: Assigns input value to capacity.
if (argc != 2){
printf("Usage: %s number. Max 1024. \n",argv[0]); //Usage: *program* *num*
return(1);
}
if (1 != sscanf(argv[1],"%d",&capacity)){
printf("Usage: %s number. Max 1024. \n",argv[0]);
return(1);
}
//File reading.
fp=fopen("knapsack.data","r");
if(NULL==fp){
printf("Error opening file. \n");
exit(0);
}
//Write to arrays.
while(NULL != fgets(buffer, BUFFER, fp)){
result=sscanf(buffer, "%d %d %s", &weight[i], &value[i], &object[i][0]);
i++;
}
//Print the arrays.
printarr();
fclose(fp);
}
According to GDB it segfaults when it hits the sscanf statement. But as far as I can tell there's nothing wrong with the way I'm accessing the locations... clearly I'm mistaken. Any help would be appreciated.
Edit: I was half right, fix this line:
result=sscanf(buffer, "%d %d %s", &weight[i], &value[i], &object[i][0]);
to look like this:
result=sscanf(buffer, "%d %d %s", &weight[i], &value[i], object[i]);
You are reading in a whole string, so you need to write to the c string location, in this case, object[i]. Also, init i for best practice (although gcc does init ints to zero if uninitialized, try it yourself and see).
Edit: Ignore the downvote, I am correct but I did make an error in forgetting to remove your second index, you can access a c string 2d array with object[i] or &object[i][0], both work. object[i] for accessing an entire string looks cleaner to me than using &object[i][0].

How to read specifically formatted data from a file?

I'm supposed to read inputs and arguments from a file similar to this format:
Add id:324 name:"john" name2:"doe" num1:2009 num2:5 num2:20
The problem is I'm not allowed to use fgets. I tried with fscanf but have no idea how to ignore the ":" and seperate the string ' name:"john" '.
If you know for sure the input file will be in a well-formed, very specific format, fscanf() is always an option and will do a lot of the work for you. Below I use sscanf() instead just to illustrate without having to create a file. You can change the call to use fscanf() for your file.
#define MAXSIZE 32
const char *line = "Add id:324 name:\"john\" name2:\"doe\" num1:2009 num2:5 num3:20";
char op[MAXSIZE], name[MAXSIZE], name2[MAXSIZE];
int id, num1, num2, num3;
int count =
sscanf(line,
"%s "
"id:%d "
"name:\"%[^\"]\" " /* use "name:%s" if you want the quotes */
"name2:\"%[^\"]\" "
"num1:%d "
"num2:%d "
"num3:%d ", /* typo? */
op, &id, name, name2, &num1, &num2, &num3);
if (count == 7)
printf("%s %d %s %s %d %d %d\n", op, id, name, name2, num1, num2, num3);
else
printf("error scanning line\n");
Outputs:
Add 324 john doe 2009 5 20
Otherwise, I would manually parse the input reading a character at a time or or throw it in a buffer if for whatever reason using fgets() wasn't allowed. It's always easier to have it buffered than not IMHO. Then you could use other functions like strtok() and whatnot to do the parse.
perhaps this is what you want ?
#include <stdio.h>
#include <string.h>
int main()
{
char str[200];
FILE *fp;
fp = fopen("test.txt", "r");
while(fscanf(fp, "%s", str) == 1)
{
char* where = strchr( str, ':');
if(where != NULL )
{
printf(" ':' found at postion %d in string %s\n", where-str+1, str);
}else
{
printf("COMMAND : %s\n", str);
}
}
fclose(fp);
return 0;
}
If output of it will be
COMMAND : Add
':' found at postion 3 in string id:324
':' found at postion 5 in string name:"john"
':' found at postion 6 in string name2:"doe"
':' found at postion 5 in string num1:2009
':' found at postion 5 in string num2:5
':' found at postion 5 in string num2:20

Resources