how to return an argument using sscanf - c

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);
}

Related

Is it possible to make some loop which scans always one number and one string more than once? (Part of my homework)

so in my CS course we have to make a calculator which reads input and then calculates the result after the = sign has been read.
Input always consists of one number followed by operator.
I'm now struggling with the way of scanning the input. I want to use some loop which would always store it like:
scanf("%lf %s ", &in, c);
Note: the calculator goes one operation after other. Thus in example below the plus sign works only for 20 and 4, and only then the result takes the division sign and gets divided by 8. Then the new result gets negated by 'neg' string.
E.g.: Input: 20 + 4 / 8 neg =
Output: Result: -3
This is how I tried to solve it. My intention was to make the loop store each number into a new "box" of array, and then to store each string into the new "line" of char array. The 4 in op array is meant to set the max length of the string, because i know that the longest string that can occur is "sqrt".
I see that the '\n' in the condition of for is probably useless but can't figure out how to do it...
I'm thinking about using either for, or a while loop.
int main(){
double in[10];
char op[5][4];
for(int i=0; i<5;i++){
scanf("%lf %s ", &in[i], op[i][4]);
}
printf("%.3f %s", in[0], op[0][0]);
return 0;
}
//just a "skeleton" of the code. There's more to it, but here I submitted just the part that I'm struggling with.
For example if I run this code, I want to write a few numbers followed by operator into the input.
I expect it to print the first number and string (just to check whether the loop works).
But actually it does absolutely nothing and just gives me some large negative number as a return.
From the man page of scanf
int scanf(const char *format, ...);
as you can see first argument is of const char * type i.e you need to provide valid address.
With this
char op[5][4]; /* 5 char array, in each char array you can have 4 char's
* i.e op[row][0] to op[row][3]. There is no op[i][4]
*/
you can have
for(int i=0; i<5;i++){
scanf("%s",op[i]); /* op[i] itself address, so don't need & */
}
or
for(int i=0; i<5;i++){
for(int j=0; j<4; j++) {
scanf(" %c", &op[i][j]); /* storing char by char */
}
}
Also while printing here use %c as op[0][0] is of char type.
printf("%.3f %c", in[0], op[0][0]);
In a scanf format string, %s indicates you want to read a string, meaning it needs the address of where to put that string. You are passing op[i][4] for it, which is a char.

Pass Strings in C and fill them

So I'm trying to open a textfile, which looks something like this:
name 1.52
someothername 2.42
...and so on
Now I have to copy these strings and floats into arrays, so I can mess around with them later in my code. The thing is, I'm having trouble assigning the strings that are being found in the textfile my array that I need somewhere else in my code. The arrays have the space 100, because this is supposed to be the maximum length that I allow. I know that the problem lies here
char a[100];
and here
fscanf(fp, "%s %f\n", &a, &b);
how can I pass my empty array to the fscanf function properly so that it can be "filled"?? I keep getting errors like "warning: format specifies type 'char ' but the argument has type 'char ()[100]' [-Wformat]"
/* reads the list into the arrays name and prices and returns the number of lines (i.e.
elements) that have been read */
int read_priceList(const char* path, char names[100][100],
float price[100]){
FILE *fp = fopen(<path>, "r");
char a[100];
float b;
int i = 0;
if(fp == NULL) {
perror("Error opening File");
return -1;
}
while (!feof(fp) && i < 100) {
fscanf(fp, "%s %f\n", &a, &b);
strcpy(names[i], &a);
price [i] = b;
i++;
}
i--;
fclose(fp);
return i;
}
Also later in my code I want to pass an empty, two dimensional string array to this function, which is also a problem...
warning: incompatible pointer types passing 'char ' to parameter of type 'char ()[100]
First, I initialize them (this now happens in the main function, which calls the read_pricelist function)
char namesPricelist[100][100];
float prices[100];
and then I want to call the readPricelist function and give them these parameters.
readPricelist(<path>, &namespricelist[0][0], &prices[0]);
I'm starting to lose my mind, please help...
Among the things wrong with your function:
Regarding the warning, you're passing a char (*)[100] as a formatted target expecting a target of char *. The value you should be passing is the base address of the Nth element needing to be populated.
while (!feof(fp)...) is wrong Read this to see why.
In conjunction with the above, you never validate the fscanf did, in fact, actually work. Rather, you assume it did and blindly throw indeterminate data in to your output buffer. This is especially dangerous when the loop is first entered. If the first fscanf fails to parse anything the array a[] is left utterly indeterminate and the ensuing strcpy will be searching for a terminator to stop, but have no valid string populated in a with which to do so. If you're (un)lucky it will fine a null byte 0x00 somewhere within the first 100 chars, but such behavior is completely undefined.
You leave yourself open to a potential buffer overrun with your wide-open %s format. It should be length-limited.
You needlessly read data into temporaries. fscanf can read properly formatted data directly in your output targets; there is no need for intermediate targets and copying.
Applying all of the above can be done while significantly reducing the code-load, and is worth considering:
int read_priceList(const char* path, char names[100][100], float price[100])
{
FILE *fp = fopen(path, "r");
int i = 0;
if(fp == NULL)
{
perror("Error opening File");
return -1;
}
while (i<100 && fscanf(fp, "%99s %f", names[i], price+i) == 2)
++i;
fclose(fp);
return i;
}
There is still more that can be done, but this should get you considerably further down the road.

