How to give whitespace in string in structure in C Language [duplicate] - c

This question already has answers here:
How do you allow spaces to be entered using scanf?
(11 answers)
Closed 2 years ago.
Hello senior programmers! I am new in programming. I am having trouble making my program run efficiently. My code works perfectly fine when I do not give white space. But when I give white space while writing the name or route it doesn't work.
Example: Driver's Name: ALI ( work perfectly )
Example: Driver's Name: ALI ALI ( not working )
I want to write all the char with white space. I have already tried every possible way. I have commanded all the ways which I have tried. I am a beginner. It is my college assignment. Kindly, please help me, How can I fix this?
/*
You manage a travel agency and you want your n drivers to input their following details:
1. Name
2. Driving License No
3. Route
4. Kms
Your program should be able to take n as input(or you can take n=3 for simplicity) and your drivers will start inputting their details one by one.
Your program should print details of the drivers in a beautiful fashion.
User structures.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define Max_Size 1000
#define max 1000
struct Drivers
{
char Name[150];
char Driving_License_No[150];
char Route[150];
char Kms[50];
int positionNo;
} drivers[Max_Size];
int main()
{
int totalDrivers;
char name[200];
printf("Enter the total numbers of drivers\n");
scanf("%d", &totalDrivers);
for (int i = 0; i < totalDrivers; i++)
{
drivers[i].positionNo=i+1;
printf("\nFor Driver Id no. %d,\n", drivers[i].positionNo);
printf("Enter the full name: ");
scanf("%s", &drivers[i].Name);
// scanf("%[^\n]",drivers->Name);
// scanf("%[^\n]s",drivers->Name);
// fgets(drivers.Name, 150, stdin);
// gets(Name);
// gets(driver.Name);
printf("Enter the Driving License no : ");
scanf("%s", &drivers[i].Driving_License_No);
printf("Enter the Driving Route : ");
scanf("%s", &drivers[i].Route);
printf("Enter the Driving KM's : ");
scanf("%s", &drivers[i].Kms);
}
printf("The Information of all drivers are given below\n");
for (int i = 1; i < totalDrivers; i++)
{
printf("\nDriver Id no.: %d\n", i + 1);
printf("Driver's Name: ");
puts(drivers[i].Name);
printf("Driving License no: %s", drivers[i].Driving_License_No);
printf("\n");
printf("Driving Route: %s", drivers[i].Route);
printf("\n");
printf("Driving KM's: %s", drivers[i].Kms);
printf("\n");
}
return 0;
}

There are multiple issues:
parsing a string with embedded white space can be done with %[^\n] in scanf().
you should tell printf the maximum number of characters to store into the destination arrays to avoid potential undefined behavior on invalid input.
&drivers[i].Name is not a char *, you should pass drivers[i].Name.
when printing the details, you start at 1 instead of 0.
to input multiple strings with embedded spaces, which is likely required here, you should use " %[^\n]" with an initial space to skip the pending newline and any initial spaces.
Here is a modified version:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define Max_Size 1000
#define max 1000
struct Drivers {
char Name[150];
char Driving_License_No[150];
char Route[150];
char Kms[50];
int positionNo;
} drivers[Max_Size];
int main() {
int totalDrivers;
char name[200];
printf("Enter the total numbers of drivers\n");
if (scanf("%d", &totalDrivers) != 1)
return 1;
if (totalDrivers > Max_Size) // avoid overflowing the drivers array;
totalDrivers = Max_Size;
for (int i = 0; i < totalDrivers; i++) {
drivers[i].positionNo = i + 1;
printf("\nFor Driver Id no. %d,\n", drivers[i].positionNo);
printf("Enter the full name: ");
scanf(" %149[^\n]", drivers[i].Name);
printf("Enter the Driving License no: ");
scanf(" %149s", drivers[i].Driving_License_No);
printf("Enter the Driving Route: ");
scanf(" %149s", drivers[i].Route);
printf("Enter the Driving KM's: ");
scanf(" %49s", drivers[i].Kms);
}
printf("The Information of all drivers are given below\n");
for (int i = 0; i < totalDrivers; i++) {
printf("\n");
printf("Driver Id no.: %d\n", i + 1);
printf("Driver's Name: %s\n", drivers[i].Name);
printf("Driving License no: %s\n", drivers[i].Driving_License_No);
printf("Driving Route: %s\n", drivers[i].Route);
printf("Driving KM's: %s\n", drivers[i].Kms);
}
return 0;
}

See instead of using %s as format specifier you should use %[^\n] as the format specifier while taking input in scanf to take the input with white spaces.
printf("Enter the full name: ");
scanf("%[^\n]", drivers[i].Name);
In case of any query please feel free to ask.

Related

Why does my program exit after taking an input?

Consider:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
int n;
char name[100];
int number;
printf("Enter the value of n\n");
scanf("%d",&n);
printf("Enter %d values\n", n);
for(int i=0; i<n; i++)
{
scanf("%[^\n]s", &name);
}
}
Whenever I am entering the value of n, it just prints (Enter n values) and exits the program. The for loop never runs. It ran successfully for the first time, but after that it just exits the program.
There were some answers that said it will not print anything. I don’t want it to print just to take input n times. It is not doing that.
My aim is to take n as input and then take strings of names (like harry, robin, etc.) n number of times as input.
Your code is a little incomplete. And there are a few errors here: scanf ("%[^\n]s", &name)
Do this and everything will be fine:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main(void)
{
int n;
char name[100];
int number;
printf("Enter the value of n\n");
scanf(" %d", &n);
printf("Enter %d values\n", n);
for(int i=0; i<n; i++)
{
scanf(" %99[^\n]", name);
printf("%s\n", name);
}
return 0;
}
scanf is particularly unsuited for user input.
You probably want this:
int main() {
int n;
char name[100];
int number;
printf("Enter the value of n\n");
scanf("%d", &n);
printf("Enter %d values\n", n);
for (int i = 0; i < n; i++)
{
// the space at the beginning of "%[^\n]"
// gets rid of the \n which stays in the input buffer
scanf(" %[^\n]", name); // also there sis no 's' at the end of the "%[^\n]" specifier
printf("name = %s\n", name); // for testing purposes
}
}
But this doesn't actually make much sense because the program is asking for n names, but at each run of the for loop the previous name will be overwritten with the new name.
Also be aware that scanf("%[^\n]", name); is problematic because if the user types more than 99 characters you'll get a buffer overflow.

Write a program in C to read and print the names of n students of a class

I know this seems a very easy problem but till I am not getting the required output. Please correct any mistakes on asking the question as i am posting question on this site for the first time.
The code I tried is as follows:
#include<stdio.h>
int main()
{
int i, n;
char name[20][80];
printf("\nEnter the number of students: ");
scanf("%d", &n);
printf("\nEnter the name of the students: ");
for(i=0; i<n; i++)
{
fgets(name[i], 80, stdin);
}
printf("\nThe name of the students are: \n");
for(i=0; i<n; i++)
{
puts(name[i]);
}
return 0;
}
But the output is like:
Enter the number of students: 3
Enter the name of students: Park Jimin
Jeon Jungkook
The name of the students are:
Park Jimin
Jeon Jungkook
I can't understand why the number of students became 2 though I mentioned 3.
Please help.
Don't use the scanf family of functions - in my experience they cause more problems than they solve. In this case the issue is that scanf leaves the newline (\n) character in the buffer after you entered the number of students, so a blank line was read the first time your program tried to get a student name. The following should solve your homework problem successfully:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int i, n;
char buf[20];
char name[20][80];
printf("Enter the number of students: ");
fgets(buf, sizeof(buf), stdin);
n = atoi(buf);
for(i=0; i<n; i++)
{
printf("Enter student name #%d: ", i+1);
fgets(name[i], 80, stdin);
name[i][strlen(name[i])-1] = '\0'; /* overwrite the trailing \n */
}
printf("\nThe names of the students are:\n");
for(i=0; i<n; i++)
printf("name[%d] = \"%s\"\n", i, name[i]);
return 0;
}
OnlineGDB test here
Instead of using fgets and puts use scanf and printf as shown in below code. Below code is working I checked it. You can change it as you want show like with carriage return etc.
int i, n;
char name[20][80];
printf("\nEnter the number of students: ");
scanf("%d", &n);
printf("\nEnter the name of the students: ");
for(i=0; i<n; i++)
{
//fgets(name[i], 80, stdin);
scanf("%s",name[i]);
printf("%d",i);
}
printf("\nThe name of the students are: \n");
for(i=0; i<n; i++)
{
//puts(name[i]);
printf("%d%s",i,name[i]);
}
return 0;
From my pov, the issue here is an unexpected newline character in the input buffer. While this behaviour is known, there are two different approaches to resolve this.
1. Sanitize your inputs:
Simply reading data and working on this data is often a bad idea. Therefore you may want to check, if the data you just got makes sense and is within your expectation. In your example you should never accept an empty name, no matter if comes from buffer artifacts or real user input.
int j = 0;
while(j<n)
{
printf("Write to index: %d", j);
fgets(name[j], 80, stdin);
if (name[j][0] != '\n')
{
j++;
}
}
https://onlinegdb.com/Hy5ZDWq0U
Restructuring your input loop to something like this already gets rid of empty entries. Yet it is not even close to a fully sanitized input as there are numbers, printable and non-printable special characters and length limitations to consider.
The printf("Write to index: %d", j) easily shows you, that the evil newline is still there, but due to our input check it is overridden within the next loop execution. The output loop can remain unchanged and will not print any empty entries anymore.
2. Try to clear the buffer:
Another approach is to clear the buffer in order to get known preconditions before calling fgets or similar functions. Within Using fflush(stdin) you can find a nice discussion on how this can go wrong and why it is rather brittle to do so.
Personally I would always prefer the first over the second solution, as your code should be responsible to handle unexpected inputs according to its needs. Relying on others easily goes wrong, if they do not exactly know, what your expectations are.

