I am facing a very weird issue that i can only produce on linux. I really couldnt find anything like it on the internet, but if my searching skills are not good enough, I apologize if this was a repeat of any question.
Take the following minimal viable code below: I cut back much as i could while still having the issue.
#include <stdio.h>
#define MAX 10
#define MAXNAME 30
typedef struct sup{
int rating;
char supName[MAXNAME];
}sup;
typedef struct spec{
char name[MAXNAME];
float width;
float height;
float depth;
char material[MAXNAME];
sup supvisor[MAX];
}spec;
int read_Supervisors(char fileName[], spec *specread){
int i=0;
char buffer[MAX];
FILE *supervisors = fopen(fileName, "r");
while (i < MAX && fgets (buffer, sizeof(buffer), supervisors)) {
if(sscanf(buffer, "%19s %d", specread->supvisor[i].supName, &specread->supvisor[i].rating) == 2){
i++;}}
fclose(supervisors);
return i;
}
void read_Specs(char fileName[],spec *spec1){
FILE *specs = fopen(fileName, "r");
fscanf(specs, "%29[^\n]\n %19s\n %f\n %f\n %f", spec1->name, spec1->material,&spec1->width, &spec1->height, &spec1->depth);
fclose(specs);
}
int main(int argc, char *argv[]) {
spec spec1 = {.name = ""}; // Initialize .name at zero
//Read specs file.
read_Specs(argv[1],&spec1);
int iteration = read_Supervisors(argv[2], &spec1),
selectedSuper = 1,
calculatedDays = 50;
float priceOfProject = 1;
//Print all the values.
printf("Dear %s,"
"\nThank you for your order.\n"
"Your retaining wall of specifications:\n"
"Material: %s\n"
"width: %.2f m\n"
"height: %.2f m\n"
"depth: %.3f m\n"
"Will be completed in %d days and the assigned project supervisor is %s\n"
"The estimated price is: $%.2f\n", spec1.name, spec1.material, spec1.width,spec1.height,spec1.depth,calculatedDays, spec1.supvisor[selectedSuper].supName,priceOfProject);
return 0;
}
Output:
,ear Jason Oliver
Thank you for your order.
Your retaining wall of specifications:
Material: Concrete
width: 5.50 m
height: 1.00 m
depth: 0.250 m
Will be completed in 50 days and the assigned project supervisor is Sally
The estimated price is: $1.00
Notice that the print out was ,ear rather than Dear Jason oliver,
when removing the comma Dear %s,
to Dear %s
it works perfectly. I can have the comma before the %s
but not after.
I have tried a many things, increasing the #defines, I have tried splitting to multiple printf, i have tried a different versions of C11, C23, I have also tried updating my linux. I gonna note that this is a clean install of linux.
Here is some information about the linux(22.04) env I am using:
Linux Linux 5.19.0-35-generic #36~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Feb 17 15:17:25 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
Compiler version:
gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0
structure of the files:
specs.dat file:
Jason Oliver
Concrete
5.50
1.0
0.250
Builders.dat file:
Bob 50
Sally 78
Jian 69
Hecctor 89
>Solution :
Your input file must be using \r\n
line endings prevalent on Windows, rather than the single \n
that Unix is using. Your code reads the name up to the \n
character, so \r
becomes part of the name
. When you print the name to the terminal, \r
instructs it to move the cursor to the beginning of the line (it’s a carriage return control character). The next character you print after that is a comma, thus it overwrites the ‘D’ of the ‘Dear’ that’s located at the same position.
You can fix your fscanf
to exclude \r
from the string too. Note that the following \n
in the format string is incorrect in such a situation. A simple space will do the trick to skip both \r
and \n
, as well as other white-space characters:
fscanf(specs, "%29[^\r\n] %19s %f %f %f", spec1->name, spec1->material,&spec1->width, &spec1->height, &spec1->depth);