I have simple program, in which i am taking information and forming record out of them.
if i give the following input:
name: rahul
usn: 1rv16is038
age:20
the strcat() is missing name string. output should be 1rv16is038|rahul|20|########## but instead output is 1rv16is038||20|###############.
why this unusual behavior?
#include<stdio.h>
#include<string.h>
#define LEN 30
int main(){
char record[255],name[30],usn[10],age[5];
int index;
printf("\nEnter name: ");
scanf(" %s",name);
printf("\nEnter usn: ");
scanf(" %s",usn);
printf("\nEnter age: ");
scanf(" %s",age);
strcpy(record,usn);
strcat(record,"|");
strcat(record,name);
strcat(record,"|");
strcat(record,age);
strcat(record,"|");
for(int i=strlen(record);i<LEN;i++){
strcat(record,"#");
}
printf("\nRecord created is: %s",record);
return 0;
}
I have checked that all the variable is taking input, the problem lies in `strcat()'
1rv16is038 is 10 characters, so you need 11 chars to store it plus the null terminator. The usn array is only 10 chars, so reading this into it is undefined behavior.
In general, you should avoid scanf("%s", ...) because there is no way to prevent buffer overflow. You can use fgets instead if you are reading separate lines, or limit the size with e.g. scanf("%9s", ...).
Related
Struggling on my homework assignment.
After I give inputs it stops rather than doing the random array and last print if anyone can help I would appreciate it
#include <stdio.h>
#include <stdlib.h>
int main() {
char name, color;
int age;
int *poer = &age;
char *p = &name;
char *ptr = &color;
printf("What is your name?\n");
scanf(" %s", &name);
printf("How old are you??\n");
scanf(" %d", &age);
printf("What is your favorite color?\n");
scanf(" %s", &color);
char *story[5] = {"old volkswagen beetle", "singlet", "quater", "left sock",
"blackberry bold ninek"};
srand(time(0));
printf("My pal right here %s is %d years old I feel like we have been coding"
" together for a hundred years now I always wonder where the time has gone"
" One thing I have wanted to know is why they love "
"their %s %s so much I guess I might never know\n",
name, age, color, story[rand() % 5]);
return 0;
}
Plenty of errors can be caught by enabling the compiler warnings.
Here is the list of all problems with their proper solutions:
For this line:
srand(time(0));
You need to include the time.h library, otherwise, you will get an implicit definition of time() error message. Passing NULL to time() is a good practice.
As people figured out:
char name, color;
A single char-type cannot hold more than a single ASCII character. Thus, you need to formulate a sequence of characters, called character array. In C99, variable-length arrays are supported. Still, using a macro constant for defining string lengths during compile-time makes the code good. Replace it:
#define MAX_LENGTH 128 // Prefer your length
...
char name[MAX_LENGTH], color[MAX_LENGTH];
In the similar lines:
printf("What is your name?\n");
scanf(" %s", &name);
scanf() function stops reading further input after whitespace. For example, if you input: John Doe, the name will only store John, Doe becomes truncated. Also, never put an ampersand sign for a char-array in scanf().
fgets() is considered safer than this, since it accepts a limited number of characters defined in its second argument. Replace the scanf():
// ... , sizeof name, ... --- is also applicable here
if (fgets(name, MAX_LENGTH, stdin) == NULL) {
// Do something when input's invalid
}
// Input is okay
Note: The fgets() leaves a trailing newline character as soon as it stops receiving user input. To discard this, use this after its usage:
name[strcspn(name, "\n")] = 0;
After applying all these changes, you will not get any further problems.
the following code will be fine
char name[256];
char color[256];
int age;
printf("What is your name?\n");
scanf(" %s", name);
printf("How old are you??\n");
scanf(" %d", &age);
printf("What is your favorite color?\n");
scanf(" %s", color);
in your code, a char was casted to char* the variable will hold data larger than it could. the the stack was ruined
You used char for string which is wrong. You need a char array to store the strings.
Try this:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define STR_MAX 300
int main()
{
char name[STR_MAX];
char color[STR_MAX];
int age;
printf("What is your name?\n");
scanf(" %s", name);
printf("How old are you??\n");
scanf(" %d", &age);
printf("What is your favorite color?\n");
scanf(" %s", color);
char *story[5] = {"old volkswagen beetle","singlet","quater","left sock","blackberry bold ninek"};
srand(time(0));
printf("My pal right here %s is %d years old I feel like we have been coding together for a hundred years now I always wonder where the time has gone One thing I have wanted to know is why they love their %s %s so much I guess I might never know\n",name, age, color, story[rand()%5]);
return 0;
}
your program terminated abnormally because stack was ruined.
char name; //has only 1 byte space
char color; //has only 1 byte space
but these two variables was used to hold data larger than they can. then data was written to some place else which will cause the stack overflow.
code like this will be ok
char name[256];
char color[256];
I made a program to take multiple inputs as string, store and print them.
Somehow the "Account Number" that's stored in a[i].acn is not printing. I've tried debugging and the problem seems to be in the loop that adds spaces to a[i].name .
#include <stdio.h>
#include <string.h>
struct Bank
{
char name[10],acn[8];
float bal;
}a[100];
int n,i,flag;
void add()
{
//function to add Rs. 100 to accounts that have balance over 1000
//and print the details.
for(i=0;i<n;i++)
if(a[i].bal>=1000)
a[i].bal+=100;
printf("\nS.No.\tName\t\tAcc. No.\tBalance(in Rs.)");
for(i=0;i<n;i++)
printf("\n[%d]\t%s\t%s\t%.2f",i+1,a[i].name,a[i].acn,a[i].bal);
}
void main()
{
printf("Enter the number of customers: ");
scanf("%d",&n);
printf("Enter the details of %d customers:\n",n);
for(i=0;i<n;i++)
{
printf("\nCustomer-%d",i+1);
printf("\nFirst Name: ");
fflush(stdin);
gets(a[i].name);
printf("Account Number: ");
fflush(stdin);
gets(a[i].acn);
printf("Account Balance: ");
scanf("%f",&a[i].bal);
}
for(i=0;i<n;i++)//The problem seems to be in this loop
while(strlen(a[i].name)<10)
strcat(a[i].name," ");
add();
}
Input:
Enter the number of customers: 2
Enter the details of 2 customers:
Customer-1
First Name: Aarav
Account Number: ASDF1234
Account Balance: 1200
Customer-2
First Name: Asd
Account Number: abcd1122
Account Balance: 999.9
Output:
S.No. Name Acc. No. Balance(in Rs.)
[1] Aarav 1300.00
[2] Asd 999.90
scanf() then gets() is bad
scanf("%d",&n); reads the integer, yet leaves the following '\n' in stdin that gets() reads as an empty string "".
I recommend to use fgets() to read all the line into a sizable buffer and then parse using sscanf(), strtol() etc.
Code overfills buffer
a[i].nam only has enough room for 9 characters and then the null character. Appending a space until it has a length more the 9 overfills .name[10].
struct Bank {
char name[10],acn[8];
float bal;
} a[100];
while(strlen(a[i].name)<10)
strcat(a[i].name," ");
Use while(strlen(a[i].name)<9) to pad with spaces, but not too many.
Money needs special considerations. For now, consider a long of lowest denominational (cents). Read in a double and then long balance = lround(input*100.0);
Other weaknesses exist.
There are few things to correct in your program.
Use fgets instead of gets because in gets there is no boundary check and there is a danger of reading beyond the allocated size.
When using fgets , scanf and even gets they all read the left over \n characters from the standard buffer , so using fgets we can avoid it if we properly use it.(scanf also avoids space characters but it cannot be used to read multiword strings)
remove fflush(stdin), its not required you can see reason here
And last, but certainly not least use int main() instead of void main()
You have this:
struct Bank
{
char name[10],acn[8];
float bal;
}a[100];
since C strings must end with a NUL character (aka '\0') the name can be at maximum 9 chars long.
But here
while(strlen(a[i].name)<10)
strcat(a[i].name," ");
you keep adding spaces until it's 10 characters long. In other word - you write outside the array.
Change name to be name[11]
Besides that gets and fflush(stdin) should be avoided.
I'm a student studying C, and seem to be stuck when using Structures and Arrays to read in characters as part of the array.
When I run the code, it skips over the char scanf and will not read in any characters. There is no problem reading in integers etc.
For example (This is an example, my code is much longer but I know there's a problem here). Is the scanf part that reads in the name correct?
struct stud s[5];
int i = 0;
for (int i = 0; i < 5; i++)
{
fflush(stdout);
s[i].no = i + 1;
printf("\nStud number %d\n", s[i].no);
printf("Enter name:");
scanf_s("%c", &s[i].name);
printf("Enter grade: ");
scanf_s("%d", &s[i].grade);
printf("Successfully added to grade book\n");
}
I declared them below:
struct stud {
int no;
char name;
int grade;
};
It would be great if someone could point me in the correct direction?
You have to declare name as a char array
struct room {
int no;
char name[32]; /* pick a reasonable size */
int grade;
};
And then this
scanf_s("%c",&s[i].name);
would change to
scanf_s("%s",s[i].name, _countof(s[i].name));
and since there is no guarantee that the name would be 31 characters length, you have to specify a field length like this
scanf_s("%31s",s[i].name, _countof(s[i].name));
the length should be the sizeOfArray - 1 since c strings need to mark the end of the string with a null byte '\0', and scanf_s will append that byte to the read string.
If you don't specify the field length and it turns out that there are more than characters than requested by _countof(s[i].name) then nothing is read, for more information read here.
Note that you should create a char array of a reasonable size and use %s as mentioned by #iharob in his answer if you want to enter more than 1 character for a student. If you want name to be a char,then change
scanf_s("%c", &s[i].name);
To
scanf_s(" %c", &s[i].name, 1);
The space before %c skips all kinds of blanks(like newlines and spaces) present in the stdin and %c will then scan a non-whitespace character.
The %c will not the characters because the characters will be present in stdin, and you have to skip the characters.
scanf_s("%c", &s[i].name);
if the last character in the previous is \n the %c will take the \n as input.
You have to change the code, just give a space before the %c.
scanf_s(" %c", &s[i].name);
This will flush the white space characters in the stdin and it will get the input.
This question already has answers here:
How do you allow spaces to be entered using scanf?
(11 answers)
Closed 6 years ago.
I'm trying to run the following code in the basic ubuntu gcc compiler for a basic C class.
#include<stdio.h>
struct emp
{
int emp_num, basic;
char name[20], department[20];
};
struct emp read()
{
struct emp dat;
printf("\n Enter Name : \n");
scanf("%s", dat.name);
printf("Enter Employee no.");
scanf("%d", &dat.emp_num);
//printf("Enter department:");
//fgets(dat->department,20,stdin);
printf("Enter basic :");
scanf("%d", &dat.basic);
return dat;
}
void print(struct emp dat)
{
printf("\n Name : %s", dat.name);
printf("\nEmployee no. : %d", dat.emp_num);
//printf("Department: %s", dat.department);
printf("\nBasic : %d\n", dat.basic);
}
int main()
{
struct emp list[10];
for (int i = 0; i < 3; i++)
{
printf("Enter Employee data\n %d :\n", i + 1);
list[i] = read();
}
printf("\n The data entered is as:\n");
for (int i = 0; i < 3; i++)
{
print(list[i]);
}
return 0;
}
I want the name to accept spaces.
The problem comes when I'm entering the values to the structures. I am able to enter the name the first time but the subsequent iterations don't even prompt me for an input.
I've tried using fgets, scanf("%[^\n]",dat.name) and even gets() (I was desperate) but am the facing the same problem every time.
The output for the 1st struct is fine but for the rest is either garbage, the person's last name or just blank.
Any ideas?
When reading a string using scanf("%s"), you're reading up to the first white space character. This way, your strings cannot include spaces. You can use fgetsinstead, which reads up to the first newline character.
Also, for flushing the input buffer, you may want to use e.g. scanf("%d\n") instead of just scanf("%d"). Otherwise, a subsequent fgets will take the newline character and not ask you for input.
I suggest that you experiment with a tiny program that reads first one integer number and then a string. You'll see what I mean and it will be much easier to debug. If you have trouble with that, I suggest that you post a new question.
The problem is that scanf("%[^\n",.. and fgets don't skip over any whitespace that may be left over from the previous line read. In particular, they won't skip the newline at the end of the last line, so if that newline is still in the input buffer (which it will be when the last line was read with scanf("%d",..), the scanf will fail without reading anything (leaving random garbage in the name array), while the fgets will just read the newline.
The easiest fix is to add an explicit space in the scanf to skip whitespace:
printf("\n Enter Name : \n");
scanf(" %19[^\n]", dat.name);
This will also skip over any whitespace at the beginning of the line (and blank lines), so may be a problem if you want to have a name that begins with a space.
Note I also added a length limit of 19 to avoid overflowing the name array -- if the user enters a longer name, the rest of it will be left on the input and be read as the employeee number. You might want to skip over the rest of the line:
scanf("%*[^\n]");
This will read any non-newline characters left on the input and throw them away. You can combine this with the prior scanf, giving you code that looks like:
printf("\n Enter Name : ");
scanf(" %19[^\n]%*[^\n]", dat.name);
printf("Enter Employee no. : ");
scanf("%d%*[^\n]", &dat.emp_num);
printf("Enter department : ");
scanf(" %19[^\n]%*[^\n]", dat.department);
printf("Enter basic : ");
scanf("%d%*[^\n]", &dat.basic);
This will ignore any spurious extra stuff that someone enters on a line, but will still have problems with someone entering letters where numbers are expected, or end-of-file conditions. To deal with those, you need to be checking the return value of scanf.
What you have tried was:-
scanf("%[^\n]",dat.name)
In this you forgot to specify the specifier.
You can try to use this:-
scanf ("%[^\n]%*c", dat.name);
or fgets() if you want to read with spaces.
Note:- "%s" will read the input until whitespace is reached.
I'm trying to store a few values in a struct object and I want to repeat the prompt until the user types in "yes". I want to use a do-while loop for that. I'm already failing with the read-in of the first "last name". When I type in something, the program just stops (no error). I don't even use the do-while, since I'm not sure if it will work with my while() condition.
#include <ctype.h>
#include <stdio.h>
#include <string.h>
struct employeelist
{
char last[6];
char first[6];
int pnumber;
int salary;
};
int main()
{
struct employeelist employee[5];
char check;
//do
//{
printf("Hello. Please type in the last name, the first name, the personal number and the salary of your employees.\n");
printf("Last name: ");
scanf("%c", employee[1].last);
printf("First name: ");
scanf("%c", employee[1].first);
printf("Personal number: ");
scanf("%d", &employee[1].pnumber);
printf("Salary: ");
scanf("%d", &employee[1].salary);
printf("You have more employess (yes/no)?: ");
scanf("%c", &check);
//}while (scanf("yes"));
return 0;
}
Use %s as your format specifier if you're trying to get a string. You might also want to limit its length to 5, since that's how much space you have for last and first. So that would be %5s. Also, 5 characters is pretty short for a name.
Another comment: arrays in C are zero-based, so employee[1] is the second employeelist in your array. If you want to do this in a loop with an incrementing index, start at 0.
Hi when you read char array you must use scanf("%s", employee[1].last); %s but not %c
What do you think this code does?
scanf("%c", ....
%c indicates that scanf should only read ONE character.
One letter is not going to get you an entire name.
You need to switch to %s for starters.
First of all the first index to work
with will be '0',not 1.
wrong identifier for string,it
should be %s.
If you just want to iterate by
asking y/n then just change the
display message from yes/no to y/n
and also change that strange while
condition to check=='y'||check=='Y'.
The code will actually not work
after 5 iterations because you
initialized only 5 structures of
that type.Why don't you add that in
the loop?