I have a text file having info as
Emp_Id Dept_Id
1 1
1 2
1 3
2 2
2 4
I am trying to read this file through C with this code below :
#include "stdio.h"
#include "stdlib.h"
int main()
{
FILE *fp;
char line[100];
char fname[] = "emp_dept_Id.txt";
int emp_id, dept_id;
// Read the file in read mode
fp = fopen(fname, "r");
// check if file does not exist
if (fp == NULL)
{
printf("File does not exist");
exit(-1);
}
while (fgets(line, 100, fp) != NULL)
{
printf("%s", line);
sscanf(line, "%s %s", &emp_id, &dept_id);
printf("%s %s", dept_id, dept_id);
}
fclose(fp);
return 0;
}
While i am trying to compile the code its all fine but when running it shows the follwoing error :
Segmentation fault (core dumped)
What can be the possible solution and mistakes for my code .
thanks
P.S : I am on IBM AIX and using CC . And have no other option to move from them .
Use %d to scan and print integers:
sscanf(line, "%d %d", &emp_id, &dept_id);
printf("%d %d", dept_id,dept_id);
(You should probably be checking the return value of sscanf as well, to make sure it really did read two integers - reading the first line into integers isn't going to work.)
You are trying to scan and print two integers using %s, it should be %d.
Your code invokes undefined behaviour because you use the wrong conversion specifier for reading and printing integers. You should use %d instead of %s. Also, output a newline to immediately print output to the screen as stdin stream is line buffered by default. Change your while loop to
while(fgets(line, 100, fp) != NULL)
{
// output a newline to immediately print the output
printf("%s\n", line);
// change %s to %d. also space is not needed
// between %d and %d since %d skips the leading
// whitespace characters
sscanf(line, "%d%d", &emp_id, &dept_id);
// sscanf returns the number of input items
// successfully matched and assigned. you should
// check this value in case the data in the file
// is not in the correct format
// output a newline to immediately print the output
printf("%d %d\n", dept_id, dept_id);
}
Related
I am currently learning reading from files in C.
Anyway, cutting to the chase:
Text file content:
123456 James Doakes; 0
987987 Dexter Morgan; 0
010203 Masuka Perv; 0
int main()
{
char accountNr[ACCOUNTNRSIZE], ownerName[NAMESIZE], enter[3];
int accountBalance = 0;
char filename[] = "breg.txt";
FILE *file = fopen(filename, "r");
if (file != NULL) {
char line[128];
while (fgets(line, sizeof(line), file) != NULL) {
sscanf(line, "%s %[^;] %d ", accountNr, ownerName, &accountBalance);
printf("%s", ownerName);
//fflushstdin();
}
fclose(file);
} else {
perror(filename);
}
return 0;
}
I wrote this to check if the name for instance James Doakes was registered correctly :
printf("%s", ownerName);
But when it prints that out it's like the stdout is still active and I can push Enter and it will type the name again. My goal is to of course be able to sscanff the number, the full name, and the last number as seperate variables. But it obviously doesn't work. I am guessing a \n gets registered as well. Dunno, I am just speculating.
What am I doing wrong? Why? And how do I solve this?
Much appreciated,
Mif
%s %[^;] %d
means a string terminated by white space, optional white space, a sequence of characters that are not ;, optional white space, then a number.
You appear to be not scanning for the actual ; character itself so that, when you try to get the number, the ; in the input stream will cause it to fail. You can see this with:
#include <stdio.h>
#define ACCOUNTNRSIZE 100
#define NAMESIZE 100
int main (void) {
char accountNr[ACCOUNTNRSIZE], ownerName[NAMESIZE], enter[3];
int accountBalance = 0;
char filename[] = "breg.txt";
FILE *file = fopen(filename, "r");
if (file != NULL) {
char line[128];
while (fgets(line, sizeof(line), file) != NULL) {
int count = sscanf(line, "%s %[^;] %d ", accountNr, ownerName, &accountBalance);
printf ("%d [%s] [%s] [%d]\n", count, accountNr, ownerName, accountBalance);
}
fclose(file);
} else {
perror(filename);
}
return 0;
}
which outputs:
2 [123456] [James Doakes] [0]
2 [987987] [Dexter Morgan] [0]
2 [010203] [Masuka Perv] [0]
In fact, even if you change the breg.txt file to be:
123456 James Doakes; 314159
987987 Dexter Morgan; 271828
010203 Masuka Perv; 42
you still get 0 for the account balance because the scanning only successfully reads two items.
Whenever you use one of the scanf-family functions, you should check the return code to ensure it's scanning the correct number of items, as in:
int count = sscanf (line, "%s %[^;] %d ", accountNr, ownerName, &accountBalance);
if (count != 3) {
fprintf (stderr, "Catostrophic failure, count is %d\n", count);
return 1;
}
The fix here is relatively simple, just use %s %[^;]; %d as the format string.
With that change, the output you see is:
3 [123456] [James Doakes] [314159]
3 [987987] [Dexter Morgan] [271828]
3 [010203] [Masuka Perv] [42]
Keep in mind you don't actually need a space before the %d (though it causes no harm). That particular format specifier skips white space before attempting to scan the number.
This is my first post here so dont really know how to post something here with correct format. I have a question on how to read a line from file and read some of the words as string and some as Int.
int check = sscanf(read, "%s %d", string, &integer);
printf("%s, %d", string, integer);
Above is kind of what I did. The input is "oneword 1". What I got is "(null) 4196448". So how can I do it correctly? Thank you
Here is part of my code.
int i;
for (i = 1; i <= 3; i++)
{
char read[MAX_LENGTH_INPUT];
fgets(read, sizeof(read), stdin);
int check2 = sscanf(read, "%s %d", word, &number);
printf("%s %d\n", word, number);
}
So the for loop is to scan three lines in .in file. Can I do that?
Here is the .in file which is the input.
oneword 1
twoword 2
thirdword 3
The output was
(null) 4196448
(null) 4196448
(null) 4196448
Also in your code int check2 = sscanf(read, "%s %d %d", word, &number); format specifier are 3 but arguments 2.
if file contain data like
oneword 1
secondword 2
thirdword 3
fourthword 4
Then
#include <stdio.h>
int main ()
{
FILE *fp = fopen("file", "r");
char read[100];
int integer;
char string[64];
while (fgets(read, sizeof(read), fp) != NULL)
{
int check = sscanf(read, "%s %d", string, &integer);
if (check == 2) {
printf("%s, %d\n", string, integer);
}
else{
printf("Failed to scan all values\n");
}
}
}
And output is
oneword, 1
secondword, 2
thirdword, 3
fourthword, 4
You can modify fgets here to take input from stdin by just replacing fp by stdin in line while (fgets(read, sizeof(read), fp) != NULL)
You are using sscanf
which reads data from char * type and stores them according to parameter format into the locations given by the additional arguments, as if scanf was used, but reading from string instead of the standard input (stdin).
you need to use fscanf and read in your code should be pointer to a FILE.
This is a homework assignment for my C Programming class.
I am given a text file, with two data columns; the first column is the age; the second column is the avgprice. I'm able to read and print the values fine. However, for some reason the age and avgprice are flipped in the output. I have no clue why.
Here is the code
#include "stdafx.h"
#include <stdio.h>
int main() {
double age, avgprice; //age = 1st column, avgprice = 2nd column
FILE *corolla; //ptr for file
char eof; //needed for end of file check
corolla = fopen("C:/Users/Nate/Downloads/DataFiles/corolla.txt", "r");
if (corolla == NULL) { //makes sure the file exists
printf("File does not exist!\n");
return 0; //prevents crashing
}
else {
printf("Age \t\t Average Price\n"); //header for data when printed
/*prints values until we're at the end of the file*/
while (fscanf(corolla, "%c", &eof) != EOF) {
fscanf(corolla, "%lf %lf", &age, &avgprice); //scans in data from file
printf("%.1f \t\t $%.2f\n", age, avgprice); //prints data from file
}
}
fclose(corolla); //closes file
return 0;
}
This is what the output looks like
It's puzzling to me because I have used this exact format to do the same thing with other data files--no issues. For some reason, this one file is having difficulty.
Here is the datafile I'm supposed to be reading. I've uploaded it to my Dropbox that way you can inspect the formatting if necessary. Corolla.txt
This line:
while (fscanf(corolla, "%c", &eof) != EOF)
reads a character from the file. The first character in the file is 1 so it reads that 1 into eof.
Your next line is:
fscanf(corolla, "%lf %lf", &age, &avgprice);
which reads the next two entries from the file, which are 13990 and 2, in that order. So the first age is 13990 and the first avgprice is 2.
After that, the file pointer is now pointing to the blank space after the 2. When you go:
fscanf(corolla, "%c", &eof)
it reads a space into eof.
Then when you get to:
fscanf(corolla, "%lf %lf", &age, &avgprice);
It reads the next two values, 13495 and 3 respectively. And so on.
To fix this you should stop doing fscanf(corolla, "%c", &eof). I don't know what you are expecting this to do exactly , but it does not test whether you're at the end of the file or not. Instead it reads a character, ignores the character, and checks the return value of fscanf.
To fix your code:
while (2 == fscanf(corolla, "%lf %lf", &age, &avgprice))
{
printf("%.1f \t\t $%.2f\n", age, avgprice); //prints data from file
}
The return value of fscanf is the number of items successfully read (if it succeeded). When it returns something other than 2 you know you must have hit the end of the file.
Your input file uses a line-based format. fscanf reads the input chunk by chunk. A chunk is usually something separated by white space, which can be space, tabs or even the new-line. Therefore fscanf is not suited to read line-based formats.
In my opinion, it is better to read the input in two steps: first, read a line with fgets, then read the data from that line with sscanf. For example:
#include <stdlib.h>
#include <stdio.h>
int main()
{
FILE *f;
int line = 0;
f = fopen("kk", "r");
if (f == NULL) {
printf("File does not exist!\n");
return 0;
}
printf("%20s%20s\n", "age", "avg. price ($)");
for (;;) {
char buffer[80];
int age, price;
if (fgets(buffer, sizeof(buffer), f) == NULL) break;
line++;
if (sscanf(buffer, "%d %d", &age, &price) < 2) {
printf("(Skipping bad input in line %d).\n", line);
} else {
printf("%20d%20d\n", age, price);
}
}
fclose(f);
return 0;
}
This also gives you a kind of low-level error reporting.
Also, there's usually no need to do extra checking for EOF. The file input functions return a special value when the end of the file is reached. fscanf and getc return EOF; fgets returns NULL. It is usually always better to stop reading based on these return values.
In your case, the fscanf("%c", &oef) eats up the first character in your file, the digit 1. Luckily, after that it only feeds on new-line so your input doesn't get tripped up worse. (But change your scan format to "%lf %lf " for a drastic price reduction.)
I have a text file that contains the following three lines:
12 5 6
4 2
7 9
I can use the fscanf function to read the first 3 values and store them in 3 variables. But I can't read the rest.
I tried using the fseek function, but it works only on binary files.
Please help me store all the values in integer variables.
A simple solution using fscanf:
void read_ints (const char* file_name)
{
FILE* file = fopen (file_name, "r");
int i = 0;
fscanf (file, "%d", &i);
while (!feof (file))
{
printf ("%d ", i);
fscanf (file, "%d", &i);
}
fclose (file);
}
How about this?
fscanf(file,"%d %d %d %d %d %d %d",&line1_1,&line1_2, &line1_3, &line2_1, &line2_2, &line3_1, &line3_2);
In this case spaces in fscanf match multiple occurrences of any whitespace until the next token in found.
I am new to C, and want to read some data from a file.
Actually, I find many reading functions, fgetc, fgets, etc..
But I don't know which one/combination is the best to read a file with the following format:
0 1500 100.50
1 200 9
2 150 10
I just need to save each row above into a struct with three data members.
I just need to know the best practice to do that, hence I am new to C programming.
Thanks.
Try reading each line using fgets. With each line, you can then use sscanf.
FILE* f = fopen("filename.txt", "r");
if (f) {
char linebuff[1024];
char* line = fgets(linebuff, 1024, f);
while (line != NULL) {
int first, second;
float third;
if (sscanf(line, "%d %d %g", &first, &second, &third) == 3) {
// do something with them..
} else {
// handle the case where it was not matched.
}
line = fgets(linebuff, 1024, f);
}
fclose(f);
}
This may have errors, but it's just meant to give you an example of how you might use the functions. Be sure to validate what sscanf returns you.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void
read_file(const char *fname)
{
FILE *f;
char line[1024];
int lineno, int1, int2, nbytes;
double dbl;
if ((f = fopen(fname, "r")) == NULL) {
perror("fopen");
exit(EXIT_FAILURE);
}
for (lineno = 1; fgets(line, sizeof line, f) != NULL; lineno++) {
int fields = sscanf(line, " %d %d %lg %n", &int1, &int2, &dbl, &nbytes);
if (fields != 3 || (size_t) nbytes != strlen(line)) {
fprintf(stderr, "E: %s:%d: badly formatted data\n", fname, lineno);
exit(EXIT_FAILURE);
}
/* do something with the numbers */
fprintf(stdout, "number one is %d, number two is %d, number three is %f\n", int1, int2, dbl);
}
if (fclose(f) == EOF) {
perror("fclose");
exit(EXIT_FAILURE);
}
}
int main(void)
{
read_file("filename.txt");
return 0;
}
Some notes on the code:
The fscanf function is quite difficult to use. I had to experiment a while until I got it right. The space characters between the %d and %lg are necessary so that any white-space between the numbers is skipped. This is especially important at the end of the line, where the newline character must be read.
Most of the code is concerned with checking errors thoroughly. Almost every return value of a function call is checked whether it succeeded or not. In addition, the number of fields and the number of characters that have been read are compared to the expected values.
The format strings for fscanf and fprintf differ in subtle details. Be sure to read the documentation for them.
I used the combination of fgets to read one line at a time and sscanf to parse the fields. I did this because it seemed impossible to me to match a single \n using fscanf.
I used the GNU C Compiler with the standard warning flags -Wall -Wextra. This helped to avoid some easy mistakes.
Update: I forgot to check that each invocation of fgets reads exactly one line. There might be lines that are too long to fit into the buffer. One should check that the line always ends with \n.