Having problems with 2D char arrays

So I've got an assignment where my program asks the brand (10 letters), model (10 letters), age (1986 - 2019) and cost (positive real number) of 10 cars and then wants the program to check which car is the oldest and to print out it's brand and model. I don't have a problem with the first part but with the second part.
The code is:
//First part
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define C 10
#define M 11
int main(void)
{
char brand[C][M];
char model[C][M];
int year[C];
float cost[C];
int i, len1, len2, min;
for(i=0; i<C; i++){
printf("Car %d\n", i+1);
do{
printf("Brand: ");
scanf("%s", brand[i]);
len1 = strlen(brand[i]);
} while(len1<0 || len1>10);
do{
printf("Model: ");
scanf("%s", model[i]);
len2 = strlen(model[i]);
} while(len2<0 || len2>10);
do{
printf("Year: ");
scanf("%d", &year[i]);
} while(year[i]<1986 || year[i]>2019);
do{
printf("Cost: ");
scanf("%d", &cost[i]);
} while(cost[i]<=0);
}
//Second part
year[0] = min;
for(i=0; i<10; i++)
if(year[i] < min){
min = year[i];
printf("\nThe oldest car is %s %s\n", brand[i], model[i]);
}
For some reason it either prints out gibberish in the place of brand[i] or if I lose the columns of the if statement prints out all the car brands and their models, where I only want the oldest one.
Aside from scanf not being recommended there are some problems with this code, first when you read the brand and model you do:
do{
printf("Brand: ");
scanf("%s", brand[i]);
len1 = strlen(brand[i]);
} while(len1<0 || len1>10);
The problem here is that you first write the string to brand[i] and then check if it's too long, but you have already written it into the array so if the string is longer than your space you already have a buffer overflow. Limit the size you can read with scanf using scanf("%10s, brand[i]) or better yet use fgets(brand[i], sizeof(brand[i]), stdin).
Next in the second part you use min without initializing it, and you overwrite the content of year[0] with it. You probably wanted something like:
min = 2020; // or a number that will be bigger than all your cars anyway
int older = 0;
i = 0;
for(i=0; i<C; i++){ // Use C here, you have it might as well use it instead of magic numbers
if(year[i] < min){
older = i;
min = year[i];
}
}
printf("\nThe oldest car is %s %s\n", brand[older], model[older]);
but bare in mind that this solution will print multiple cars if they are the oldest ones and have the same year

C: Array of Structs (Input into int array within array of structs)

Hi I have to create a database that stores students number, name and also stores an array of course marks (1-N) in C Programming Language.
Everything worked until I started coding for the array of course marks. Then every time I compiled the code it kept crashing as soon as it asked to input the course marks.
Can you please tell me where I'm going wrong in my programming for this task? I have attached it to this message.
The program worked for inputting the name, student number, however I could not get the program to input array of marks. I have asked how many course marks to be entered and then used a for loop within the "void insert(void)" function to keep inputting the course marks into the array *marks. I am referring specifically to lines 24 to 30 in my programming code.
Always at this point the program kept crashing and I could not proceed further to enter more names or print the stored student details.
I think there is a problem with this part:
for (i= 0; i < num_marks; i++)
{
printf("Enter Course Mark: \n");
scanf("%d", &(list[num_students].marks[num_marks]));
}
Anyway here is the full code:
#include <stdio.h>
#include <string.h>
struct student{
int number;
char name[10];
int marks[5];
};
struct student list[10];
int num_students = 0;
int num_marks = 0;
int *p;
void insert(void)
{
int student_number;
int i;
printf("Enter number: \n");
scanf("%d", &list[num_students].number);
printf("Enter NAME: \n");
scanf("%s", &list[num_students].name);
printf("Enter NO of courses: \n");
scanf("%d", num_marks);
for (i= 0; i < num_marks; i++)
{
printf("Enter Course Mark: \n" );
scanf("%d", &(list[num_students].marks[num_marks]));
}
num_students++; // HOW DO WE INPUT ARRAY MARKS??? MARK1: , MARK2: , MARK3 ,
}
void printtest(void)
{
int i;
for (i=0; i < num_students; i++)
{
printf("Name: \n");
puts(list[i].name);
printf("Number: %d \n", list[i].number);
printf("Mark: %d /100 \n", list[i].marks);
printf("\n");
}
}
int main(void)
{
int code;
int opt1;
int courses, i, k, j, counter;
for (;;){
printf("Enter operation code: \n");
printf("(1) ADD NEW STUDENT DETAILS: \n");
printf("(2) DISPLAY REPORT OF ALL STUDENTS: \n");
scanf(" %d", &code);
switch (code){
case 1 :
insert();
break;
case 2 :
printtest();
break;
default:
printf("Illegal code\n");
printf("\n");
}
}
}
Apart from what others pointed out, I'd like to draw your attention towards the following:
void insert(void)
{
int student_number;
int i;
printf("Enter number: \n");
scanf("%d", &list[num_students].number);
printf("Enter NAME: \n");
scanf("%s", &list[num_students].name);
printf("Enter NO of courses: \n");
scanf("%d", num_marks);
for (i= 0; i < num_marks; i++)
{
printf("Enter Course Mark: \n" );
scanf("%d", &(list[num_students].marks[num_marks]));
}
num_students++;
}
void printtest(void)
{
int i;
for (i=0; i < num_students; i++)
{
printf("Name: \n");
puts(list[i].name);
printf("Number: %d \n", list[i].number);
printf("Mark: %d /100 \n", list[i].marks);
printf("\n");
}
}
There are three problematic statements:
scanf("%s", &list[num_students].name); This is why beginners should use compilers with all warnings enabled.
printf("Mark: %d /100 \n", list[i].marks); What did you declare marks as in the first place?
scanf("%d", num_marks); Seems like you put & operator where not needed and ignore where needed. Read your textbook before asking a question next time.
Seems like you're having a tough time understanding the concept of arrays and pointers. Read your text book thoroughly before venturing into the world of pointers. If you don't use them correctly, even compiler can't help you.
Also, even if I don't expect your program to have a robust input mechanism, at least array bounds checking is expected. Learn good habits from the beginning. They'll save a lot of your time while debugging later.
Seems to be an error in:
for (i= 0; i < num_marks; i++)
{
printf("Enter Course Mark: \n" );
scanf("%d", &(list[num_students].marks[num_marks]));
}
The crash is probably because num_marks as index indexes beyond the array. Change to:
for (i= 0; i < num_marks; i++)
{
printf("Enter Course Mark: \n" );
scanf("%d", &(list[num_students].marks[i]));
}

How to get multiple inputs in one line in C?

I know that I can use
scanf("%d %d %d",&a,&b,&c):
But what if the user first determines how many input there'd be in the line?
You are reading the number of inputs and then repeatedly (in a loop) read each input, eg:
#include <stdio.h>
#include <stdlib.h>
int main(int ac, char **av)
{
int numInputs;
int *input;
printf("Total number of inputs: ");
scanf("%d", &numInputs);
input = malloc(numInputs * sizeof(int));
for (int i=0; i < numInputs; i++)
{
printf("Input #%d: ", i+1);
scanf("%d", &input[i]);
}
// Do Stuff, for example print them:
for (int i=0; i < numInputs; i++)
{
printf("Input #%d = %d\n", i+1, input[i]);
}
free(input);
}
Read in the whole line, then use a loop to parse out what you need.
To get you started:
1) Here is the manual page for getline(3):
http://man7.org/linux/man-pages/man3/getline.3.html
2) Some alternatves to getline:
How to read a line from the console in C?
3) Consider compressing spaces:
How do I replace multiple spaces with a single space?
4) Use a loop for parsing. You might consider tokenizing:
Tokenizing strings in C
5) Be careful and remember that your user could enter anything.
#include <conio.h>
#include <stdio.h>
main()
{
int a[100],i,n_input,inputs;
printf("Enter the number of inputs");
scanf("%d",&n_input);
for(i=0;i<n_input;i++)
{
printf("Input #%d: ",i+1);
scanf("%d",&a[i]);
}
for(i=0;i<n_input;i++)
{
printf("\nInput #%d: %d ",i+1,a[i]);
}
}
/*
_______________This program is in C Programming Language_______________
We have to directly enter all the elements in one line giving spaces between them. Compiler will automatically ends the for loop I have used and assign the value to their respective variables or array indexes. Below program and output will give you better understanding.
*/
#include <stdio.h>
int main()
{
//taking no of inputs from user
int len;
printf("Enter the number of inputs you want to enter : ");
scanf("%d", &len);
int i;
//defined an array for storing multiple outputs
int arr[100];
//included a printf statement for better understanding of end user
printf("Enter the inputs here by giving space after each input : ");
/*here is the important lines of codess for taking multiple inputs on one line*/
for (i=0;i<len;i++)
{
scanf("%d", &arr[i]);
}
printf("Your entered elements is : ");
for (i=0;i<len;i++)
{
printf("%d ", arr[i]);
}
}
/*
OUTPUT :
Enter the number of inputs you want to enter : 5
5 5 5 8 7
Your entered elements is : 5 5 5 8 7
*/

Resources