error: invalid operands to binary + (have ‘float’ and ‘float *’) - c

I'm trying to make a program in which I can read a file with animals weight and calculate the weight average. I got this error while trying to compile. Does anyone knows why?
funciones.c
#include "header.h"
float count_animals(FILE *file){
float total_animals = 0;
char word[20];
while (fscanf(file, "%s", word) == 1){
total_animals++;
}
return total_animals;
}
float sum_weight_animals(FILE *file){
float sum_weight = 0;
float weight[20];
while (fscanf(file, "%f", weight) == 1){
sum_weight += weight;
}
return sum_weight;
}
header.h
#include <stdio.h>
#define MAXWORD 80
float count_animals(FILE *file);
float sum_weight_animals(FILE *file);
Just in case here's the main.c
Now I have the problem that it's not adding up the sum_weight value in sum_weight_animals function.
#include "header.h"
int main(){
char WORD[MAXWORD];
char file_name[MAXWORD];
FILE *fileptr;
printf("Please, enter a file name: ");
scanf("%s", file_name);
printf("Reading file %s...\n", file_name);
fileptr = fopen(file_name, "r");
if(fileptr == NULL){
fprintf(stderr, "ERROR: The file '%s' doesn't exists\n", file_name);
return 1;
}
float total_animals = count_animals(fileptr);
if (total_animals > 0){
printf("There're %.2f animals.\n", total_animals);
}
else{
fprintf(stderr, "WARNING: File not found or it's empty\n");
}
float total_sum = sum_weight_animals(fileptr);
if (total_sum > 0){
printf("The sum of all animal's weight is %.2f [kg].\n", total_sum);
}
else{
fprintf(stderr,"WARNING: File not found or it's empty\n");
}
fclose(fileptr);
return 0;
}
When ex Makefile, it compiles correctly and the first function works fine, but the second one doesn't and it gives me the WARNING: File not found or it's empty\n that I put on main.c

Replace
float weight[20];
with
float weight;
and replace
fscanf(file, "%f", weight)
with
fscanf(file, "%f", &weight)
Explanation:
sum_weight += weight;
is basically equivalent to
sum_weight = sum_weight + weight;
Let's look at the right-hand side, sum_weight + weight.
sum_weight is a float.
weight is an array of 20 float elements.
What does it mean to add a float and an array together? Nothing, that's what. This makes no sense.
You assigned a value to weight[0], and this is the value you want to add. Not weight.
But why is weight an array in the first place? As the name implies, it's only used to store one weight. You only ever assign to weight[0]. So it makes no sense to use an array.

Related

