fscanf not advancing pointer - c

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

Related

write file to structs

I want to write and read some statics from file to structs.
write from structs to file is work of but write data from file isn't ok.
I will be grateful to help me what is the problem.
#include <stdio.h>
#include <stdlib.h>
const char* MemberFormatIn="(%[^,], %[^,], %[^,], %d)";
const char* MemberFormatOut="(%s, %s, %s, %d)\n";
typedef struct member {
char name[20],
lastName[20],
address[20];
int age;
}p1,p2;
void inputMemberList(struct member p[],int count) {
printf("name:");
scanf("%s",p[count].name);
printf("lastName:");
scanf("%s",p[count].lastName);
printf("address:");
scanf("%s",p[count].address);
printf("age:");
scanf("%d",&p[count].age);
}
void printMemberList(struct member p[],int count) {
system("cls");
for(int i=0; i<count; i++) {
printf("\aMember %d:\n", i+1);
printf("Name is: %s", p[i].name);
printf("\nLast name is: %s", p[i].lastName);
printf("\nAddress is: %s", p[i].address);
printf("\nAge is: %d", p[i].age);
printf("\n\n");
}
}
void saveMember(struct member p[],int count) {
FILE* fp = fopen("member.txt","a+");
if (fp == NULL) {
printf("File can't open.");
exit(1);
}
fprintf(fp, MemberFormatOut, p[count].name, p[count].lastName, p[count].address, p[count].age);
fclose(fp);
}
void fileToStructure(struct member p[],int count) {
FILE* fp = fopen("member.txt","a+");
if (fp == NULL) {
printf("File can't open.");
exit(1);
}
fseek(fp, 0, SEEK_SET);
for (int i=0; i<count+1; i++) {
fscanf(fp, MemberFormatIn, p[i].name, p[i].lastName, p[i].address, &p[i].age);
}
fclose(fp);
}
int numberOfMember() {
int count = 0;
char c;
FILE* fp = fopen("member.txt","r");
if(fp == NULL) {
printf("File can't open.");
exit(1);
}
do {
c = fgetc(fp);
if(c == '\n')
count++;
}while(c != EOF);
fclose(fp);
return count;
}
int main() {
int len = 100;
p1 p[len];
int count = numberOfMember();
inputMemberList(p,count);
saveMember(p,count);
fileToStructure(p,count);
printMemberList(p,count);
return 0;
}
at result just statics of member true and shown show but the others doesn't true.
File data(example):
(ahmad, dad, tir, 12)
(hossein, dad, tiran, 12)
(ali, dad, tir, 15)
(mohammadi, mmad, tiron, 16)
(helma, dad, tiran, 5)
(mohammad, amin, dadkhah, 5)
output(example):
Member 1:
Name is: ahmad
Last name is: dad
Address is: tir
Age is: 12
Member 2:
Name is: ├wöΩ\`
Last name is:
Address is: ↑
Age is: 0
Member 3:
Name is: Ä
Last name is: t
Address is: e
Age is: 7471221
Member 4:
Name is: r
Last name is: l
Address is: o
Age is: 6881396
Member 5:
Name is: n
Last name is: s
Address is:
Age is: 0
Member 6:
Name is:
Last name is:
Address is:
Age is: 0
In fileToStructure(), the first iteration of the loop calls fscanf() and if all is OK, the next character to be read from the file will be the newline character at the end of the first line. Unfortunately for the next iteration, the next call to fscanf() is expecting to read the ( character, but instead it reads the newline character. This will cause this call to fscanf() and all the subsequent calls to fail to match anything and return EOF.
The code needs to eat the newline character. One way to do that is to change the MemberFormatIn format string to one of the following:
const char* MemberFormatIn=" (%[^,], %[^,], %[^,], %d)"; - will discard any whitespace characters before the ( character; or
const char* MemberFormatIn="(%[^,], %[^,], %[^,], %d) "; - will discard any whitespace characters after the ) character.
The first one (discarding whitespace before the ( character) would be preferable for interactive input, but it doesn't matter too much when reading from a file.

How to properly fscanf txt file in 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++;
}

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.

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].

C parsing fgets() char array into multiple variables with sscanf using structures

In this program it compiles but i get segmentation fault, sscanf(str, "%d %s %s %d %f", &pos, z[pos-1].city, z[pos-1].state, &z[pos-1].population, &z[pos-1].growth); its because this line z[pos-1].city, z[pos-1].state, doesnt have & but when i add that i get warning: format â%sâ expects type âchar *â, but argument 4 has type âchar (*)[200]â.
i'm sure there is another way of doing this, i need to use structure, read in file store info into an array of a structure then displaying the array. the printf works just storing the city and state into char array.
I commented the area where i tried to initialize to array and had an incompatable type with the char array value all three: a, 'a', "a".
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct{
int rank;
char city[200];
char state[50];
int population;
float growth;
}city_t;
void read_data(city_t *z)
{
FILE *inp;
inp = fopen("cities.dat", "r");
char str[256];
int pos = 0;
if(inp==NULL)
{
printf("The input file does not exist\n");
}
else
{
/*reads and test until eof*/
while(1)
{
/*if EOF break while loop*/
if(feof(inp))
{break;}
else
{
/*read in a number into testNum*/
//fscanf(inp, "%d", &testNum);
fgets(str,sizeof(str),inp);
sscanf(str, "%d %s %s %d %f", &pos, z[pos-1].city, z[pos-1].state, &z[pos-1].population, &z[pos-1].growth);
z[pos-1].rank = pos;
}
}
}
fclose(inp);
}
void print_data(city_t *z, int size)
{
int i;
printf("rank\tcity\t\tstate\tpopulation\t\tgrowth\n");
for(i=0;i<size;i++)
{
printf("%d\t%s\t\t%s\t\%d\t\t%f\n", z[i].rank, z[i].city, z[i].state, z[i].population, z[i].growth);
}
}
int main()
{
int i;
city_t cities[10];
/*for(i;i<10;i++)
{
cities[i].rank = 0;
cities[i].city = "a";
cities[i].state = "a";
cities[i].population = 0;
cities[i].growth = 0.00;
}*/
read_data(&cities[0]);
print_data(&cities[0], 10);
return(0);
}
{
dat file
1 New_York NY 8143197 9.4
2 Los_Angeles CA 3844829 6.0
3 Chicago IL 2842518 4.0
4 Houston TX 2016582 19.8
5 Philadelphia PA 1463281 -4.3
6 Phoenix AZ 1461575 34.3
7 San_Antonio TX 1256509 22.3
8 San_Diego CA 1255540 10.2
9 Dallas TX 1213825 18.0
10 San_Jose CA 912332 14.4
}
In read_data, you scan into z[pos-1].... where pos starts at 0. So you will be writing beyond (before) the extend of the array.
Just do a global replace of pos-1 with pos and also increment pos; you can also use fscanf, so your reading can be:
for (int pos=0; !feof(inp); ++pos)
{
fscanf(inp, "%d %s %s %d %f",
&z[pos].rank,
z[pos].city,
z[pos].state,
&z[pos].population,
&z[pos].growth);
}

Resources