C fscanf input format - c

I have an input file that contains lines of the following format:
%s %d %d %d %lf %lf ... %lf\n
where the number of double values is unknown, but for my calculations I accept only first 15 of them.
The problem I can't figure out is, when I get to the line like this:
City0 28 2 2016 1 2 3 4 5 6 7 8 9 10
City1 28 2 2016 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
City2 1 3 2016 1 2 3 4 5
and I correctly assign respective values to a certain structure, I get the following:
City0 28 2 2016 Number of measures: 10
City1 28 2 2016 Number of measures: 15
16 17 18 19 Number of measures: 1
City2 1 3 2016 Number of measures: 5
How do I read(to nowhere)/ignore everything until I get to the end of the line, and then start reading the next line as usual? I need the following output:
City0 28 2 2016 Number of measures: 10
City1 28 2 2016 Number of measures: 15
City2 1 3 2016 Number of measures: 5
I tried this but ain't got any more ideas:
i=0; char character;
while (fscanf(fp, "%s %d %d %d", c.name, &c[i].date.day,
&c[i].date.month, &c[i].date.year)==4 && i<number_of_cities) {
while (fscanf(fp, "%lf", &c[i].measures[j])==1 && j<15) {
j++;
}
if (j==15) {
while (fscanf(fp, "%s", character)!='\n') {}
}
c[i].mnum = j;
j=0;
i++;
}

You can use fscanf() to read in an entire line of input, use sscanf() to scan the first four values, and use sscanf() again in a loop to read the double values. The trick here is to use the %n directive to save the position of the next read location in the string.
Here is an example. Note that size_t is used for array indices, as this is an unsigned integer type that is guaranteed to hold any array index. Also note that there is some error-checking when opening the file, and when scanning the beginning of a line. If the initial elements of the line do not match expected values, the program exits with an error message. This error-checking could be tightened up a bit; for example, if the year is entered as a floating point value, such as 2016.0, the input will be accepted, but the values stored in measures[] will begin with the 0 following the decimal point.
#include <stdio.h>
#include <stdlib.h>
struct Data {
char name[1000];
struct {
int day;
int month;
int year;
} date;
size_t mnum;
double measures[15];
};
int main(void)
{
size_t i = 0, j = 0;
char buffer[1000];
char *read_ptr = buffer;
int n_read = 0;
size_t number_of_cities = 3;
struct Data c[number_of_cities];
FILE *fp;
if ((fp = fopen("datafile.txt", "r")) == NULL) {
fprintf(stderr, "Unable to open file\n");
exit(EXIT_FAILURE);
}
while (fgets(buffer, 1000, fp) != NULL) {
if (sscanf(buffer, "%s %d %d %d %n", c[i].name, &c[i].date.day,
&c[i].date.month, &c[i].date.year, &n_read) != 4) {
fprintf(stderr, "Incorrect input format\n");
exit(EXIT_FAILURE);
}
read_ptr += n_read;
while (sscanf(read_ptr, "%lf %n", &c[i].measures[j], &n_read) == 1 &&
j < 15) {
read_ptr += n_read;
++j;
}
c[i].mnum = j;
++i;
j = 0;
read_ptr = buffer;
if (i == number_of_cities) {
break;
}
}
for (i = 0; i < number_of_cities; i++) {
printf("%s %d %d %d Number of measures: %zu\n",
c[i].name,
c[i].date.day, c[i].date.month, c[i].date.year,
c[i].mnum);
for (j = 0; j < c[i].mnum; j++) {
printf("%5g", c[i].measures[j]);
}
putchar('\n');
}
return 0;
}
Program output using your example data as input:
City0 28 2 2016 Number of measures: 10
1 2 3 4 5 6 7 8 9 10
City1 28 2 2016 Number of measures: 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
City2 1 3 2016 Number of measures: 5
1 2 3 4 5

Related

Ignoring escape sequence in C