For loop doesn`t work when add [^\n] to a scanf_s

This program should ask you to add member (people) to a struct and print them on a file but after the first for loop just stop working and jump over the name part. I just found that thing that allow you to add space to a string, tried it but no success...
I tried to remove it and it work without any problem so the [^\n] make something go wrong.
What is wrong ?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Staff {
char Surname[100];
char Name[100];
int age;
char spec[100];
int id;
} person;
void write();
void leggi();
void trova();
int main() {
write();
}
void write() {
int i = 0;
int n = 1;
int r;
FILE *fp;
fopen_s(&fp, "index.txt", "w+");
if (fp == NULL) {
printf("Failed to open file\n");
exit(1);
}
fprintf(fp, "%d\n", i);
for (i = 0; i < n; i++) {
printf("Surame:\n");
scanf_s("%[^\n]s", person.Surname, 100);
fprintf(fp, "%s\t\t", person.Surname);
//loop just get over the name part
printf("Name:\n"); //after the first loop
scanf_s("%s", person.Name, 100);
fprintf(fp, "%s\t", person.Name);
printf("Age:\n");
scanf_s("%d", &person.age);
fprintf(fp, "%d\t", person.age);
printf("Specialization\n");
scanf_s("%s", person.spec, 100);
fprintf(fp, "%s\n", person.spec);
printf("Want to enter another? 1=yes 0=no...\n");
scanf_s("%d", &r);
if (r == 1)
n = n + 1;
}
rewind(fp);
fprintf(fp, "%d\n", i);
fclose(fp);
}
There are multiple problems in your code:
you use the so called secure functions fopen_s, scanf_s etc, but you do not check the return values to detect invalid input. You should instead use standard functions, pass the appropriate arguments and check the return values.
using scanf_s is actually non portable: the scanf_s function defined in Annex K of the C Standard requires the length argument after the pointer to have size_t type, whereas the function with the same name in the Microsoft library uses type UINT, which has a different representation on 64-bit versions of their Windows OS. A classical case of the Embrace, enhance and extinguish strategy. In Standard C, one should write: scanf_s("%s", person.Name, (size_t)100) or better:
scanf_s("%s", person.Name, sizeof person.Name)
there is no need to open the output file for update with "w+", just use "w".
you rewind the stream pointer back to the beginning of file and overwrite the number of entries at the start of the file. This works as long as you have less than 10 entries, but beyond that, the number has more digits so some characters in the file will be corrupted. You could use a format with padding such as "%6d\n" which would allow for up to 1 million records without risks.
"%[^\n]s" is not a correct scanf format: you should just write "%[^\n]" or better " %99[^\n]" to skip initial white space and limit the input to 99 characters.
Here is a modified version:
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Staff {
char Surname[100];
char Name[100];
int age;
char spec[100];
int id;
};
void write(void);
void leggi(void);
void trova(void);
int main() {
write();
}
int flush_input(void) {
int c;
while ((c = getchar()) != EOF && c != '\n')
continue;
return c;
}
void write(void) {
int n = 0;
int r;
FILE *fp = fopen("index.txt", "w");
if (fp == NULL) {
fprintf("Failed to open file index.txt: %s\n",
strerror(errno));
exit(1);
}
fprintf(fp, "%6d\n", n);
for (;;) {
struct Staff person = { 0 };
printf("Surname:\n");
if (scanf(" %99[^\n]", person.Surname) != 1)
break;
flush_input();
fprintf(fp, "%s\t\t", person.Surname);
//loop just get over the name part
printf("Name:\n"); //after the first loop
scanf(" %99[^\n]", person.Name);
flush_input();
fprintf(fp, "%s\t", person.Name);
printf("Age:\n");
scanf("%d", &person.age);
flush_input();
fprintf(fp, "%d\t", person.age);
printf("Specialization\n");
scanf(" %99[^\n]", person.spec, 100);
flush_input();
fprintf(fp, "%s\n", person.spec);
n++;
printf("Want to enter another? 1=yes 0=no...\n");
if (scanf("%d", &r) != 1 || r != 1) {
flush_input();
break;
}
flush_input();
}
rewind(fp);
// update the entry count on 6 characters
fprintf(fp, "%6d\n", n);
fclose(fp);
}
Change the call of scanf below for entering strings by inserting a space in the beginning of the format string. For example instead of this call
scanf_s("%[^\n]s", person.Surname, 100);
(where the letter s must be removed from the format string) write
scanf_s(" %[^\n]", person.Surname, ( rsize_t )100);
^^^^^^^^
This allows to skip leading white space characters in the input buffer.
Pay attention to that changing the condition or the for loop the was as you are doing
for (i = 0; i < n; i++) {
//...
if (r == 1)
n = n + 1;
}
makes the code unclear. Instead of the for loop you could use do-while loop.

Why data read from the random access file and print twice of last line of the table on screen ? (Got picture) [duplicate]

This question already has answers here:
Why is “while( !feof(file) )” always wrong?
(5 answers)
Closed last year.
can I know why the last line of the table below will print twice? Everything is executed well and just has the problem stated above.
The type of file used is a random access file and data written into a binary file named toyota.txt.
Anyone can teach me what is the problem there? Thank you so much!
The code is shown below:
/*program 1 write the data into file toyota.txt*/
#include<stdio.h>
struct vehicledata{
char vnum[100];
int cnum;
float f50;
float f100;
float f200;
float f400;
float f800;
};
int main()
{
FILE *fptr;
struct vehicledata toyota;
if((fptr = fopen("toyota.txt","wb")) == NULL)
{
printf("Error! File fail opened!");
}
else
{
printf("This program can create a text file named toyota.txt \n");
printf("and save the value of car noise level(dB) with\ndifferent frequency and vehicle numbers into file\n\n");
printf("======================================================================\n");
printf("Enter car number(1 to 10, enter 0 to end input)\n");
printf("? ");
scanf("%d", &toyota.cnum);
while (toyota.cnum != 0)
{
printf("\nEnter Vehicle number\n");
printf("? ");
scanf("%s", toyota.vnum);
printf("Enter car noise level(dB) at 50Hz, 100Hz, 200Hz, 400Hz and 800Hz\n");
printf("? ");
scanf("%f %f %f %f %f", &toyota.f50, &toyota.f100, &toyota.f200, &toyota.f400, &toyota.f800);
fseek(fptr, (toyota.cnum - 1) * sizeof(struct vehicledata), SEEK_SET);
fwrite(&toyota, sizeof(struct vehicledata), 1, fptr);
printf("\n======================================================================\n");
printf("\nEnter car number (1 to 100, 0 to end input) \n");
printf("? ");
scanf("%d", &toyota.cnum);
}
}
fclose(fptr);
return 0;
}
/*program 2 reads the data from the file toyota.txt and find
the car that emanates the minimum noise at 200Hz*/
#include <stdio.h>
#include <stdlib.h>
struct vehicledata{
char vnum[100];
int cnum;
float f50;
float f100;
float f200;
float f400;
float f800;
};
char name[10];
float min;
int i, m;
int main()
{
FILE *fptr;
struct vehicledata toyota;
if ((fptr = fopen("toyota.txt","rb")) == NULL)//open and read data in the file
{
printf("Error! File fail opened!");
}
else
{
printf("This program can read and display the data from the toyota.txt\n and find car that have minimum noise in 200Hz\n\n");
printf("\nThe information in the toyota.txt are shown at below:\n");
printf("\n\t\t\t\tCar Noise Level(dB)\t\t\t");
printf("\n=======================================================================\n");
printf("%s\t\t%s\t%s\t%s\t%s\t%s\t\n","Vehicle Number","50Hz","100Hz","200Hz","400Hz","800Hz");
printf("=======================================================================\n");
char name[10];
float min=100;
while(!feof(fptr))
{
fread(&toyota, sizeof(struct vehicledata), 1, fptr);
if(toyota.f200 < min)
{
min=toyota.f200;
for(int i=0 ; i<10 ; i++)
{
name[i]=toyota.vnum[i];
}
}
if(toyota.cnum != 0)
{
printf("%s\t\t\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n", toyota.vnum, toyota.f50, toyota.f100, toyota.f200, toyota.f400, toyota.f800);
}
}
printf("=======================================================================\n");
printf("\n\n+++++++++++++++++++++++++++++++++Result+++++++++++++++++++++++++++++++++\n");
printf("\nVehicle number of car with minimum noise in 200Hz is %s at %.2f dB\n", name, min);
}
fclose(fptr);
return 0;
}
The problem is in program 2. In the section below you assume that your fread will be OK since you are not att the EOF. This is not the case.
while(!feof(fptr))
{
fread(&toyota, sizeof(struct vehicledata), 1, fptr);
What happens is that you check for EOF in your loop and being at the very end of the file the last fread is indeed read one more time but fails. Since you don't check for it and fread did not have toyota overwritten (since the read failed) you have a duplicate that you print out. After that you now check for EOF and leave the loop.
A better loop would look like this:
while (fread(&toyota, sizeof(struct vehicledata), 1, fptr)) {
Since the documentation for fread states, "If an error occurs, or the end of the file is reached, the return value is a short item count (or zero).", in your case we are not really checking for errors and we are at EOF.
But if you want to figure out that the loop ended due to EOF or an error then "callers must use feof(3) and ferror(3) to determine which occurred.".

Calculating Average from array and seperate structure

Trying to make a program that prints data entered into a file.
Everything is working all and good apart from the Calculating Average for marks entered.
I can't seem to figure out how to do it, even though it should be simple I just cant get my head around it.
The error I am currently getting is:
"temp->mark = temp->mark + studentArray[j];" (Invlalid operands to
binary + (have 'float' and 'char *').
Much appreciated if someone could help me. I have tried the following
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
struct student{
char name[30];
int id;
float mark;
};
int count = 0;
void student_update(char *stuadd);
void display(char *stuadd);
void main(int argc, char *studentArray[100])
{
int choice;
while(1)
{
printf("Welcome to Student Archives\n\n");
printf("1. Display Students' Details\n");
printf("2. Calculate average of all students’ marks \n");
printf("3. Add new student to the record \n");
printf("4. Quit Program\n");
scanf("%d",&choice);
switch(choice)
{
case 1:display(studentArray[100]);
break;
case 2:
break;
case 3:
student_update(studentArray[100]);
break;
case 4: printf("Program Terminated.\n");
exit(0);
default: printf("Wrong Choice. Enter again\n");
break;
}
}
}
void display(char *stuadd)
{
FILE *fptr;
char ch;
int rec = count;
fptr = fopen("stuadd.txt", "r");
struct student *temp = (struct student *)malloc(sizeof(struct student));
if (fptr == NULL)
printf("File does not exist.");
else
{
while (rec)
{
fread(temp->name, 50, 1, fptr);
printf(" %s\n", temp->name);
fread(&temp->id, sizeof(int), 1, fptr);
printf("%d", temp->id);
fread(&temp->mark, sizeof(int), 1, fptr);
printf("%.2f", temp->mark);
rec--;
}
}
fclose(fptr);
free(temp);
free(temp->name);
}
void calculateAverage(char *studentArray[100])
{
struct student *temp = (struct student *)malloc(sizeof(struct student));
int j;
float avg;
temp->mark = avg = 0;
for(j = 0; j < 100; j++)
{
temp->mark = temp->mark + studentArray[j];
}
avg = (float)temp->mark / j;
printf("Average of students' total marks are: %.2f",avg);
}
void student_update(char *stuadd)
{
FILE *fptr;
fptr = fopen("stuadd.txt", "a+");
struct student *temp = (struct student *)malloc(sizeof(struct student));
if (fptr == NULL)
printf("\nError.");
else
{
printf("\nEnter the students' name\n");
scanf(" %[^\n]s", temp->name);
printf("Enter the students' ID\n");
scanf("%d", &temp->id);
printf("Enter the students' mark\n");
scanf("%f", &temp->mark);
fprintf(fptr, "%s %d %.2f", temp->name, temp->id, temp->mark);
count++;
}
fclose(fptr);
free(temp);
free(temp->name);
}
The posted code does not compile!
under ubuntu linux, using:
gcc -ggdb -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled.c" (in directory: /home/richard/Documents/forum)
the compiler outputs the following:
untitled.c:16:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
void main(int argc, char *studentArray[100])
^~~~
untitled.c: In function ‘main’:
untitled.c:16:15: warning: unused parameter ‘argc’ [-Wunused-parameter]
void main(int argc, char *studentArray[100])
^~~~
untitled.c: In function ‘display’:
untitled.c:48:10: warning: unused variable ‘ch’ [-Wunused-variable]
char ch;
^~
untitled.c:45:20: warning: unused parameter ‘stuadd’ [-Wunused-parameter]
void display(char *stuadd)
^~~~~~
untitled.c: In function ‘calculateAverage’:
untitled.c:83:33: error: invalid operands to binary + (have ‘float’ and ‘char *’)
temp->mark = temp->mark + studentArray[j];
~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~
untitled.c:86:29: warning: conversion to ‘float’ from ‘int’ may alter its value [-Wconversion]
avg = (float)temp->mark / j;
^
untitled.c: In function ‘student_update’:
untitled.c:91:27: warning: unused parameter ‘stuadd’ [-Wunused-parameter]
void student_update(char *stuadd)
^~~~~~
Compilation failed.
There are some other problems, like:
free(temp);
free(temp->name);
That is accessing a pointer into allocated memory after the allocated memory has been passed to free() The result is indefined behavior. Suggest:
free(temp->name);
free(temp);
Regarding the following statements
FILE *fptr;
fptr = fopen("stuadd.txt", "a+");
struct student *temp = (struct student *)malloc(sizeof(struct student));
if (fptr == NULL)
printf("\nError.");
Always check for an error indication immediately after the call to the C library function.
output error messages to stderr, not stdout
When the error indication is from a C library function, then immediately call perror(); to output both your error message AND the text reason the system thinks the error occurred, all to stderr
when calling any of the heap allocation functions: malloc calloc realloc, 1) the returned type is void* which can be assigned to any pointer. Casting just clutters the code, making it more difficult to understand, debug, etc. 2) always check (!=NULL) the returned value to assure the operation was successful. Suggest:
FILE *fptr;
fptr = fopen("stuadd.txt", "a+");
if ( !fptr )
{
perror("fopen failed");
exit( EXIT_FAILURE );
}
// implied else, fopen successful
struct student *temp = malloc(sizeof(struct student));
if( !temp )
{
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
regarding:
scanf(" %[^\n]s", temp->name);
That call to scanf() is nonsense. Since the input format specifier %[^\n] will stop input from stdin when it encounters a newline sequence, there is no possible way for the next char in stdin to be a s When calling any of the scanf() family of functions, always check the returned value to assure the operation was successful. when using the input format specifiers %s and/or %[...] always include a MAX CHARACTERS modifier that is one less than the length of the input buffer to avoid any possibility of buffer overflow (and the resulting undefined behavior). Suggest removing the trailing s in the format string and check the return value and limiting the total number of characters that can be input, as in:
if( scanf(" %29[^\n]", temp->name) != 1 )
{
fprintf( stderr, "scanf failed to input the student name\n" );
exit( EXIT_FAILURE );
}
regarding:
for(j = 0; j < 100; j++)
{
temp->mark = temp->mark + studentArray[j];
}
there is no array studentArray[] so this will never produce the desired results.
regarding the error message:
avg = (float)temp->mark / j;
untitled.c:83:33: error: invalid operands to binary + (have ‘float’ and ‘char *’)
temp->mark = temp->mark + studentArray[j];
of course a 'float` value cannot be added to a pointer to a char array. What were you actually trying to accomplish?
All the above is just the 'tip of the iceburg' of problems in the posted code. Suggest using a debugger and stepping through your code to determine the many problems

