Scanning strings and ints from file into array in C - c

I am scanning from a file into parallel arrays.
I successfully scan the strings, but the ints and floats do not scan correctly!
What is going wrong here???
Num, human, and cool are arrays declared in the main function.
An example of a record in hello.txt:
Angela, Merkel, 50, 10, 9.1
void read(int *lines, char first[ENTRY][FIRST], char last[ENTRY][LAST], int *num, int *human, float *cool)
{
FILE *ifile;
int i;
ifile = fopen("hello.txt", "r");
fscanf(ifile, "%[^,] %*c %[^,] %*c %d %*c %d %*c %f", first[0], last[0], &num[0], &human[0], &cool[0]);
printf("%s", first[0]);
printf("%s\n", last[0]);
printf("%d\n", num[0]);
printf("%d\n", human[0]);
printf("%f", cool[0]);
fclose(ifile);
}

Try
fscanf(ifile, "%[^,] %*c %[^,] %*c %d %*c %d %*c %f", first[0], last[0], num, human, cool);

First, with scanf family of functions, a space matches any amount of white space, including none, in the input, also don't use %*c, it is not necessary. Second, you need to specify the comma in format string to successfully scan the fields. Third, when you scanf always check its return value to make sure the expected number fields were input. Try this fix:
void read(int *lines, char first[ENTRY][FIRST], char last[ENTRY][LAST], int *num, int *human, float *cool)
{
FILE *ifile;
ifile = fopen("hello.txt", "r");
if (ifile == NULL) return;
int ret = fscanf(ifile, "%[^,], %[^,], %d, %d, %f", first[0], last[0], &num[0], &human[0], &cool[0]);
if (ret != 5) { // input file does not match the format
return;
}
printf("%s ", first[0]);
printf("%s\n", last[0]);
printf("%d\n", num[0]);
printf("%d\n", human[0]);
printf("%f\n", cool[0]);
fclose(ifile);
}

Related

Using fgets and sscanf for taking a string from a file

i have a file.txt structured this way:
author, "title", genre, price, copies_inStock
R. Tolkien, "The lords of the rings", Fantasy, 65.50, 31
i tried using fgets and sscanf
FILE *fp = NULL;
char string[100];
char title[30], author[30], genre[30];
float price;
int copies=0;
fp = fopen("text.txt", "r");
while(!feof(fp)) {
fgets(string, 100, fp);
sscanf(string, "%[^,],%[^,],%[^,],%f[^,],%d[^ ]", autore, titolo, genere, &prezzo, &copie);
}
fclose(fp);
printf("%s %s %s %.2f %d\n", author, title, genre, price, copies);
OUTPUT
R. Tolkien "The lord of the rings" fantasy 65,50 0
Why it don't access to the variable copies?
There are better ways? Thanks
The format specifiers on this line are incorrect
sscanf(string, "%[^,],%[^,],%[^,],%f[^,],%d[^ ]", autore, titolo, genere, &prezzo, &copie);
It should be
sscanf(string, "%[^,], %[^,], %[^,],%f,%d", autore, titolo, genere, &prezzo, &copie);
The additional spaces are to filter leading whitespace - it is not automatic with %[] (or with %c).
The %f and %d were a sort of mangled hybrid of what they should be. The conversion of those stops at the first character that cannot be used, without your intervention.
Side note: you really must check the result of scanf() function family: the number of successful conversions made.
"%f[^,]" is legal, yet certainly not what OP wants.
"%f" scans for a float, then "[^,]" scans for that 4 character sequence.
There are better ways?
Use " %n" to check scanning success. It records the offset of the scan.
Use width limits like 29 in %29[^,] to not overfill the char array.
Use a space before %29[^,] to consume optional leading whitespace.
Money is always tricky.
Do not use while(!feof(fp)). Check return from fgets().
char string[100];
char title[30], author[30], genre[30];
double price;
int copies;
FILE *fp = fopen("text.txt", "r");
if (fp) {
while(fgets(string, sizeof string, fp)) {
int n = 0;
sscanf(string, " %29[^,], %29[^,], %29[^,],%lf ,%d %n",
author, title, genre, &price, &copies, &n);
// If n==0, scan was incomplete
// If string[n], string has extra garbage
if (n == 0 || string[n]) {
fprintf(stderr, "Bad <%s>\n", string);
} else {
printf("%s %s %s %.2f %d\n", author, title, genre, price, copies);
// Robust code here would do additional work:
// Trim trailing string whitespace. Range checks on numeric values, etc.
}
}
fclose(fp);
}

