Copy a string into a char array - c

Hello i want to copy the input of a user into an array of char which is defined in a struct. Sincerly i have no idea how to do this.
#include <stdio.h>
#include <stdlib.h>
int main ()
{
struct employee
{
char firstname[11];
char lastname[11];
char number[11];
int salary;
}
int i;
int nemps;
const int maxemps = 5;
struct employee* emps[maxemps];
printf("How many employees do you want to store?(max:5): ");
scanf("%d", nemps);
for (i = 0; i < nemps; i++)
{
printf("Employee 1./nLast name:");
scanf("....")// Read the string and copy it into char lastname[]
}
}

First off struct employee* emps[maxemps]; creates an array of pointers to struct employee with array size maxemps. You haven't actually set aside any space in memory for the actual structs, just the pointers that will point to them. To dynamically allocate space on the heap for your structs so you can use them in a meaningful way, you'll need to loop over a call to malloc() like so:
for (i = 0; i < maxemps; i++) {
emps[i] = malloc(sizeof(struct employee));
}
You'll also want a similar loop at the end of your program which will free() each pointer.
Next, when you are getting input from a user you really want to be using fgets() over scanf() because fgets() allows you to specify the number of characters to read in so you can prevent overflows on your destination buffer.
Update
If you want to work with a single struct employee without the use of pointers this is accomplished by declaring one or more struct employee on the stack and then using the . member access operator as follows:
struct employee emp;
fgets(emp.lastname, sizeof(emp.lastname), stdin);
Update2
I found a number of errors in your code. Please see this link for a working sample with comments.

You only need:
scanf("%10s", (emps[i])->last_name);
Here "%10s" denotes a string with a maximum length of 10, and it will load the string to last_name.
In C the string is represented as a char array, with '\0' as the end.
Using scanf here is vulnerable to buffer attacks if the user-input is longer than 10: http://en.wikipedia.org/wiki/Scanf#Security, so you need to assign a maximum length to the format.

Related

simple c scanf is not reading and parsing my input

I have created Date struct to store date format as date, month, year which is inputed by the user as a single line string seperated by space.
I want to split the input and store it accordingly. I have used simple C sscanf() to split and store my input in struct Date. But when I try to print my data it's showing some garbage value, I don't know what is missing.
Help me to clear this issue.
My code:
Input: 24 Jan 1980
output: 24 ? -978635323
here is my C code.
struct Date
{
int date;
char* month;
int year;
};
int main()
{
struct Date date[1];
char* string;
scanf("%s",string);
sscanf(string,"%d %s %d",&date[0].date,date[0].month,&date[0].year);
printf("%d %s %d",date[0].date,date[0].month,date[0].year);
return 0;
}
Thanks in advance.
it works for me. You can check it.
struct Date
{
int dat;
char month[20];
int year;
};
int main()
{
struct Date date[1];
char str[20];
scanf("%[^\n]%*c", str);
sscanf(str,"%d %s %d",&date[0].dat,&date[0].month,&date[0].year);
printf("%d %s %d",date[0].dat,date[0].month,date[0].year);
return 0;
}
EXPLANATION
In your code, you have declared two char * pointers char *month and char *string, and trying to store string values in them. You have to understand that these two are mere pointers. All they can store are memory addresses to char arrays. It is true that an array variable is interchangeable with a pointer in C. But an array declaration also involves a size attribute.
When you declare a character array as:
char str[10];
It actually reserves a block of size 10 in memory, implicitly creates char *str, and stores the base address of the newly created block in str. But when you just declare char *str, all it does is create a pointer. This doesn't have any associated memory block for the array.
That's why you have to declare a character array of some size before storing strings in it with scanf(). Or you have to dynamically allocate memory with calloc or malloc after declaring the char * pointer. Only then can you store a string input in it.
I have modified your code to work properly. It produces the desired output now. Hope this helps.
WORKING CODE
#include <stdio.h>
#include <stdlib.h>
struct Date
{
int date;
char month[10];
int year;
};
int main()
{
struct Date date[1];
char string[20];
scanf("%[^\n]s",string);
sscanf(string,"%d %s %d",&date[0].date,date[0].month,&date[0].year);
printf("%d %s %d",date[0].date,date[0].month,date[0].year);
return 0;
}
EDIT
They themselves are integers actually (as are all pointers).
As mentioned by anastaciu, pointers are not equivalent to integers per se. You can follow the links given in his comments for more knowledge. I had mentioned that statement to assert the difference between pointers and array declarations.
char* string is an uninitialized pointer, it cannot hold a string, you need to allocate memory, initialize it as an array of chars or point it to a variable with memory already allocated or to an existing array of chars.
Your structure member month suffers from the same problem.
A -Wall flag in your compiler should give you a warning:
'string is used uninitialized in this function [-Wuninitialized]'
Another problem is that %s only gets a string, when it finds a blank space, it stops reading, so it can only read 24 in your case.
Though "%[^\n]s" can work, a better solution would be to use fgets, it's a safer function since you can limit the size of the input to the size of receiving container, unlike scanf.
#include <stdio.h>
#define SIZE 100
struct Date
{
int date;
char month[SIZE];
int year;
};
int main()
{
struct Date date[1];
char string[SIZE];
fgets(string, sizeof(string), stdin);
sscanf(string,"%d %s %d",&date[0].date, date[0].month, &date[0].year);
}

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.