Search returning only the first result in structure C

I am trying to read a file and print the records where the jumper has exceeded the distance provided by the user, but the search only returns the first line in the file and that's it, i know there is something wrong in the logic but i cant put my finger on it.
#include<stdio.h>
#include<string.h>
typedef struct {
char fname[30];
char lname[30];
char nationality [30];
double distance;
}Player;
void print(Player p) {
printf("%s %s %s %f \n", p.fname, p.lname, p.nationality, p.distance);
}
int search(double distance, Player allPlayers[], int max){
int i=0;
for(i=0; i<max; i++){
if(distance > allPlayers[i].distance){
return i;
}
return -1;
}
}
void load (char filename[10], Player players[]){
char tempfName [30];
char templName [30];
char tempNationality [30];
double tmpdistance;
FILE * input=fopen(filename,"r+");
if(input==NULL)
printf("Error found in opening the file\n");
else {
printf("The data are loaded successfully.\n");
int counter = 0;
while(!feof(input)){
strcpy(tempfName," ");
fscanf(input, "%s %s %s %f",tempfName, templName, tempNationality, &tmpdistance);
if(strcmp(tempfName, " ") !=0){
strcpy(players[counter].fname, tempfName);
strcpy(players[counter].lname, templName);
strcpy(players[counter].nationality, tempNationality);
players[counter].distance = tmpdistance;
counter++;
}
}
fclose(input);
}
}
int main (int argc, char *argv[]){
Player players2[40];
char myFileName[10] ="jump.txt";
load(myFileName, players2);
double tmpdistance;
printf("Please enter the distance threshold: ");
scanf("%lf", &tmpdistance);
printf("The jumpers exceeded 8.10 m are: \n");
int index = -1;
index = search(tmpdistance,players2,40);
if(index!=-1)
print(players2[index]);
else
printf("NOT Found! \n");
return 0;
}
some sample data from the file I'm trying to read :
Arsen Sargsyan Armenia 7.62
Boleslav Skhirtladze Georgia 7.26
Christian Reif Germany 7.92
Christopher Tomlinson Great_Britain 8.06
In your search() function:
if(distance > allPlayers[i].distance){
return i;
}
This will return the first jumper whose performance is less than the distance provided.
If you replace it with:
if(allPlayers[i].distance > distance){
return i;
}
It will return the first jumper whose performance is greater than the distance provided, which is what you want.
Also:
Don't loop over feof() to read a file: Why is “while ( !feof (file) )” always wrong?
You're printing "The data are loaded successfully" when you haven't loaded the data yet - you've just opened the file
You don't need the arguments to main()
You don't need to initialise index to -1 as you assign it in the next line
You don't need to specify the size of myFileName as the compiler can work it out