How to read and print all the different data types together from a file in C programming

My code is given below. If run this code then even though the text file gets created correctly, for some reason junk values get printed in the console. When I include the string then only the string gets read and printed correctly in the console window and I get junk value for the rest of the variables but when I remove the string completely then I get correct values for rest of the variables. Why is this issue occurring and how to fix it ?
This is the code:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char str[] = "a string";
char str2[50];
char ch ='a';
char ch1;
int num = 12;
int num1;
float deci = 51.15;
float deci1;
FILE *new;
new = fopen("a.txt","w");
if (new == NULL) {
printf("Error! file not found! \n");
}
fprintf(new, "%s\n", str);
fprintf(new, "%c\n", ch);
fprintf(new, "%d\n", num);
fprintf(new, "%.2f\n", deci);
fclose(new);
new = fopen("a.txt", "r");
if (new == NULL) {
printf("Error! file not found! \n");
}
fscanf(new, "%[^\n]s", str2);
//str2[7]='\0';
fflush(stdin);
fscanf(new, "%c", &ch1);
fscanf(new, "%d", &num1);
fscanf(new, "%f", &deci1);
//fclose(new);
printf("string: %s character: %c integer: %d float: %f", str2, ch1, num1, deci1);
//enter code here
fclose(new);
}
If I'm not wrong the error is here:
fscanf(new, "%[^\n]s", str2);
Try to change it with:
fscanf(new, "%[^\n]\n", str2);
This does work for me.

get the values for each line in the file in c

I need to read this main.txt file:
STUDENT ID 126345
TEACHER MATH CLASS 122
And i need to get each values from this file . If this main.txt file was like this:
STUDENT ID 126345
TEACHER ID 3654432
I could do it like this:
#include <stdio.h>
int main(){
FILE *ptr_file;
int id;
char string1[100],string2[100];
ptr_file = fopen("main.txt","r");
while(fscanf(ptr_file,"%s %s %d",string1,string2,id) != EOF){
}
}
But I can't use fscanf() function because space amount between these values is not equal for each line. How can i get every value in line by line like this code ?
If every line has 3 values separated by empty spaces (or tabs), then
fscanf(ptr_file,"%s %s %d",string1,string2,&id);
is OK (and note that I used &id instead of id), because %s matches a sequence of non-white-space characters, so it
doesn't matter how many empty spaces are between the values, %s will consume
the empty spaces:
#include <stdio.h>
int main(void)
{
const char *v = "STUDENT \t ID \t 126345";
int id;
char string1[100],string2[100];
sscanf(v, "%s %s %d", string1, string2, &id);
printf("'%s' '%s' %d\n", string1, string2, id);
return 0;
}
which prints
$ ./a
'STUDENT' 'ID' 126345
In general the most robost solution would be to read line by line with fgets
and parse the line with sscanf as you have more control over when a line has a
wrong format:
char buffer[1024];
while(fgets(buffer, sizeof buffer, stdin))
{
int id;
char string1[100],string2[100];
if(sscanf(buffer, "%99s %99s %d", string1, string2, &id) != 3)
{
fprintf(stderr, "Line with wrong format\n");
break;
}
// do something with read values
}
edit
User Weather Vane points out that the line might have 3 or 4 values, then you
could do this:
char buffer[1024];
while(fgets(buffer, sizeof buffer, stdin))
{
int id;
char string1[100],string2[100],string3[100];
res = sscanf(buffer, "%99s %99s %99s %d", string1, string2, string3, &id);
if(res != 4)
{
int res = sscanf(buffer, "%99s %99s %d", string1, string2, &id);
if(res != 3)
{
fprintf(stderr, "Line with wrong format, 3 or 4 values expected\n");
break;
}
}
if(res == 3)
printf("'%s' '%s' %d\n", string1, string2, id);
else
printf("'%s' '%s' '%s' %d\n", string1, string2, string3, id);
}

