Program doesnt want to read file - c

this is my struct
typedef struct {
char mmsi[10];
char name[20];
double latitude;
double longitude;
int course;
double speed;
}Vessel;
this is my function which doesnt want to work
void searchByLatLong(double latitude, double longitude){
FILE * file;
struct dirent *drnt;
DIR * dir = opendir("./text");
char *path = (char *)malloc(19);
Vessel *vessel = (Vessel *)malloc(sizeof(Vessel));
while((drnt = readdir(dir)) != NULL) {
if(strcmp(drnt->d_name,".") && strcmp(drnt->d_name,"..")) {
strcpy(path,"text/");
strcat(path,drnt->d_name);
file=fopen(path, "r");
fscanf(file," %s %[a-zA-Z0-9 ]19s %lf %lf %d %lf", &vessel->mmsi,&vessel->name,&vessel->latitude,&vessel->longitude,&vessel->course,&vessel->speed);
// if (mmsi+".txt" == drnt->d_name){
printf("%s\n%s\n%lf\n%lf\n%d\n%lf\n\n",vessel->mmsi,vessel->name,vessel->latitude,vessel->longitude,vessel->course,vessel->speed);
//}
fclose(file);
}
seekdir(dir, telldir(dir));
// if(this->mmsi == mmsi){
// printVessel();
// }
}
closedir(dir);
}
When i try to load txt file it loads only two first strings then after it theres some rubbish from memory. Loading the data to another variables changes nothing ;/
This is a sample txt file which should be loaded:
3
RMS Titanic
22.222
33.333
4
5.9

The problem is with your format string. The correct format string is:
" %s %19[a-zA-Z0-9 ] %lf %lf %d %lf"
The field width goes before the conversion specifier. Also, the [...] sequence is a conversion specifier, just like 's'. The problem you're seeing is that fscanf() processes the '3' because it matches the first %s. Then it processes the 'RMS Titanic' because it matches %[a-zA-Z0-9 ] but then processing stops because there is no '19s' in the input. At this point the remaining arguments are uninitialized.
You should check the return value from fscanf(). It will tell you how many conversions were actually performed.

Thanks for posting an interesting question; I learned about fscanf() and the [] notation it accepts.
The [] notation specifies that a string is being read, therefore, the s you have appended to it is considered a literal character that should match. Similarly, the width-specifier you have provided, 19 should appear prior to the [].
Your current code would start working if you had a ship named, e.g., "RMS Titanic19s".
Change your fscanf to:
fscanf(file," %s %19[a-zA-Z0-9 ] %lf %lf %d %lf",
vessel->mmsi,vessel->name,&vessel->latitude,
&vessel->longitude,&vessel->course,&vessel->speed);
and your code will start working.
Notice I fixed some compile warnings by dropping the superfluous & from the char [] members mmsi and name -- these already point to the buffers you wish to fill. You don't need & in front of them. A pedagogical alternative form is &vessel->mmsi[0] -- the address of the first character of mmsi.

Related

How to read comma delimited data from txt file to struct