trying to scan strings to 2 different elements of a struct in c

I tried to scan 2 different strings to 2 different elements of the same struct and I don't know why its not working.
This is my code:
struct qRegStudents{
char studID[6];
char studName[25];
};
typedef struct qRegStudents students;
int RegStudent() {
students Student;
char temp[6];
printf("Enter ID Number: ");
scanf(" %6s",Student.studID);
printf("Enter Name: ");
scanf(" %25s",Student.studName);
printf("%s",Student.studID);
return 0;
}
I input the student ID as "123456" and then the name as "josh". It prints "123456josh" as just the student ID
You didn't allocate enough space in the studID field to hold 6 characters plus the null terminator. Change the definition to:
struct qRegStudents{
char studID[7];
char studName[25];
};
Edit... Best to include a \n at the end of the printf string to make sure it gets flushed to stdout.
your program have a undefined behavior as there is no memory space you kept for '\0' at the end of studID and studName. Allocate enough memory location.
make it like
struct qRegStudents{
char studID[7]; /* plus 1 for terminating \0 char at end */
char studName[26];
};
Also do fflush(stdout) to clear stdout stream or use \n. for e.g
printf("%s\n",Student.studID);
printf("%s\n",Student.studName);
Always compile your code with warning enable flags. For e.g -Wall flag. It will tell you something about unused variable(temp[6]), read it.

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.

Structures in C - not printing the whole string

Working on some self study in understanding structures in C.
I've made a small program that gets info from the user and then prints it back via functions.
I used two different methods of handing off the data using a couple examples in the C Primer Plus book.
What happens is that I can input the data but when it prints it back out the numeric data is ok but only the first character in each string is printed with garbage after it.
My code is below for review. I can't figure out what the issue is.
Any help would be great. Thanks!
#include <stdio.h>
#include <stdlib.h>
struct stats {
char name;
char city;
int wins;
int losses;
int draws;
};
void screen_print(char name,char city,int wins,int losses,int draws);
void team_input (struct stats * ptr);
int main()
{
struct stats team;
team_input(&team);
screen_print(team.name,team.city,team.wins,team.losses,team.draws);
return 0;
}
void screen_print(char name,char city,int wins,int losses,int draws)
{
// system("cls");
printf("==================================================\n");
printf("Name:\t\t\t%s\n",&name);
printf("City:\t\t\t%s\n",&city);
printf("Number of Wins:\t\t%d\n",wins);
printf("Number of Losses:\t%d\n",losses);
printf("Number of Draws:\t%d\n",draws);
printf("==================================================");
}
void team_input (struct stats * ptr)
{
system("cls");
printf("Enter Team name: ");
scanf("%s",&(ptr->name));
printf("\nEnter City:");
scanf("%s",&(ptr->city));
printf("\nEnter Wins:");
scanf("%d",&(ptr->wins));
printf("\nEnter Losses:");
scanf("%d",&(ptr->losses));
printf("\nEnter Draws:");
scanf("%d",&(ptr->draws));
}
name and city are single characters only: they are not strings.
scanf("%s",&(ptr->name)); is invalid and will be overwriting memory as an attempt is being made to read a string into a single char.
printf("%s", &name); expects name to be a null terminated string, so it will print the name char then random characters until a null is found somewhere in memory.
Change to:
struct stats {
char name[20]; /* Or greater than 20 if required */
char city[20];
int wins;
int losses;
int draws;
};
or dynamically allocate memory before populating if maximum possible length of name and city are unknown beforehand.
Change the printf() statements to:
printf("Name:\t\t\t%s\n", name);
printf("City:\t\t\t%s\n", city);
and scanf() statements to:
scanf("%s",ptr->name);
scanf("%s",ptr->city);
and screen_print() signature to:
void screen_print(char* name,char* city,int wins,int losses,int draws)
You're using single chars instead of arrays of chars. Both when inputting and outputting, the system is getting the memory address of a char, thinking that it's a string, and writing to/reading from it without any bounds check. So the adjacent memory is accessed as well, even though you didn't intend to.
You're lucky that your numeric data is input after the textual ones, or else even those would be wrong. Since a struct will usually occupy contiguous positions in memory, it's likely that they are being overwritten when you input your strings. That "garbage" you're seeing is in fact the data in the rest of your struct, plus anything that's "close" to it in memory, until an empty value is found (\0, interpreted as the null char).
In your struct, only one char is allocated for name and city. To hold a string, you need to specify the length at declaration.
struct stat {
char city[20];
char name[20];
...
}
String in C is quite tricky. It is an array of characters using an invisible '\0' for the ending. A string "hello" is actually 'h', 'e', 'l', 'l', 'o', '\0' in the memory.

Resources