How to convert a values i get from a file (char) and store the values in to an array of double?

I am reading data from a file, retrieving how many columns and rows I have ( data file ), everything of so far. Now I am trying to read the values one by one and store the values in to a 2D array (double). I get the values as char using getc but when I try to use atoi or atof to convert the values from char to double i get strange values.
double ther[j][number];
char c;
int tim=0,nther=0;
FILE *fp3 = fopen("data.txt", "r");
c = getc(fp3) ;
while (c!= EOF)
{
ther[tim][nther]=atoi(&c);
printf("%lf", ther[tim][nther]);
nther++;
c = getc(fp3);
if(nther==number)
{
tim++;
nther=0;
}
tim=0;
}
fclose(fp3);
any suggestion?… (i keep searching). Sorry well i have a file data.txt and this file has rows an columns of numbers:
1 2 3 4 5
6 7 8 9 10
So i need to store the data into a 2D array: Thanks to the answers i have some ideas like: use an string, then divide all values and stored every one of them. 1st line is string-> array[0][0], array[0][1], etc. Then move to the other row and do the same.
Until now i get some numeric values but none of them are stored at the data.txt.
Firstly, it should be int c;. The getc() function has to be able to return a different value for all possible chars, and also a different value EOF (which signifies end-of-file, or stream error).
If you use char c;, then you must end up with EOF being converted to the value of a legal character, so you can't tell the difference between the two cases. In other words, your code might act like it hit EOF when in fact it just hit that particular character.
Moving on, atoi(&c) is not correct. If you read the documentation for the atoi function -- this is always a good idea when using functions -- you will find that it expects a string as input. However, &c is not a string. It is the address of a single char.
So your options are:
construct a string and pass it to atoi
don't use atoi
You didn't say what you were expecting to happen; but if you want to convert the character you read in of '3' to be the integer 3 then you can write: ther[tim][nther] = c - '0';.
However you should also have some code to handle cases when you read something that was not a number.
If you wanted to read in more than one character at a time (e.g. "31" -> 31) then the approach of using getc is not appropriate - you'll need to switch to using a function that reads multiple characters at once, such as fscanf or fgets.
Finally, you set tim to 0 every single loop iteration, so the tim++ never has any lasting effect, maybe this was an oversight.
You can read a double from a file using fscanf. An example would be:
double d;
fscanf("%f", &d);
fscanf can do much more than that so I'd recommend checking the documentation.
The method you're using gets a single character (as Matt McNabb pointed out - incorrectly). A character is 1 byte and can store the values 0-255. You're reading in text mode since you don't specify a mode with fopen (it is generally considered a good practice to explicitly ask for either binary "rb/wb" or text "rt/wt" mode). This means you read the ASCII value of a single digit.
So let's say the file contains:
7.2, 3.0, 1.0
The first call to getc(fp3) would get the character '7' which would have a value of 55 for ASCII. Obviously this is not going to give you what you're looking for.
Instead you could use:
double d[3];
fscanf("%f, %f, %f" &d[0], &d[1], &d[2]);
Which would get the three float values in the file.
#include <stdio.h>
int main(){
int j = 2;
int number = 5;
double ther[j][number];
double d;
int tim=0,nther=0;
FILE *fp3 = fopen("data.txt", "r");
while (fscanf(fp3, "%lf", &d)==1){
ther[tim][nther]=d;
printf("%g ", ther[tim][nther++]);
if(nther==number){
++tim;
nther=0;
printf("\n");
}
}
{
int r, c;
for(r=0;r<tim;++r){
for(c=0;c<number;++c){
printf("%f ", ther[r][c]);
}
printf("\n");
}
}
return 0;
}