I have text file which have the following content
inputfile
I have used a function to get data from the input file which is comma delimited.
I want to read data from it and want to remove comma and store the data to Struct Resistor_struct.
I have tried the following code.
'''
#include<stdio.h>
//functions header
int blown_ressistors();
struct resistor_struct
{
char ID_LEN[5];
char id;
float max_poewr;
int resistance;
};
struct resistor_struct rs[100];
int blown_ressistors()
{
FILE *fp = fopen("input.txt", "r");
int i = 0;
if(fp!=NULL)
{
while(fscanf(fp, "%s[^,], %d[^,], %f[^,]",rs[i].ID_LEN,rs[i].resistance, rs[i].max_poewr)!=EOF)
{
printf("%s\t", rs[i].ID_LEN);
printf("%d\t", rs[i].resistance);
printf("%d\t\n", rs[i].max_poewr);
i++;
}
}
else
{
perror("Input.txt: ");
}
'''
output
output image
You don't want to compare the value returned from scanf with EOF.
In your case, the format string is such that scanf can never match more than 1 conversion specifier, since %s[^,], is trying to match the literal input string [^,], but the [ is guaranteed not to match since the first character that scanf will stop consuming for the %s is whitespace. And [ is not whitespace. Try something like:
while(fscanf(fp, " %4[^,], %d, %f", rs[i].ID_LEN, &rs[i].resistance, &rs[i].max_poewr) == 3 )
but note that this will behave oddly on whitespace in the first column. You might want to try: " %4[^, \t\n] , %d, %f", but quite frankly the better solution is to stop using scanf. Even with something trivial like this, your behavior will be undefined on an input like foo, 9999...9999 (where the 2nd column is any value that exceeds the capacity of an int). Just stop using scanf. Read the data and parse it with strtol and strtod.

How to scan strings from a text file with delimiter and then display it?

So i tried to make a program that will scan strings from a text file and then display it using loop. But, somehow my program cannot work and it is display weird symbols.. i am new to text file and i would appreciate a lot if someone can explain to me what is wrong with my code.
My code :
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fPtr;
fPtr = fopen("alumni.txt", "r");
if (fPtr == NULL) {
printf("There is a error opening the file.");
exit(-1);
}
char name[20], design[50], category[20], location[20];
while (fscanf(fPtr, "%s:%[^\n]:%[^\n]:%[^\n]", &name, &design, &category, &location) != EOF) {
printf("Name : %s\n", name);
printf("Designation : %s\n", design);
printf("Category : %s\n", category);
printf("Location : %s\n", location);
}
}
and this is my text file,
Shanie:Programmer:Full Time:Kuala Lumpur
Andy:Sales Agent:Part Time:Johor Bahru
Elaine:Database Administrator Full Time Melaka
Stephanie:MIS manager:Full Time:Penang
You have two problems: The first is that %s will read space delimited "words", it won't stop at the :. The second problem is that the format %[^\n] reads all until newline.
So you need a scanset format for the first name as well as tell it to read until the next :, which is done with the format %[^:].
So please change to:
while (fscanf(fPtr, " %19[^:]:%49[^:]:%19[^:]:%19[^\n]", name, design, category, location) == 4) {
...
}
Please note a couple of other changes I made to your call and loop condition: First of all, I have added length specifiers to the formats, so fscanf will not write out of bounds of your arrays.
Secondly both the %s and %[] formats expects a char * argument, while you provided a pointer to arrays (&name will be of type char (*)[20] not char *). Arrays naturally decay to pointers to their first element, so e.g. name will decay to &name[0] which will be of the correct type char *.
Thirdly I changed the comparison to compare against 4, which is what fscanf will return if it successfully parsed the input.
Lastly I added a space before the first format, to skip any leading space (like the newline from the previous line).
To be sure to be able to continue even in the case of malformed input, I recommend you read full lines instead (using e.g. fgets), and then possibly use sscanf to parse each line.

Storing String Inside a String?

My problem is when I try to save the string (series[0]) Inside (c[0])
and I display it, it always ignore the last digit.
For Example the value of (series[0]) = "1-620"
So I save this value inside (c[0])
and ask the program to display (c[0]), it displays "1-62" and ignores the last digit which is "0". How can I solve this?
This is my code:
#include <stdio.h>
int main(void)
{
int price[20],i=0,comic,j=0;
char name,id,book[20],els[20],*series[20],*c[20];
FILE *rent= fopen("read.txt","r");
while(!feof(rent))
{
fscanf(rent,"%s%s%s%d",&book[i],&els[i],&series[i],&price[i]);
printf("1.%s %s %s %d",&book[i],&els[i],&series[i],price[i]);
i++;
}
c[0]=series[0];
printf("\n%s",&c[0]);
return 0;
}
The use of fscanf and printf is wrong :
fscanf(rent,"%s%s%s%d",&book[i],&els[i],&series[i],&price[i]);
Should be:
fscanf(rent,"%c%c%s%d",&book[i],&els[i],series[i],&price[i]);
You have used the reference operator on a char pointer when scanf expecting a char pointer, also you read a string to book and else instead of one character.
printf("1.%s %s %s %d",&book[i],&els[i],&series[i],price[i]);
Should be:
printf("1.%c %c %s %d",book[i],els[i],series[i],price[i]);
And:
printf("\n%s",&c[0]);
Should be:
printf("\n%s",c[0]);
c is an array of char * so c[i] can point to a string and that is what you want to send to printf function.
*Keep in mind that you have to allocate (using malloc) a place in memory for all the strings you read before sending them to scanf:
e.g:
c[0] = (char*)malloc(sizeof(char)*lengthOfString+1);
and only after this you can read characters in to it.
or you can use a fixed size double character array:
c[10][20];
Now c is an array of 20 strings that can be up to 9 characters long.
Amongst other problems, at the end you have:
printf("\n%s",&c[0]);
There are multiple problems there. The serious one is that c[0] is a char *, so you're passing the address of a char * — a char ** — to printf() but the %s format expects a char *. The minor problem is that you should terminate lines of output with newline.
In general, you have a mess with your memory allocation. You haven't allocated space for char *series[20] pointers to point at, so you get undefined behaviour when you use it.
You need to make sure you've allocated enough space to store the data, and it is fairly clear that you have not done that. One minor difficulty is working out what the data looks like, but it seems to be a series of lines each with 3 words and 1 number. This code does that job a bit more reliably:
#include <stdio.h>
int main(void)
{
int price[20];
int i;
char book[20][32];
char els[20][32];
char series[20][20];
const char filename[] = "read.txt";
FILE *rent = fopen(filename, "r");
if (rent == 0)
{
fprintf(stderr, "Failed to open file '%s' for reading\n", filename);
return 1;
}
for (i = 0; i < 20; i++)
{
if (fscanf(rent, "%31s%31s%19s%d", book[i], els[i], series[i], &price[i]) != 4)
break;
printf("%d. %s %s %s %d\n", i, book[i], els[i], series[i], price[i]);
}
printf("%d titles read\n", i);
fclose(rent);
return 0;
}
There are endless ways this could be tweaked, but as written, it ensures no overflow of the buffers (by the counting loop and input conversion specifications including the length), detects when there is an I/O problem or EOF, and prints data with newlines at the end of the line. It checks and reports if it fails to open the file (including the name of the file — very important when the name isn't hard-coded and a good idea even when it is), and closes the file before exiting.
Since you didn't provide any data, I created some random data:
Tixrpsywuqpgdyc Yeiasuldknhxkghfpgvl 1-967 8944
Guxmuvtadlggwjvpwqpu Sosnaqwvrbvud 1-595 3536
Supdaltswctxrbaodmerben Oedxjwnwxlcvpwgwfiopmpavseirb 1-220 9698
Hujpaffaocnr Teagmuethvinxxvs 1-917 9742
Daojgyzfjwzvqjrpgp Vigudvipdlbjkqjm 1-424 4206
Sebuhzgsqpyidpquzjxswbccqbruqf Vuhssjvcjjylcevcisdzedkzlp 1-581 3451
Doeraxdmyqcbbzyp Litbetmttcgfldbhqqfdxqi 1-221 2485
Raqqctfdlhrmhtzusntvgbvotpk Iowdcqlwgljwlfvwhfmw 1-367 3505
Kooqkvabwemxoocjfaa Hicgkztiqvqdjjx 1-466 435
Lowywyzzkkrazfyjuggidsqfvzzqb Qiginniroivqymgseushahzlrywe 1-704 5514
The output from the code above on that data is:
0. Tixrpsywuqpgdyc Yeiasuldknhxkghfpgvl 1-967 8944
1. Guxmuvtadlggwjvpwqpu Sosnaqwvrbvud 1-595 3536
2. Supdaltswctxrbaodmerben Oedxjwnwxlcvpwgwfiopmpavseirb 1-220 9698
3. Hujpaffaocnr Teagmuethvinxxvs 1-917 9742
4. Daojgyzfjwzvqjrpgp Vigudvipdlbjkqjm 1-424 4206
5. Sebuhzgsqpyidpquzjxswbccqbruqf Vuhssjvcjjylcevcisdzedkzlp 1-581 3451
6. Doeraxdmyqcbbzyp Litbetmttcgfldbhqqfdxqi 1-221 2485
7. Raqqctfdlhrmhtzusntvgbvotpk Iowdcqlwgljwlfvwhfmw 1-367 3505
8. Kooqkvabwemxoocjfaa Hicgkztiqvqdjjx 1-466 435
9. Lowywyzzkkrazfyjuggidsqfvzzqb Qiginniroivqymgseushahzlrywe 1-704 5514
10 titles read

Scanning values from file using fscanf

Hey I need to read the data from file and print it(i have to use fscanf). My code only works for first value when I add more it's not working.
Here is my code
char name[5]; //this value is fixed size
char isWorking;
double latitude; //the length may vary
double longitude; //the length may vary
while(fscanf(fp2,"%s %c %lf %lf",name,isWorking,latitude,longitude) == 4) {
printf("\n%s %c %lf %lf",id,type,latitude,longitude);
i++;
}
my file looks like that
Bob1 Y 122.232323 -9.323232
Bob2 N 9.0001 -9.001
It doesn't print anything except when I remove other values and try to read only name

how to return an argument using sscanf

I am reading a line at the time from a text file that has this format: 2.34 4.68 5.98. I want to store these float values in an array so that I can make use of each argument later on but once I use sscanf and try to print the argument I get 0. Any idea what’s the problem is. Thank you.
char* line[2000];
char* State[2000];
sscanf(line[12],"%f", &State[12]).
printf("\n state 1: %2.3f", &State[0]);// this suppose to print 2.34 but it prints 0
You can scan them all at once:
float state[3];
if(sscanf(line[12], "%f %f %f", &state[0],
&state[1], &state[2]) != 3) {
...
} else
printf("\n state1: %f, state2: %f, state3:%f",
state[0], state[1], state[2]);
}
At the moment you're scanning into one place (State[12]) and expecting the value to be stored somewhere else (State[0]).
A few more mistakes you're making:
Storing into a char * array when you should be storing into a float array
Using pointers with printf when it expects to take in actual values
Using . to end a statement...? Not sure if this is a typo
sscanf(line[12],"%f", &State[12]).
OK. You win a prize for having a new (at least to me) way of misunderstanding how arrays work in c.
You almost certainly don't want the [12] in either case here.
The name of an array (either line or State) can be automatically converted to a char* which points at the beginning of the array. So
sscanf(line,"%f", ...);
scans the contents of line. How ever line[12] is a the single character at the position (*line)+12.
You need a float to put the result in or you need to change your format specifier from %f to %s. You should never but the results of a %f into a char*.
You are puting the number in 12th case of your table ; that's strange.
Is it not easier to use fscanf directly ?
FILE *fp = fopen(fileName);
float tabNumbers[3] = {0};
if (fp) {
for (int i = 0; i < 3; ++i)
fscanf(fp, "%f", &tabNumbers[i]);
fclose(fp);
}

Resources