How to only get numbers from a file with spaces in C

How can I get only the first 100 numbers(negative, integers, and floats) from a file that has numbers, spaces, and characters.
I was using this at the moment, but I think fgets is not the best command to use for this.
int readFile (FILE* fp)
{
char number[101] = "test";
//printf ("%s\n", number);
fgets(number, 101, fp);
//fscanf(fp, "%s", number);
printf ("%s", number);
return 0;
}
I suppose this current method could be used if spaces and unwanted characters were deleted, but currently this is not even working unless there are no spaces in the file.
here is an example of a file
44.5 -55 93942 11 text text text 333.55 999999999999 1111
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int readFile (FILE* fp){
char buff[4096];
while(NULL!=fgets(buff, sizeof(buff), fp)){
char *number, *check;
for(number=buff;NULL!=(number=strtok(number," \t\n"));number=NULL){
//separate string by strtok, isNumber check by strtod
strtod(number, &check);
if(*check=='\0'){
printf("%s\n",number);
}
}
}
return 0;
}
int main(){
readFile(stdin);
return 0;
}
You can use fgets to get the line, then use sscanf to extract the data needed:
double d1, d6;
int i2, i3, i4, i8;
long long ll7;
sscanf(input, "%lf %d %d %d %*s %*s %*s %lf %lld %d", &d1, &i2, &i3, &i4, &d6, &ll7, &i8);
Use fgets to parse the file contents in a single array of chars, then strtok() that for each number. Each number you store in a double with the coresponding function. Check this out to see how you can do that.

Reading ints from file with C

This is a very simple question, but I can't seem to find something about it in here already. I want to read two integers from a file with C. My code now is this:
int main() {
FILE *fp;
int s[80];
int t;
if((fp=fopen("numbers", "r")) == NULL) {
printf("Cannot open file.\n");
} else {
fscanf(fp, "%d%d", s, &t);
printf("%d %d\n", s[0], s[1]);
}
return 0;
}
I get the first integer from the file, but the next one is just a random number. My file is like this:
100 54
Thanks in advance
This line:
fscanf(fp, "%d%d", s, &t);
is putting one of the ints in s[0] and the other in t, but you are printing out s[0] (which is your first int) and s[1], which is uninitialized (and hence "random").
You are reading the results into s and t but printing only s ?
Your problem is on this line:
fscanf(fp, "%d%d", s, &t);
printf("%d %d\n", s[0], s[1]);
You're reading into s[0] and t, but printing s[0] and s[1]. Either of the following would work as a replacement:
fscanf(fp, "%d%d", s, &t);
printf("%d %d\n", s[0], t);
Or:
fscanf(fp, "%d%d", &s[0], &s[1]);
printf("%d %d\n", s[0], s[1]);
You never initialize it. You pass pointer to s, which means (here) the first element, as a first parameter. What do you expect to show up in s[1]?
When you are doing the fscanf, you are using one set of variables.
But when you do the printf, you are using another.
One way to get it working correctly:
#include "stdio.h"
int main()
{
FILE *fp;
int s[80];
if((fp=fopen("numbers", "r")) == NULL) {
printf("Cannot open file.\n");
} else {
fscanf(fp, "%d%d", &s[0], &s[1]);
printf("%d %d\n", s[0], s[1]);
fclose(fp);
}
return 0;
}
You need to read into &s[0] and &s[1] or print out s[0] and t.

Resources