Structs and char strings [duplicate] - c

This question already has answers here:
Why does reading into a string buffer with scanf work both with and without the ampersand (&)?
(2 answers)
Closed 8 years ago.
#include <stdio.h>
#define MAX 3 // students in class
#define LEN 20 // max lengths stydent's name
typedef struct {
char name[LEN];
int am;
float tv;
}student;
void read (student board[]) { //this function should fill the board of structs
int i;
for (i=0; i<MAX; i++) {
printf("\n give student's name");
scanf ("%s",&board[i].name);
}
}
void read (student board[]);
int main (void) {
student class[MAX];
read (class);
return 0;
}
when i try to compile it i get this error
let2.c:15:3: warning: format ‘%s’ expects argument of type ‘char ’, but argument 2 has type ‘char ()[20]’ [-Wformat=]
let2.c:15:3: warning: format ‘%s’ expects argument of type ‘char ’, but argument 2 has type ‘char ()[20]’ [-Wformat=]

Lose the & in your scanf call. You want a pointer to the first character of the string, not a pointer to the array itself:
scanf("%s", board[i].name);
Or, equivalently:
scanf("%s", &board[i].name[0]);

Related

Why is print portion of this program that takes info of 11 cars and prints the model name of red cars not working?

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

Problem in my program code of c please help me in resolving the problem

WHY I AM getting ERROR during COMPILATION with GCC even i have putted the ch variable as char type?
my program:
#include <stdio.h>
void circular(int*,int*,int*);
int main(){
int n1,n2,n3,flag=1;
char fb='y';
do{
printf("enter the value of x,y,z resp.: ");
scanf("%d%d%d",&n1,&n2,&n3);
circular(&n1,&n2,&n3);
printf("after %d circular shift values are: \nx= %d\ny= %d\nz= %d\nwant to do circular shift again(y/n): ",flag,n1,n2,n3);
scanf("%s",fb);
flag+=1;
}while(fb=='y' || fb=='Y');
return 0;
}
void circular(int *n1,int *n2,int *n3){
int temp;
temp=*n1;
*n1=*n2;
*n2=*n3;
*n3=temp;
}
error after compiling with gcc:
c4q13.c: In function ‘main’:
c4q13.c:22:11: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
22 | scanf("%s",fb);
| ~^ ~~
| | |
| | int
| char *
As the message says, the variable fb has type char and it is promoted to int in variable-number arguments. You have to pass char* for %s in scanf().
Also %s reads strings (sequence of characters terminated by a null-character), so passing a pointer to an one-character buffer for %s is bad, causing dangerous out-of-range access.
You should allocate an array for string and pass a pointer to its element. Also you should set the maximum number of characters to read to avoid buffer overrun. Considering the terminating null-character, the limit should be (at most) the number of elements in the buffer minus one.
Things to change:
char fb='y';
scanf("%s",fb);
}while(fb=='y' || fb=='Y');
They should be:
char fb[4]="y";
scanf("%3s",fb);
}while(fb[0]=='y' || fb[0]=='Y');

Why does the printf fail to print Jack and George's names? [duplicate]

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

Segmentation fault and printf warinings

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 *.

C - Strings are giving me errors

So I am writing a simple code to print out each symbol in my string. When compiling it, it gives me an error tough that I do not understand:
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (void) {
char my_string[50];
int i, n;
printf("Type in a string please : ");
scanf("%s", &my_string);
n = strlen(my_string);
for (i = 0;i < n; i++) {
printf("%c",my_string[i]);
}
}
The error it gives:
gcc yl2.c -o Yl2
yl2.c: In function ‘main’:
yl2.c:9:2: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[50]’ [-Wformat=]
scanf("%s", &my_string);
^
What is the problem here?
scanf("%s", &my_string); there should not be a &.
Since you have declared char my_string[50]; my_string as character array which is of type char * which is expecting in scanf() as the warning states.
Just use, scanf("%s", my_string);. Base address of the array as argument is sufficient.
scanf("%s", &my_string); should be scanf("%s", my_string);
my_string is an array, which decays to a pointer when you type it out without [ ].
If you type &my_string, you get an array pointer, which is strictly speaking not the same thing. That's why the compiler complains.
&my_string is a pointer to my_string i.e. a ‘char (*)[50]’
You can either use
scanf("%s", &my_string[0]);
or more conventionally
scanf("%s", my_string);
remove & sign in scan, it will work
Also no need to use string.h here

Resources