Reading from a text file and plotting using GNU libplot

I've made a program that reads from a file, and alphabetically sorts names contained within the file. The file contains planet names, mass, size, color, primary body, positions x,y,z and velocity x,y,z. I'm now trying to plot each planet using this file, but I'm unsure how to go about doing that. I'm using GNU libplot to plot the planets. I'm thinking that I need to use a loop and fscanfs to get the x and y coordinates (can omit Z for now) to plot each planet.
Here's my current code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAMES 20
struct planets{ //sets up initial characters and doubles to place into body.
char primaryBody[NAMES];
char name[NAMES];
char color[NAMES];
double mass;
double size;
double posx, posy, posz;
double velx, vely, velz;
};
struct planets body[100];
int readData(FILE* fd){ //This reads the file solarsystem.txt and fills array
int current = 0;
char line[201];
char cmpline[2] = "#";
do{
fgets(line, 200, fd); // Makes sure that the number of bytes written dont overflow your character.
}while((strlen(line)<2)||(strncmp(line, cmpline, 1))==0);
sscanf(line, "%s %lf %s %lf %s", body[current].name, &body[current].mass, body[current].color, &body[current].size, body[current].primaryBody);
fscanf(fd, "%lf %lf %lf", &body[current].posx, &body[current].posy, &body[current].posz);
fscanf(fd, "%lf %lf %lf", &body[current].velx, &body[current].vely, &body[current].velz);
current++;
while(!feof(fd)){//Runs the loop until the end of the file is met.
fscanf(fd, "%s %lf %s %lf %s", body[current].name, &body[current].mass, body[current].color, &body[current].size, body[current].primaryBody);
fscanf(fd, "%lf %lf %lf", &body[current].posx, &body[current].posy, &body[current].posz);
fscanf(fd, "%lf %lf %lf", &body[current].velx, &body[current].vely, &body[current].velz);
current++;
}
return current;
}
void sortNames(int planetNames){ //traditional bubble sorting code, with slight modification.
struct planets temp[1];
for(int i=0; i<(planetNames);i++){
for(int j=0; j<(planetNames-1); j++){
if (strcmp(body[j].name, body[j+1].name)>0){
temp[0] = body[j];
body[j] = body[j+1];
body[j+1] = temp[0];
}
}
}
void printBodies(int sortNames){// code to print out the sorted file.
int planetNames = sortNames;
printf("Name Mass Color Size Primary Body\n");
printf("_____________________________________________\n");
for(int i=0; i<(planetNames); i++){
printf("%-8s %1.4E %-6s %.2lf %s\n", body[i].name, body[i].mass, body[i].color, body[i].size, body[i].primaryBody);
}
}
int main(int argc, char *argv[]){/*runs the different structs, and if file not available, will tell the user.*/
FILE *fd;
fd = fopen (argv[1], "r");
if(!fd){
printf("File not available, or user did not type file name.\n");
return 1;
}
int planetNames=readData(fd);
sortNames(planetNames);
printBodies(planetNames);
findMax(planetNames);
return 0;
}

Resources