I need to enter a matrix of size NxN of integers.
My idea is to enter it as a sequence of chars into char array and proceed working with it.
Matrix is given into stdin all at once.
The problem is to ignore escape characters (e.g. "\n") and enter all NxN integers as one string where integers will be separated with space.
Matrix itself is copied from txt file.
Input must end when Enter key is pressed.
//en axample of what I'm trying to reach
char buff[512];
gets(buff);
/*1 2 9 10 25
4 3 8 11 24
5 6 7 12 23
16 15 13 14 22
17 18 19 20 21*/
printf("%s", buff);
/*1 2 9 10 25
4 3 8 11 24
5 6 7 12 23
16 15 13 14 22
17 18 19 20 21/*
I tried using gets but it ended reading symbols when "\n" is reached.
Initial code looks like this:
int main(){
int size;
printf("enter size of matrix >> ");
scanf("%d",&size);
int matrix[size][size];
char allNumbers[size][512];
for (int i = 0; i < size; i++){
fgets(allNumbers[i], 511, stdin);
}
printf("%s", allNumbers[2]);
return 0;
}
input:1 2 9 10 25\n 4 3 8 11 24\n 5 6 7 12 23\n 16 15 13 14 22\n 17 18 19 20 21\0
output:
1 2 9 10 25
Consider using one char array for input.
Generally do not use both scanf and fgets.
This uses fgets to read a line with the size and sscanf to parse the integer from the line.
The same array is used to read the lines pasted from the file.
The loop continues until an empty line is read.
It may be necessary to hit enter a few times to exit the loop.
This does not parse the integers from the file. sscanf can be used to accomplish that as well. strtol is another parsing option.
#include <stdio.h>
#include <stdlib.h>
int main ( void) {
char input[512] = "";
int size = 0;
int row = 0;
int col = 0;
int offset = 0;
int used = 0;
printf ( "enter size of matrix >> ");
fflush ( stdout);
if ( ! fgets ( input, sizeof input, stdin)) {
fprintf ( stderr, "problem fgets\n");
return 1;
}
if ( 1 != sscanf ( input, "%d", &size)) {
fprintf ( stderr, "problem sscanf for size\n");
return 2;
}
int matrix[size][size];
for ( row = 0; row < size; ++row) {
for ( col = 0; col < size; ++col) {
matrix[row][col] = 0;
}
}
row = 0;
printf ( "enter matrix values >> ");
while ( fgets ( input, sizeof input, stdin)){
if ( '\n' == input[0]) {
break;
}
printf ( "\nrow %d %s", row, input);
offset = 0;
if ( row < size) {
// parse integers from input;
}
++row;
}
for ( row = 0; row < size; ++row) {
for ( col = 0; col < size; ++col) {
printf ( "%4d ", matrix[row][col]);
}
printf ( "\n");
}
return 0;
}

How to use input letter to print on the screen the list of employees whose name starts with that letter and their corresponding info

The problem consist of 2 array structures and each task is broken down into functions. I need help with the function that would ask the user for a letter and print on the screen the list of employees whose name starts with that letter.
These are the files.
employees.txt
Jimmy OBrien 1234567D Irish 40 1 2
David Keogh 3234567F Irish 61 0 0
David Hanahoe 5234567G Irish 48 1 2
Tom Byrne 6234567N Irish 62 1 4
Thomas Collins 8234567B Irish 35 0 0
Aoife Murphy 4234567F Irish 63 1 3
Joan OBrien 5234567M Irish 36 1 1
Maria Ionescu 7734567E Romanian 43 1 2
Celine Keogh 2254893R Irish 38 1 0
benefits.txt
1234567D 37500 20 10 0
3234567F 40000 20 10 0
5234567G 42000 20 10 0
6234567N 45000 20 10 0
8234567B 47000 20 10 0
4234567F 50000 20 10 0
5234567M 55000 20 10 0
7734567E 60000 20 10 0
5234997P 75000 20 10 0
2254893R 75000 20 10 0
void input_letter()
{
char letter[1];
int i;
printf("Please enter a letter of a employee. \n ");
scanf("%c", letter);
printf("\nNAME\tSURNAME\tPPS\tSALARY\tPENSION\tALLOWANCE\n");
for(i = 0; i < no_emplo; ++i)
{
if(strcmp(emplo[i].name, letter) == 0) {
printf("\n%s\t%s\t%s\t%d\t%d\t%d\n",
emplo[i].name,
emplo[i].surname,
emplo[i].PPS,
bene[i].salary,
bene[i].pension,
bene[i].allowance);
}
}
}
When I run this code, it only prints out the first 2 print functions and doesn't even allow me to input a letter.
You said you wanted to read one letter from stdin. But your variable letter is an array of size 1. It is not long enough to store a string of length 1 and the terminating '\0', so it can't be used with the %c format specifier.
Why don't you simply use a char?
void input_letter(void)
{
puts("Please enter a letter of a employee.");
char letter;
if (scanf(" %c", &letter) != 1) {
fputs("Input error!\n\n", stderr);
return;
}
puts("\nNAME\tSURNAME\tPPS\tSALARY\tPENSION\tALLOWANCE");
for(size_t i = 0; i < no_emplo; ++i)
{
if(emplo[i].name[0] == letter) {
printf("\n%s\t%s\t%s\t%d\t%d\t%d\n",
emplo[i].name,
emplo[i].surname,
emplo[i].PPS,
bene[i].salary,
bene[i].pension,
bene[i].allowance
);
}
}
}
Please consider these changes:
void input_letter()
{
char letter;
int i;
printf("Please enter a letter of a employee. \n ");
scanf("%c", & letter);
printf("\nNAME\tSURNAME\tPPS\tSALARY\tPENSION\tALLOWANCE\n");
//Prints the table
for(i=0; i<no_emplo; i++)
{
if(emplo[i].name[0] == letter) {
printf("\n%s\t%s\t%s\t%d\t%d\t%d\n",
emplo[i].name,
emplo[i].surname,
emplo[i].PPS,
bene[i].salary,
bene[i].pension,
bene[i].allowance);
}
}
}

i'm not processing more than one block correctly

I have an assignment where I'm suppose to read input lines such as
2
67 5 100 1 11 97 98 10 1 110
15 72 10 101 47 67 88 20 94 6 22 11
4
61 11 93 4 73 39 78 34 17 104
23 43 11 93 65 52 20 96 66 31 86 24 40 61 102 13 50 51
73 43 28 73 8 89 31 68 77 27 24 77 42 72 15 24 64 51
25 75 7 90 10 111 17 16
.....
process every two integers (the first line in a block only tells us how many words we will process), add them then match
them to their corresponding ASCII char. The example above would be two blocks.
The output should be:
Decoded messages:
Hello World!
Happy Bhutanese teacher's day!
I'm having problems when it comes to dealing with a file with multiple blocks, more than 20 and so forth following the same format on one input text. I can handle one block fine, two blocks okay but not fine because my program doesn't seem to end. No line will be longer than 256 characters. numOfPuzzl refers to how many words we process per block.
I'd greatly appreciate any help. I attached my code and commented as much as I can too.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
//user will type in file name they choose to process and we allocated in filename[]
char filename[256];
printf("Enter filename: ");
scanf("%s", filename);
//process filename username typed in
FILE *pFile;
pFile = fopen(filename, "r");
//if there's nothong to read
if (pFile == NULL){
exit(1);
}
printf("Decoded messages:\n");
//create array we will putting lines into
char myString[256];
//simply gets the first line, which is always a lone integer
fgets(myString, 256, pFile);
int numOfPuzzl;
sscanf(myString, "%d", &numOfPuzzl);
//printf("puzzles to solve: %d\n", numOfPuzzl);
int wordsProcessed = 0;
//just remember that myString has entire line
//start processing the lines that follow, a line is a word
while (fgets(myString, 256, pFile) != NULL){
int num = 0; //first integer in line
int secondNum = 0; //second int. in line
int tot = 0; //how many bytes
int bytes_read = 0; //bytes processed
char *endOfStrAdr = strchr(myString, '\0'); //returns address of end terminating char.
int endOfStrIdx = endOfStrAdr - myString; //this will give me the index of where the terminating char. occurs within my array
//start scanning integers within array making sure to not sccan out of bounds
while (tot < endOfStrIdx){
//first integer allocated as well as how many byes it was
sscanf(myString + tot, "%d %n", &num, &bytes_read);
tot += bytes_read; //keeps tab so we don't have to read from the begn. of array everytime
//second integer allocated as well as how many byes it was
sscanf(myString + tot, "%d %n", &secondNum, &bytes_read);
tot += bytes_read; ////keeps tab so we don't have to read from the begn. of array everytime
printf("%c", (char) num + secondNum); //add the two integers and cast them to char
//we want to check if we are the end of the string, our word
if (tot == endOfStrIdx){
printf(" ");
wordsProcessed++;
//we want to print a new line char. if we finished processing all the words for the puzzle
if (wordsProcessed == numOfPuzzl){
printf("\n");
fgets(myString, 256, pFile);
}
}
}
}
fclose(pFile);
}
Ignore blank lines between puzzles.
Reset parameters (numOfPuzzl and wordsProcessed) before processing new puzzles.
To archive that, change
if (wordsProcessed == numOfPuzzl) {
printf("\n");
fgets(myString, 256, pFile);
}
into
if (wordsProcessed == numOfPuzzl) {
printf("\n");
while ( fgets(myString, 256, pFile) != NULL ){
if ( sscanf(myString, "%d", &numOfPuzzl) == 1 )
break;
}
wordsProcessed = 0;
}
I suggest like this:
#include <stdio.h>
#include <stdlib.h>
//stringize macro
#define S_(x) #x
#define S(x) S_(x)
int main(void){
char filename[FILENAME_MAX + 1];
printf("Enter filename: ");
scanf("%" S(FILENAME_MAX) "[^\n]", filename);
FILE *pFile;
if(NULL==(pFile = fopen(filename, "r"))){
perror("can't opne file");
exit(EXIT_FAILURE);
}
printf("Decoded messages:\n");
int numOfLines;
while(1==fscanf(pFile, "%d", &numOfLines)){
for(int i = 0; i < numOfLines; ++i){
int num1, num2, state;
char ck;
while(3==(state=fscanf(pFile, "%d %d%c", &num1, &num2, &ck)) || 2 == state){
putchar(num1 + num2);
if(state == 2 || state == 3 && ck == '\n')
break;
}
putchar(' ');
}
putchar('\n');
}
fclose(pFile);
return 0;
}

How to use fscanf() to read a file containing integer number?

I need to use fscanf() to read a file containing integers from multiple lines.
The first integer is useless on every line; the rest I need to read.
I am doing like this
do {
fscanf(fs1[0],"%d%c",&x,&y);
//y=fgetc(fs1[0]);
if(y!='\n') {
printf("%d ",x);
}
} while(!feof(fs1[0]));
but in vain. For example,
101 8 5
102 10
103 9 3 5 6 2
104 2 6 3 8 7 5 4 9
105 8 7 2 9 10 3
106 10 6 5 4 2 3 9 8
107 3 8 10 4 2
we have to read
8 5
10
9 3 5 6 2
2 6 3 8 7 5 4 9
8 7 2 9 10 3
10 6 5 4 2 3 9 8
3 8 10 4 2
AFTER you have read file in a string, (fgets)
you can use (strtok), to split string and then use
(sscanf) to read integer.
strtok :
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL) {
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
sscanf :
int number = 0;
if(sscanf(pch, "%d", &number) ;
You should use fgets() to read the file line by line and then parse the numbers using sscanf(). You can then skip the first number for each line just as you please.
Here is an example:
#include <stdio.h>
#include <string.h>
int main() {
char fname[] = "filename.txt";
char buf[256];
char *p;
/* open file for reading */
FILE * f = fopen(fname, "r");
/* read the file line-wise */
while(p = fgets(buf, sizeof(buf), f)) {
int x, i = 0, n = 0;
/* extract numbers from line */
while (sscanf(p+=n, "%d%n", &x, &n) > 0)
/* skip the first, print the rest */
if (i++ > 0)
printf("%d ", x);
printf("\n");
}
}
For reference:
http://linux.die.net/man/3/fgets
http://linux.die.net/man/3/sscanf
do{
fscanf(fs1[0], "%d%c",&x,&y);//ignore first data.
while(2==fscanf(fs1[0], "%d%c", &x, &y)){
printf("%d ", x);
ch = fgetc(fs1[0]);//int ch;
if(ch == '\n' || ch == EOF){
printf("\n");
break;
} else
ungetc(ch, fs1[0]);
}
}while(!feof(fs1[0]));

