My program has some warnings, and then it crashes. It seems likely that the crash is related to the warnings, but I don't understand them. Here is my code:
#include <stdio.h>
struct student {
char name[100];
int id;
char *department;
struct result {
float gpa;
char grade;
} res;
};
int main(void) {
struct student W[] = {{"Saud Farooqui",137,"Electronics",{3.05,'A'}},
{"Talha Farooqui",129,"Civil",{3.5,'A'}}};
printf("First student data is\n%s\t%d\t%s\t%f\t%c",W[0].name,W[0].id,
W[0].department,W[1].res.gpa,W[0].res.grade);
printf("\nSecond student data is\n%s\t%d\t%s\t%f\t%c",W[1].name,W[1].id,
W[1].res.gpa,W[1].res.grade);
}
The compiler printed these warnings about the format specifiers in the second printf:
foo.c:24:10: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'double' [-Wformat=]
W[1].res.gpa,W[1].res.grade);
^
foo.c:24:10: warning: format '%f' expects argument of type 'double', but argument 5 has type 'int' [-Wformat=]
foo.c:24:10: warning: format '%c' expects a matching 'int' argument [-Wformat=]
When I tried to launch the program, the first printf printed a line, but the second one failed:
Segmentation fault (core dumped)
What is wrong with it? How do I fix the warnings and the crash?
There is a missing argument for department. It is obvious, when you compile
it with warnings turned on (-Wall):
a.c:21:7: warning: format ‘%s’ expects argument of type ‘char *’, but argument 4 has type ‘double’ [-Wformat=]
W[1].name, W[1].id, W[1].res.gpa, W[1].res.grade);
^
a.c:21:7: warning: format ‘%f’ expects argument of type ‘double’, but argument 5 has type ‘int’ [-Wformat=]
a.c:21:7: warning: format ‘%c’ expects a matching ‘int’ argument [-Wformat=]
Also, your first printf prints W[1].res which is probably supposed to be W[0].res.
Fixed version:
struct student W[] = {{"Saud Farooqui",137,"Electronics",{3.05,'A'}},
{"Talha Farooqui",129,"Civil",{3.5,'A'}}};
printf("First student data is\n%s\t%d\t%s\t%f\t%c",
W[0].name, W[0].id, W[0].department, W[0].res.gpa, W[0].res.grade);
printf("\nSecond student data is\n%s\t%d\t%s\t%f\t%c",
W[1].name, W[1].id, W[1].department, W[1].res.gpa, W[1].res.grade);
So the segmentation fault is due to the attempt to interpret W[1].res.gpa as a pointer to a string (corresponding to the %s format specifier), i.e. const char *.
Related
here is the code
#include <stdio.h>
#include <string.h>
int main()
{
int val;
struct info{
char model[50];
int price;
char color[30];
}car[11];
int i;
for(i=0;i<11;i++)
{
printf("Enter model name:\n");
scanf("%s",&car[i].model);
printf("Enter price:\n");
scanf("%d",&car[i].price);
printf("Enter color:\n");
scanf("%s",&car[i].color);
}
printf("\nThe red cars are:\n");
for(i=0;i<11;i++)
{
val=strcmp("red",tolower(car[i].color));
if(0==val)
{
printf("%d. %s\n",i+1,car[i].model);
}
}
return 0;
}
also I tried using gets for string input but it doesn't seem to work.
Here are the warnings:
*main.c:17:17: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[50]’ [-Wformat=]
scanf("%s",&car[i].model);
main.c:21:17: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[30]’ [-Wformat=]
scanf("%s",&car[i].color);
main.c:26:34: warning: passing argument 1 of ‘tolower’ makes integer from pointer without a cast [-Wint-conversion]
val=strcmp("red",tolower(car[i].color));
In file included from main.c:4:0:
/usr/include/ctype.h:124:12: note: expected ‘int’ but argument is of type ‘char *’
extern int tolower (int __c) __THROW;
main.c:26:26: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast [-Wint-conversion]
val=strcmp("red",tolower(car[i].color));
In file included from main.c:2:0:
/usr/include/string.h:144:12: note: expected ‘const char *’ but argument is of type ‘int’
extern int strcmp (const char *__s1, const char *__s2)
You posted your compiler output. Good. Let's look at all those errors:
main.c:17:17: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[50]’
Most of the time, when you call scanf, you need & on the variable being stored, but %s is an exception. (Explanation elsewhere.) Get rid of the &: scanf("%s",car[i].model);
main.c:26:34: warning: passing argument 1 of ‘tolower’ makes integer from pointer without a cast
This is your main problem. Your program as written will never work. tolower expects a single character to convert, but you're passing it a pointer instead. (You're passing it a pointer to the entire string you want to convert.)
/usr/include/ctype.h:124:12: note: expected ‘int’ but argument is of type ‘char *’
This is another message explaining the tolower problem.
main.c:26:26: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast
tolower returns the single character it has converted. But strcmp expects an entire string.
/usr/include/string.h:144:12: note: expected ‘const char *’ but argument is of type ‘int’
This is another message explaining the tolower/strcmp problem.
How to fix this? There is not a standard function (that I can remember) that converts an entire string to lowercase. You'd have to write that yourself. Another option is to use a version of strcmp that compares the strings without regard to case. Two such functions (neither of which is quite standard, however) are strcasecmp and stricmp.
tolower only works with char not string, so use the function on every char of the string.
#include <string.h>
#include <stdio.h>
#include <ctype.h>
int strcicmp(char const *a, char const *b)
{
if (!a && !b)
return 0
else if (!a || !b)
return -1
for (;; a++, b++) {
int d = tolower((unsigned char)*a) - tolower((unsigned char)*b);
if (d != 0 || !*a)
return d;
}
}
int main()
{
int val;
struct info{
char model[50];
int price;
char color[30];
}car[11];
int i;
for(i=0;i<11;i++)
{
printf("Enter model name:\n");
scanf("%s",&car[i].model);
printf("Enter price:\n");
scanf("%d",&car[i].price);
printf("Enter color:\n");
scanf("%s",&car[i].color);
}
printf("\nThe red cars are:\n");
for(i=0;i<11;i++)
{
val=strcicmp(car[i].color, "red");
if(0==val)
{
printf("%d. %s\n",i+1,car[i].model);
}
}
return 0;
}
This question already has answers here:
What is the format specifier for unsigned short int?
(5 answers)
Closed 4 years ago.
I would like to know why Jack and George's names fail to print. I tried adding another member in the struct the names get printed normally, why is that ? I would really appreciate it if someone can help. Here's the code:
#include <stdio.h>
typedef unsigned short int u16;
typedef unsigned char u8;
typedef struct
{
u8 name[10];
u16 salary;
u16 bonus;
u16 deduction;
//u8 x;//why does the printed name get ruined
//without this?
}employee;
void main (void)
{
employee arr[3]={{.name = "John"},{.name =
"Jack"},{.name = "George"}};
u16 i = 0;
u16 sum = 0;
for (i = 0; i < 3; i++)
{
printf("\nPlease enter %s's Salary:",arr[i].name);
scanf(" %d",&arr[i].salary);
printf("\nPlease enter %s's Bonus:",arr[i].name);
scanf(" %d",&arr[i].bonus);
printf("\nPlease enter %s's Deduction:",arr[i].name);
scanf(" %d",&arr[i].deduction);
sum = sum + arr[i].salary + arr[i].bonus - arr[i].deduction;
}
printf("\nTotal value needed is: %d",sum);
}
It's because your scanf()'s are wrong, and are overwriting members of your struct.
A decent compiler will issue a lot of warnings that are very severe:
$ gcc -Wall t.c
t.c:13:11: warning: return type of ‘main’ is not ‘int’ [-Wmain]
void main (void)
^~~~
t.c: In function ‘main’:
t.c:22:14: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘u16 *’ {aka ‘short unsigned int *’} [-Wformat=]
scanf(" %d",&arr[i].salary);
~^ ~~~~~~~~~~~~~~
%hd
t.c:24:14: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘u16 *’ {aka ‘short unsigned int *’} [-Wformat=]
scanf(" %d",&arr[i].bonus);
~^ ~~~~~~~~~~~~~
%hd
t.c:26:14: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘u16 *’ {aka ‘short unsigned int *’} [-Wformat=]
scanf(" %d",&arr[i].deduction);
~^ ~~~~~~~~~~~~~~~~~
%hd
When you are calling scanf(" %d",&arr[i].salary); , the %d says to store the number you read as an int type.
However you have declared salary as a u16 type, which on your system is probably a lot smaller than an int. scanf jsut assumes you were telling the truth when you provided %d ,and stores an int in whatever the &arr[i].salary pointer points to, overwriting memory after that variable which might overwrite and trash the name array.
So either
declare your salary, bonus and deduction as int instead of u16, so it matches the %d argument you give to scanf
or
Provide a proper type specifier to scanf for your u16 variables, which is %hu.
e.g.
scanf(" %hu",&arr[i].salary);
scanf(" %hu",&arr[i].bonus);
scanf(" %hu",&arr[i].deduction);
builtin-stat.c: In function ‘abs_printout’:
builtin-stat.c:1023:5: error: incompatible type for argument 2 of ‘gzwrite’
gzwrite(trace_file, avg, sizeof(avg));
^
In file included from builtin.h:6:0,
from builtin-stat.c:45:
/usr/include/zlib.h:1341:21: note: expected ‘voidpc’ but argument is of type ‘double’
ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
What is a voidpc type? never heard of that. zlib.h tells me that it is z_void. What does it mean? and should i typecast here?
WARNINGS:
CC builtin-stat.o
builtin-stat.c: In function ‘abs_printout’:
builtin-stat.c:1020:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
int written = gzwrite(trace_file, (void *) &avg, sizeof(avg));
^
builtin-stat.c:1024:9: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘double’ [-Wformat=]
fprintf(stderr, "Failed to write %d to file\n", avg);
^
builtin-stat.c:1026:13: warning: passing argument 1 of ‘fclose’ from incompatible pointer type [enabled by default]
fclose(trace_file);
^
In file included from util/util.h:45:0,
from builtin.h:4,
from builtin-stat.c:45:
/usr/include/stdio.h:237:12: note: expected ‘struct FILE *’ but argument is of type ‘gzFile’
extern int fclose (FILE *__stream);
^
builtin-stat.c:1029:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]
printf("Passed %d bytes, wrote %d\n", sizeof avg, written);
the voidpc is a typedef: typedef void const * voidpc. you can find the zlib typedefs and the like in the zconf.h header file, which the zlib.h header in turn requires.
source of zconf.h here
A typecast here would not do the trick, I think. The error is saying that avg is of the type double. gzwrite takes uncompressed data, processes it byte-per-byte and writes a number of bytes to the target file. A pointer allows gzwrite to cast to a char *, and set about its business easily. Just pass a pointer, optionally cast it to a voidpc or void *, and _check the return value:
int written = gzwrite(
trace_file,
(void *) &avg,
sizeof(avg)
);
if (written == -1)
{
fprintf(stderr, "Failed to write %f to file\n", avg);
if (trace_file)
gzclose(trace_file);
exit( EXIT_FAILURE );
}
printf("Passed %llu bytes, wrote %d\n", sizeof avg, written);
Should do the trick.
How I can remove this warning:
> warning: format ‘%[^ ’ expects type ‘char *’, but argument 2 has type
> ‘char (*)[1024]’
code looks like this:
char a[1024];
scanf("%[^\n]", &a);
use code as
char a[1024];
scanf("%[^\n]", a);
(note: removal of '&' )
My program takes two files with words sorted as parameter and performs the mixture into 1 single file called final_sorted.txt.the program runs successfully and creates the mixed file, even ignoring repeated words, but the compiler tells me some warnings that are not as removed.
equipo01#equipo01-desktop:~/Escritorio/mezclar (2)$ gcc meclapro.c -o mixmeclapro.c: In function ‘mix_files’:
meclapro.c:10: warning: passing argument 1 of ‘fopen’ from incompatible pointer type
/usr/include/stdio.h:249: note: expected ‘const char * __restrict__’ but argument is of type ‘char **’
meclapro.c:11: warning: passing argument 1 of ‘fopen’ from incompatible pointer type
/usr/include/stdio.h:249: note: expected ‘const char * __restrict__’ but argument is of type ‘char **’
meclapro.c: In function ‘main’:
meclapro.c:69: warning: passing argument 1 of ‘mix_files’ from incompatible pointer type
meclapro.c:6: note: expected ‘char **’ but argument is of type ‘char *’
meclapro.c:69: warning: passing argument 2 of ‘mix_files’ from incompatible pointer type
meclapro.c:6: note: expected ‘char **’ but argument is of type ‘char *’
this is my code, which takes which takes the command line parameter
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void mix_files(char **file1, char **file2){
FILE *a1, *a2, *output;
char aux1 [10000],aux2 [10000];
a1 = fopen(file1, "r");
a2 = fopen(file2, "r");
ouput = fopen ("final.txt", "w+");
// read the first line of each file:
fscanf(a1,"%s",aux1);
fscanf(a2,"%s",aux2);
// loop, while !feof for both file
while(!feof(a1) && !feof(a2)) {
// Select the line to add
if(strcasecmp(aux1,aux2) < 0){
// add the line
fprintf(output,"%s\n",aux2);
//read the next line from aux2
fscanf(a2,"%s",aux2);
}
else if(strcasecmp(aux1,aux2)>0){
fprintf(salida,"%s\n",aux1);
fscanf(a1,"%s",aux1);
}
if (strcasecmp(aux1,aux2)==0){
//printf("repetidas\n");
fprintf(salida,"%s\n",aux1);
fscanf(a1,"%s",aux1);
fscanf(a2,"%s",aux2);
}
}
if(!feof(a1)){
while(!feof(a1)) {
fscanf(a1,"%s",aux1);
fprintf(salida,"%s\n",aux1);
}
}
if(!feof(a2)){
while(!feof(a2)) {
fscanf(a2,"%s",aux2);
fprintf(salida,"%s\n",aux2);
}
}
}
int main(int argc, char *argv[]){
mix_files(argv[2], argv[1]);
return(0);
}
I would like someone to help me discover the reason for the warning and how could I fix, thanks in advance for your answers, sorry for my English
Change:
void mix_files(char **file1, char **file2){
to:
void mix_files(char *file1, char *file2){
or better still:
void mix_files(const char *file1, const char *file2){
You will then be passing the correct type (char *) from main to mix_files, and this in turn will also fix the problem when you call fopen.