How to only get numbers from a file with spaces in C - 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.

Related

strcmp() function only works on first iteration C

I need to make a program that outputs all lines that contain a matching string "target" and sum up the number of matches along with the total cost,
The problem is that the for loop stops at the first iteration regardless of there being a match
I have tried using strstr() instead of strcmp() and it works, but since this is a school assignment, i cant use strstr()
#include<stdio.h>
#include<string.h>
struct data{
char product[100];
char name[100];
int price;
};
int main(){
FILE *f;
f = fopen("Customers.txt", "r");
int x;
scanf("%d",&x);
struct data arr[x];
for(int i=0;i<x;i++){
fscanf(f,"%[^,], %[^,], %d",arr[i].product,arr[i].name,&arr[i].price);
}
char target[100];
int res;
int count=0;
int total=0;
scanf("%s",target);
for(int j=0;j<x;j++){
res=strcmp(arr[j].product,target);
if(res==0){
printf("%s, %s, %d",arr[j].product,arr[j].name,arr[j].price);
count++;
total = total + arr[j].price;
}
else{
continue;
}
}
printf("\nTotal Buyers: %d\n",count);
printf("Total Amount: %d\n",total);
}
File:
Gem, Alice, 2000
Gold, Bob, 3000
Gem, Cooper, 2000
Input:
3 (No. of lines in the file)
Gem (target)
Expectd output:
Alice 2000
Cooper 2000
The fscanf format string is wrong, it should be:
"%[^,], %[^,], %d\n"
Note the final \n. Without that, the \n (new line) will not be absorbed and the first item of the next string read will start with \n.
Or even better: use this format string:
" %[^,], %[^,], %d"
Note the space at the beginning. With that format string all leading and trailing whitespace, including the newline, will be absorbed.
Furthermore you absolutely need to check if fopen fails, in your case it apparently doesn't, but if the file cannot be opened for some reason, and you do not any checks, the subsequent operations on f wont end well.
So you need at least this:
...
f = fopen("Customers.txt", "r");
if (f == NULL)
{
printf("Can't open file\n");
return 1;
}
...

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 fill gaps between Text in C Language

I have a text and i want to fill it with data in C
char arr[100]="Ahmed %s salah %s is %d";
i want to add data instead of %s and %d
to be
arr="Ahmed Elsayed salah Elsenbawy is 16";
just use sprintf or snprintf.
Using char * causes buffer overflow in this case.
#include <stdio.h>
#include <string.h>
int main ()
{
char arr[100]="Ahmed %s salah %s is %d";
char temp[100];
// fill the temp buffer
sprintf(temp,arr, "Elsayed","Elsenbawy",16);
//then copy
strncpy(arr,temp,100);
printf("%s\n", arr);
return 0;
}

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.

Scanning strings and ints from file into array in 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);
}

Resources