Name will not display - c

I have my code compiling without issue, accepting input without issue, printing without issue. HOWEVER, it does not want to print the name it only prints a space. It was working and I made some additional changes and I don't know what went wrong. Any thoughts would be greatly appreciated!
#include <stdio.h>
#include <stdlib.h>
struct File {
char type;
char name;
int time;
int size;
}f;
int main()
{
struct File * c = malloc(1 *sizeof(struct File));
printf("Enter file name: \n");
scanf("%s", &f.name);
printf("Enter the file size: \n", f.size);
scanf(" %d", &f.size);
printf("Enter when the file was last accessed: \n", f.time);
scanf(" %d", &f.time);
printf("Enter the file type: \n", f.type);
scanf("%s", &f.type);
printf("\n");
structPrint();
}
structPrint()
{
printf("Filename: %s, File Size: %d, Type: [%s], Access Time: %d \n", &f.name, f.size, &f.type, f.time);
}

Your structure contains space for exactly 1 character type and 1 character name. Both of those are likely to be longer than a single character - in fact, they must, since they're presumably supposed to be null-terminated strings. Try making those into arrays instead...

Your problem is that you are storing name and type as chars, not char[]s. You can either allocate memory for them at runtime or declare them as arrays of fixed size. My code will use the latter.
Change the struct to something like this:
struct File {
char type[12]; /*or whatever maximum sizes you think are appropriate */
char name[64];
int time;
int size;
}f;
Remove the & operators in the scanf and printf calls for name and type.

Related

format '%s' expects argument of type '*char' but argument 2 has type 'int'

When I try to compile my program I get the warning message in the title and when I run it after scanning the names and scores it just stops. I encountered this problem a lot of times while practicing working with strings, but I haven't been able to find a solution.
#include <stdio.h>
struct students {
char name[20];
int score[20];
} student;
int main() {
int i, n;
printf("Number of students:\n");
scanf("%d", &n);
for(i=0; i<n; i++) {
printf("Name of the student:\n");
scanf("%s", &student.name[i]);
printf("Score of the student:\n");
scanf("%d", &student.score[i]);
}
for(i=0;i<n;i++) {
if(student.score[i] >= 15) {
printf("%s passed the exam\n", student.name[i]); }
else {
printf("%s failed the exam\n", student.name[i]);
}
}
return 0;
}
There are several issues:
printf("%s passed the exam\n", student.name[i]);
student.name[i] is a char but the %s format specifier wants a pointer to char.
But the actual problem is that your declaration of students is not what you need. Following structure declares one student whose name can be up to 19 characters long and having 20 scores.
struct students {
char name[20];
int score[20];
} student;
But you need 20 (or more?) students each of them having one score:
struct student {
char name[50]; // name up to 49 characters
int score; // score
} student;
struct student students[20]; // array of 20 students
Il leave the implementation of the code to the reader as an exercise.
You need to get familiar with following concepts:
arrays
structs
strings
basics of scanf and printf
All these topics are covered in your C text book.
Your code have quite a few issue.
1) student should be array ( or dynamically memory allocated).
2) scanf of string needs to be done as
scanf("%s", student[i].name)
Or
scanf("%s", &student[i].name[0])
3) Still you would have issue if string length crosses 20 byte (include nul character).
char name[20];
sets aside space for a single 20-character string, so students.name[i] refers to a single character (which gets promoted to type int in the scanf call).
To define an array of strings, you need a 2D array of char, like
char name[NUMBER_OF_STRINGS][MAX_STRING_LENGTH+1];
and you read it as
scanf( “%s”, student.name[i] ); // no & operator here
Array expressions “decay” to pointer expression under most circumstances, so you don’t need the & operator here.
Alternately, you can declare an array of pointers to char, like
char *name[NUMBER_OF_STRINGS];
and then allocate memory for each string as you read it:
char buffer[MAX_STRING_LENGTH+1];
...
scanf( “%s”, buffer );
student.name[i] = malloc( strlen( buffer ) + 1 );
if ( student.name[i] )
strcpy( student.name[i], buffer );
You just need to remember to free each student.name[i] when you’re finished.
The student name is a singular array of char and needs to be an array of character arrays.
struct students {
char name[20][40];
int score[20];
} student;
I arbitrarily assumed 40 characters per name was sufficient.
The scanf for the name needs to be changed from:
scanf("%s", &student.name[i]);
To:
scanf("%s", student.name[i]);
scanf("%s", &student.name[i]); You're addressing a single char from the string you declared. I assume you would want an individual object for every student. To do this my advice would be to define your struct like this:
typedef struct students {
char name[20];
int score;
}Student;
With this you have defined a new data type called Student. Each object of the type Student has a string called name and an int resembling the score.
After you've created this model, you can treat it as just another variable type, e.g. the following is totally valid:
Student student1, student2;
Alternatively, you could create an array of Students: Student group[20] and then have a loop fill it with data:
for(int i = 0; i < n; i++){
puts("Name of the student: ");
fgets(group[i].name, 20, stdin);
puts("Score of the student: ");
scanf("%d", &group[i].score);
}
The deal is per iteration to refer to an individual object of the array of students.
Also, I would strongly recommend to use fgets() or at least gets_s() for inputting strings. scanf() has multiple problems, some of which are that it stops input if it encounters a space, tab or a newline and most importantly it doesn't check for array bounds. Consider using a safer variant, just keep in mind that fgets() appends a '\n' before the terminating null.