How to read a multi line using fscanf

I want to read my data.txt file which looks like and store it in an array called buffer[i][j]
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
I am writing a code which looks like
#include"stdio.h"
#include"stdlib.h"
int main() {
FILE *fp1;
int i,j;
int buffer[4][4]={0};
fp1 = fopen("exact_enumerated_config_442_cub_mc","r");
for(i=0;i<4;i++) {
for(j=0;j<4;j++) {
fscanf(fp1,"%d", &buffer[i][j]);
}
// fscanf(fp1,"\n");
}
fclose(fp1);
for(i=0;i<4;i++) {
for(j=0;j<4;j++) {
printf("%d ",buffer[i][j]);
}
printf("\n");
}
}
but i get the output...
1 1 2 1
5 1 6 1
17 1 18 1
21 1 22 1
why????
Always check the result of fopen() to ensure the file has been opened.
Always check the result of fscanf() to ensure it was successful and prevent subsequent code processing variables that may not have been assigned a value (it returns the number of assignments made).
Add a leading space character to the format specifier to skip whitespace, including newline characters: " %d".
The code will treat a single line with sixteen ints the same as four lines with four ints. If it is important that the format of the file is four ints per line then read a single line using fgets() and then use sscanf() to extract the ints with the %n format specifier to ensure full buffer was processed:
int ints[4][4] = { { 0 } };
char buffer[1024];
for (int i = 0; i < 4 && fgets(buffer, 1024, fp); i++)
{
int pos;
if (sscanf(buffer,
"%d %d %d %d%n",
&ints[i][0],
&ints[i][1],
&ints[i][2],
&ints[i][3],
&pos) != 4 || pos != strlen(buffer) - 1)
{
fprintf(stderr, "Invalid format: <%s>\n", buffer);
exit(1);
}
}
Add space at the beginning of the string format it should be " %d" to avoid the newline problems
fscanf(fp1," %d", &buffer[i][j]);
BTW you could use the following code instead
for(i=0;i<4;i++) {
fscanf(fp1," %d %d %d %d", &buffer[i][0], &buffer[i][1], &buffer[i][2], &buffer[i][3]);
}
To get required output (1111,2222,...) change:
fp1 = fopen("exact_enumerated_config_442_cub_mc","r");
to:
fp1 = fopen("data.txt","r");
Clarification: when using fopen you should write the name of file you want to read. In you case you have to write data.txt, not exact_enumerated_config_442_cub_mc...
There is no file with this name, moreover there is no any data like 1 1 1 1, 2 2 2 2, 3 3 3 3, 4 4 4 4...
For more detailes visit:
wikibooks.org/wiki/C_Programming/C_Reference/stdio.h/fopen
Here is your "modified" (excess/waste/extra { } removed and data.txt is written) code that gives you required output: 1 1 1 1, 2 2 2 2, 3 3 3 3, 4 4 4 4.
It prints the array named buffer. It means that...
...data was successfully copied! from "data.txt" to buffer[4][4]:
#include"stdio.h"
#include"stdlib.h"
int main()
{
FILE *fp1;
int i,j;
int buffer[4][4];
for ( i = 0; i < 4; i++ )
for ( j = 0; j < 4; j++ )
buffer[i][j] = 0;
fp1 = fopen("data.txt","r");
for(i=0; i<4; i++)
for(j=0; j<4; j++)
fscanf(fp1,"%d", &buffer[i][j]);
fclose(fp1);
for(i=0; i<4; i++)
{
for(j=0; j<4; j++)
printf("%d ",buffer[i][j]);
printf("\n");
}
return 0;
}
P.S.
If data.txt will contain not
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
but
1 1 1 1
2 2 2 2
3 3 3 3
4 444 // the last two elements are absent
the program will read 1-st, 2-nd and 3-rd line properly, and the output of the 4-th line will be
4 444 0 0
It prints 4, then 444, and then 0 and 0: the last two elements are '0's because buffer had been initialized by zeros, so all elements changed their values, but the last two remained to be zeros.
You have said you want to read data.txt then why are you opening the file exact_enumerated_config_442_cub_mc
Try changing this
fp1 = fopen("exact_enumerated_config_442_cub_mc","r");
to
fp1 = fopen("data.txt","r");

Resources