Passing Variables through functions C

Hello im just beginning to learn C and i want to know why im getting a problem here..
i wish to pass a char pointer
char *temp;
into a function ie call to function
checkIfUniqueCourseNo(temp,k);
with a prototype
int checkIfUniqueCourseNo(char checkchar[4],int);
and a function header
int checkIfUniqueCourseNo(char checkchar[4], int k)
Im sure im doing something really stupid here but im not sure how to fix it :(
thanks in advance. ps my error is that checkchar[4] outputs a P...
Example---
temp = "123A"
checkIfUniqueCourseNo(temp,k);
int checkIfUniqueCourseNo(char checkchar[4], int k){
printf("CheckifUniqueCourse\n");
printf("Check Value = %c \n", checkchar);
return 0;
}
Output = Check Value = P
temp = "123A"
checkIfUniqueCourseNo(temp,k);
int checkIfUniqueCourseNo(char checkchar[4], int k){
printf("CheckifUniqueCourse\n");
printf("Check Value = %c \n", checkchar);
^^^^^^^^^
return 0;
}
If you're trying to print out the first character of checkchar, then you need to change this line to either
printf("Check Value = %c\n", *checkchar);
or
printf("Check Value = %c\n", checkchar[0]);
In the context of a function parameter declaration, T a[N] and T a[] are equivalent to T *a; a is declared as a pointer to T, not an array of T.
When you wrote
printf("Check Value = %c\n", checkchar);
you lied to printf; you said the argument is supposed to be of type char, but you passed a char *. Hence the bogus output.
If you want to print out the entire string "1234", then you need to change that line to
printf("Check value = %s\n", checkchar);
This time we use the %s conversion specifier to tell printf that checkchar points to a 0-terminated array of char (a.k.a. a string).
This is not at all clear. Are you assigning any value to temp? If so, what?
It would make more sense to have your prototype as:
int checkIfUniqueCourseNo(char* checkchar, int);
Since it's not at all clear where you got the 4 from.
It's been a while since I've done C, but I can see a few problems here, temp = "123A" actually requires an array for 5 characters (one of which is to include the '\0' string terminating character).
Secondly, the line printf("Check Value = %c \n", checkchar); seems to be trying to print a memory pointer as a character, change it to the following: printf("Check Value = %s \n", checkchar); and it will output each character in the array until it hits the terminating character.
There are a couple of things to look at here, you need to take a good look at the data you have, how it is represented and what you want to do with it.
Your course code appears to be a four character string, you should know that traditionally, strings in C also include an extra byte at the end with the value of zero (NUL) so that the many string functions that exist know that they have reached the end of the string.
In your case, your four digit code takes up five bytes of memory. So wont fit well passing it into your function.
If I were you, I would pass in a pointer like so:-
int checkIfUniqueCourseNo(char* coursecode, int k ) {
int rv = -1;
if ( coursecode == NULL ) return rv;
//...
I have no idea what K is for, do you?
Once you have your sequence of bytes inside your function you can save yourself alot of hastle later by doing some simple bounds checking on the data like so:
//...
if ( strlen(coursecode) > 4 ){
fprintf(stderr,"course code too long\n");
return rv;
}
if ( strlen(coursecode) < 4 ){
fprintf(stderr,"course code too short\n");
return rv;
}
//...
You can be sure you have a 4 character string now..

Program doesnt want to read file

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.

Resources