Segmentation fault: 11 in basic single source C program

I am an absolute beginner is C, so bear with me.
I am getting a segmentation fault: 11 directly after I put my Name in When I run my code. When I compile it never has any errors so I am really not sure what I am doing wrong. I am on mac also if that affects anything.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char * name;
char * pass;
} user;
void prompt(user u) {
char passw;
char name;
printf("Enter your name:\n");
scanf("%s", &name);
if (strncmp(u.name, &name, strlen(u.name)) == 1) {
printf("Correct! Please input password:\n");
scanf("%s", &passw);
if (strncmp(u.pass, &passw, strlen(u.pass)) == 0) {
printf("Congrats! you got in.\n");
}
}
}
int main() {
user me;
me.name = "Me";
me.pass = "1234";
prompt(me);
return 0;
}
The problem here is with the variable type name and the corresponding format specifier. You defined it to be a char, but you use %s to scan the value. It causes a bound-overflow that creates undefined behavior.
You need to make name an array, like
char name[64] = {0}; //size is for demo
and the, use scanf() like
scanf("%63s", name);
same goes for passw, also.
FWIW, %s is used to scan a string, whereas, to intake a single char, you need to use %c format specifier.
Also, you can consider having a look at the man page for fgets() as this is considered a safer alternative.

Is this a misunderstanding of the functionality of strcpy()?

#include <stdio.h>
#include <string.h>
int main(void) {
int number_of_members;
char family[number_of_members][20][number_of_members][20];
char member_name[20];
char birth_state[20];
char family_last_name[20];
printf("What is the last name of the family?\n");
scanf("%s", &family_last_name);
printf("How many members do you want to create?\n");
scanf("%d", &number_of_members);
int const FAMILY_SIZE = number_of_members;
number_of_members = number_of_members -1;
printf("Enter the family member name: \n");
for(number_of_members;number_of_members>-1;number_of_members--)
{
scanf("%s", &member_name);
strcpy(family[number_of_members], member_name);
printf(" %d %s %s\n",number_of_members, member_name, family_last_name);
}
printf("%s, %s ", family[0], family[1]);
return 0;
}
Here is the output:(from Ideone.com)
Ideone.com with code
The input to this code is: Layne , 2 , tim , jim.
When run, it shows the correct index with the name in the array however, once out it will show the last entered name, jim, as family1 and family[0]. Am I not understanding how strcpy() works? or is it a logic error?Some assistance soon would be appreciated!
This is very very wrong
int number_of_members;
char family[number_of_members][20][number_of_members][20];
Because you haven't initialized number_of_members.
Because it doesn't make sense whatsoever, it's not possible that you really need this kind of array.
And yes, if you enable compiler warnings it will hit you in your nose with a stick, because
strcpy(family[number_of_members], member_name);
shouldn't even compile and is undefined behavior since the type of family[number_of_members], is an array of arrays of arrays of char.
strcpy can take an array of char's because it will be automatically converted to a char poitner, and provided that the contents of the array comply with what a c string is, then strcpy() will work correctly, in your case the behavior is undefined because almost surely the '\0' will never be found in the destination pointer.
instead of
int num_of_members;
char family[number_of_members][20][number_of_members][20];
which is not C code, do this
#define MAX_MEMBERS 20
char family[MAX_MEMBERS][20];
which creates a rectangular array of arrays each of 20 bytes long

I can't seem to print out a string from a structure but I can print an integer

My code is suppose to get the names of students and the student grade. After that I try to print the student names from the structure that I made and I can only get the grade to print. I get an error when trying to print the string using
printf("%s", test[0].names);
and the error says,
Unhandled exception at 0x0fe113af (msvcr100d.dll) in StudentNamesAndGrades.exe: 0xC0000005: Access violation reading location 0x65736f4a.
But when I use
printf("%d", test[0].studentScores);
It prints out the score of the first student. Here is the entire code because it might be something other than the way I'm trying to print it out.
#include <stdio.h>
#include <string>
/*
this program will get a name of students
and then you will enter the grade for each one :)
*/
struct students
{
char *names;
int studentScores;
};
int main(void)
{
int numStudents = 0;
students *test;
int i;
printf("Enter the number of students in your class: ");
scanf("%d", &numStudents);
test = (students*)malloc(numStudents * sizeof(students));
printf("Enter the names of the %d students\n", numStudents);
for (i = 0; i < numStudents; i++)
{
printf("Enter the name of student %d: ", i + 1);
scanf("%s", &test[i].names);
printf("Enter the students score: ");
scanf("%d", &test[i].studentScores);
}
printf("%d", test[0].studentScores);
printf("%s", test[0].names); // This is where I get a problem :/
return 0;
}
You did not allocate memory for char *names; while taking input at all.
Your struct could be like:
typedef struct students
{
char names[30];
int studentScores;
}students;
Also using fgets is safer than using scanf.
You need to allocate space for the names field, but I would recommend a different approach
struct students
{
char names[100];
int studentScores;
};
and then change the scanf() to
scanf("%99s", test[i].names);
there is another mistake in your first scanf() your are passing the address to the pointer, instead of the pointer.
You should use the address of & operator for the integer, because you need to pass a pointer to an integer for the "%d" specifier, but your names field variable was already a pointer, so no neet to take it's address.
Some other tips you might be interested in
Don't cast the result of malloc, although it seems that you are erroneously using a c++ compiler to compile c code, and in c++ you do need the cast, in c you don't, it makes your code harder to read and other problems which you can read with the most popular c question on Stack Overflow.
Check the return value from malloc, it doesn't matter how unlikely it could fail, since it could theoretically fail, you must check it's return value, which is NULL on failure.

I'm lost, and my outputs are incorrect (C)

So I have an assignment for my class and where supposed to have a structure, two functions, and a main function. The structure needs to have those 3 variables, the functions need to have those names, and the main can only have those 3 lines. This is my first C program and we've been doing c++ all year so I'm a little lost. I wrote up the program and it compiles, but after I enter the values, the outputs equal a value that's basically random.
//Joshua
#include <stdio.h>
struct Person
{
char name[100];
int age;
float gpa;
};
void fill_person(struct Person* per)
{
char name[100];
printf("Enter a name.\n");
fgets(name, 100, stdin);
per->name = name;
int age;
printf("Enter an age. \n");
scanf("%d", &age);
per->age = age;
float gpa;
printf("Enter a GPA. \n");
scanf("%f", &gpa);
per->gpa = gpa;
}
void show_person(struct Person* per)
{
char name[100];
printf("The person's name is %c\n", &name);
int age;
printf("Their age is %d\n", &age);
int gpa;
printf("Their GPA is %f", &gpa);
}
int main()
{
struct Person per;
fill_person(&per);
show_person(&per);
}
Check your printf statements in show_person — at the minute they're passing the wrong kind of variable after each string, and the values they're passing are unrelated to the struct you pass in.
The stuff around your fgets also won't work the way you expect. E.g. char string1[100], string2[100]; string2 = string1; doesn't copy the contents of string1 to string 2.
Its because you aren't using the 'per' variable you pass the show_person function. You are basically creating new variables in that function, and then displaying them. You need to use per-> and drop the declaration of the variables in the function.
The name and other variables that you're printing are uninitialized local variables. You want to print the name from the Person object instead.
This is better, you don't need to use those local variables, you can read directly into your struct:
void fill_person(struct Person* per)
{
printf("Enter a name.\n");
fgets(per->name, 100, stdin);
printf("Enter an age. \n");
scanf("%d" ,&per->age);
printf("Enter a GPA. \n");
scanf("%f",&per->gpa);
}
Check Tommy's answer for the problem with your other function.
tl;dr "The outputs equal a value that's basically random" because
printf is being used incorrectly; and
per->name = name is incorrect.
Fixing printing
The &someVariable makes sense when using scanf/fgets/etc as these functions must modify a variable (in C this is done by passing a pointer to said variable); however, one should not pass a pointer to a variable when using printf: just pass the value!
Also, use the data that has been read (here is is available via the supplied per parameter). Using new local unassigned variables (even without &someVariable) will lead to unpredictable output.
void show_person(struct Person* per)
{
// Also note use of %s, not %c - refer to the printf documentation.
printf("The person's name is %s\n", per->name);
printf("Their age is %d\n", per->age);
// ..
Fixing reading
Now, there is another crucial flaw in fill_person (does it even compile?). This because one does not "copy" strings in C with x = y as that merely assigns a value, possibly a character pointer. Either use strcpy or, better, fgets directly into the per->name character array.
void fill_person(struct Person* per)
{
printf("Enter a name.\n");
fgets(per->name, 100, stdin);
// While the following intermediate variables could also be eliminated
// using them won't affect the semantics of the code.
// ..
I hope the sample stubs above and notes get you on your way!
Because the struct in C doesn't have attributed like "protected" or "private" in C++/java and pointer *this in c++,so you can change the value of member in struct in function. I think you should write the function show_person like code bellow:
void show_person(struct Person* per)
{
printf("The person's name is %c\n",per.name );
int age;
printf("Their age is %d\n",per.age);
int gpa;
printf("Their GPA is %f", per.gpa);
}
When you use &variable, it's means the addresss of variable in memory, not its value. You should write your funciton like that
printf("The person's name is %c\n",name );

Resources