How to read string in structure with space? [duplicate] - c

This question already has answers here:
Reading string from input with space character? [duplicate]
(13 answers)
Closed 5 years ago.
Our corporation office requires an application which will maintain all registered Universities in Chennai and that application should be user friendly in terms of searching a University. Create a structure called “University” with the following attributes: name, license number and area code.
Requirement: License number for a university should be 6 digits and the first 2 digits must be alphabets of Upper case letters and last 4 digits must be number.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct University
{
char name[100];
char license[10];
int area;
}u[10];
void main()
{
int i, n, r, k = 0, flag = 1, f2 = 1, j, search = 0;
char s[100];
printf("Enter the number of records\n");
scanf("%d", &n);
printf("Enter the details of %d universities\n", n);
for (i = 0; i<n; i++)
{
printf("Name of the University\n");
getchar();
scanf("%s", u[i].name);
j = strlen(u[i].name);
if (j <= 1)
{
f2 = 0;
break;
}
printf("License Number\n");
scanf("%s", u[i].license);
k = strlen(u[i].license);
if (k<1)
{
f2 = 0;
break;
}
if (k<6)
{
flag = 0;
}
else if ((u[i].license[0] >= 'A' && u[i].license[0] <= 'Z') && (u[i].license[1] >= 'A' && u[i].license[1] <= 'Z') && (u[i].license[2] >= '0' && u[i].license[2] <= '9') && (u[i].license[3] >= '0' && u[i].license[3] <= '9') && (u[i].license[4] >= '0' && u[i].license[4] <= '9') && (u[i].license[5] >= '0' && u[i].license[5] <= '9') && k == 6)
{
flag = 1;
}
else
{
flag = 0;
}
printf("Area Code\n");
scanf("%d", &u[i].area);
//printf("%d",u[i].area);
if (u[i].area <= 0)
{
f2 = 0;
}
}
if (flag == 0)
{
printf("Sorry! You have entered incorrect license number.");
}
else if (f2 == 0)
{
printf("Unable to continue");
}
else
{
printf("Enter the name of the University to be searched\n");
scanf("%s", s);
for (i = 0; i<n; i++)
{
if ((strcmp(u[i].name, s)) == 0)
{
search = 1;
}
}
if (search == 1)
{
printf("University is licensed one.");
}
else
{
printf("University is not found.");
}
}
}
when I give number of university as 3, then it did not take input for the 3rd university.
Test Case
Input 1
Enter the number of records
3
Enter the details of 3 universities
Name of the University
SRM
License Number
SR1234
Area Code
28
Name of the University
University of Madras
License Number
SP0904
Area Code
18
Name of the University
Bharath University
License Number
BU0101
Area Code
35
Enter the name of the University to be searched
SRM
Output 1
University is licensed one.

Seems like you are interested in just reading a c-string containing a space. To do that you can use fgets. Here is a toy program:
#include <stdio.h>
#include <string.h>
struct s {
char name[100];
int something;
};
int main(void)
{
struct s myStruct;
printf("%s", "Enter name: ");
fgets(myStruct.name, 100, stdin);
myStruct.name[strlen(myStruct.name) - 1] = '\0'; //This should remove the newline char at the end
printf("Name is: %s", myStruct.name);
}

Related

C Program not ending after inputting string?

I am completing a programming exercise and when my program is run, it never executes anything past the input line and never terminates. No errors or warnings are coming up so I'm not sure what is wrong. Any help would be great.
This is the assignment:
Write a function that asks the user to input a telephone number as a string containing a threedigit area code, followed by a seven-digit number. Any other characters will be ignored, and only
the first 10 digits will be considered. Assume that the string has at most 200characters.
If the user does not provide at least 10 digits, an error message should be printed out.
It should report the telephone number in the format (123) 456-7890. Note that the user may
choose any input format, yet the program should maintain a consistent output format.
The function should be called phone_fmt. Your executable will be called phone. The function
and main should be in the files phone_fmt.c, phone_fmt.h and phone.c, respectively.
This is my code for phone.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "phone_fmt.h"
int main(){
char numStr[200];
char phoneNum[14];
int i=0;
printf("Enter phone number string up to 200 characters: \n ");
scanf("%s", numStr);
if(strlen(numStr)<10){
printf("Invalid. Entry must be at least 10 characters.\n");
exit(1);
}
while(numStr[i] != '\0' && i<10){
if(numStr[i]>'0' && numStr[i]<'9')
break;
i++;
}
if(i > 10){
printf("Invalid. Not enough digits to complete phone number.\n");
exit(1);
}
phone_fmt(numStr, phoneNum);
printf("Phone number: %s \n", phoneNum);
return 0;
}
code for phone_fmt.c
#include "phone_fmt.h"
void phone_fmt(char *numStr, char *phoneNum){
int i=0;
int j=0;
int c=0;
while(numStr[i] != '\0' && c < 10){
if(j==0){
phoneNum[j]='(';
j++;
}
else if(j==4){
phoneNum[j]=')';
j++;
}
else if(j==8){
phoneNum[j]='-';
j++;
}
if(numStr[i] >= '0' && numStr[i] <= '9'){
phoneNum[j]=numStr[i];
j++;
}
}
}
code for phone_fmt.h
#include<stdio.h>
void phone_fmt(char *numStr, char *phoneNum);
Any help would be GREATLY appreciated.
Based on your logic, you need to create a char or int array to hold your 10 phone digit number as your first parameter in phone_fmt() function. The worked code is following.
#include <stdio.h>
void phone_fmt(int *digits, char *phoneNum){
sprintf(phoneNum, "(%d%d%d) %d%d%d-%d%d%d%d", digits[0],
digits[1],
digits[2],
digits[3],
digits[4],
digits[5],
digits[6],
digits[7],
digits[8],
digits[9]);
}
int main(){
char output[20];
int digits[10];
char c;
int i = 0, j = 0;
printf("Enter phone number string up to 200 characters: \n ");
while( (c = getchar()) != '\n' && i < 10 ){
if( (c >= '0' && c <= '9') ){
digits[i++] = (int)(c - '0');
}
++j;
}
if( j < 10 || j > 200 ){
printf("Invalid. Entry must be at least 10 characters and less then 200 characters.\n");
return -1;
}
if(i < 10){
printf("Invalid. Not enough digits to complete phone number.\n");
return -1;
}
phone_fmt(digits, output);
printf("Phone number: %s \n", output);
return 0;
}

Vigenere's cipher in C several problems

I have made program which encrypts and decrypts Vigenere's cipher but I have several problems.
Here is one: First letter of sentence is encrypted incorrectly.
Second one: After sentence I have letter K. I think that's because of space but I don't know how to fix it.
And third problem: There are no spaces in encrypted sentence I know ages ago when Vigenere's cipher was used there were no spaces but I would like to have groups of 5 letters if that's possible.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
int main(int argc, char **argv) {
char message[100];
int choice;
int i, j;
char pass[33];
int value;
char repeat = 1;
while (repeat == 1) {
printf("Enter operation\n");
printf("Encrypt - 1 \n");
printf("Decrypt - 2\n");
scanf("%d", &choice);
if (choice == 1) {
printf("Please enter message to encrypt\n");
while (getchar() != '\n');
fgets(message, 100, stdin);
printf("Enter password\n");
scanf("%s", &pass);
for (i = 0, j = 0; i < strlen(message); i++, j++) {
if (message[i] == ' ')
continue;
if (j >= strlen(pass)) {
j = 0;
}
if (!isupper(message[i])) {
value = (((message[i]) - 97) + ((pass[j]) - 97));
}
if (!islower(message[i])) {
value = (((message[i]) - 65) + ((pass[j]) - 65));
}
printf("%c", 97 + (value % 26));
}
printf("\nWould you like to repeat? [1/0]\n");
scanf("%d", &repeat);
} else
if (choice == 2) {
printf("Enter message do decrypt\n");
while (getchar() != '\n');
fgets(message, 100, stdin);
printf("Zadejte heslo\n");
scanf("%s", &pass);
for (i = 0, j = 0; i < strlen(message); i++, j++) {
if (message[i] == ' ')
continue;
if (j >= strlen(pass)) {
j = 0;
}
if (!isupper(message[i])) {
value = (((message[i]) - 96) - ((pass[j]) - 96));
}
if (!islower(message[i])) {
value = (((message[i]) - 64) - ((pass[j]) - 64));
}
if (value < 0) {
value = value * -1;
}
printf("%c", 97 + (value % 26));
}
printf("\nWould you like to repeat? [1/0]\n");
scanf("%d", &repeat);
}
}
return (EXIT_SUCCESS);
}
[
The main problem in your code is you apply the translation to characters with incorrect tests: you should translate uppercase letters is you have indeed an uppercase letter, not if you don't have a lowercase character. As coded, non letters are translated twice.
Change the code to:
if (islower((unsigned char)message[i])) {
value = (((message[i]) - 'a') + ((pass[j]) - 'a'));
}
if (isupper((unsigned char)message[i])) {
value = (((message[i]) - 'A') + ((pass[j]) - 'a'));
}
Also make sure you use character constants instead of hard-coded ASCII values and make the password lowercase.
In the deciphering case, the offsets seem incorrect. You should be using 'A' and 'a' too.
First things first, the message corruption. If you add a few printf() statements in the loop that is doing the encryption, you should be able to get an idea what is going wrong. You can always comment them out, or remove them altogether, anytime later.
That K on the end could be the encrypted \n that would have been read in with the message.
To display the encrypted message in groups of five characters, keep a count of how many characters you have actually displayed (make sure the instruction to increase the count is located where it will get skipped if the character is not displayed); and when this reaches 5, display a space and reset the counter to zero.

Verifying integer input in a union in C

I'm trying to verify that what a user inputs in to one section of a union is actually an integer. I have been trying to use the isdigit function (see below) but I am having no success. All I need to do is make sure the user enters ONLY numbers for the date, but I am having a lot of trouble with it.
My code:
#define STRSIZE 30
#define PROFSIZE 30
#define NBRASSI 2
#define TRUE 1
#define FALSE 0
struct assignment
{
char name[STRSIZE];
char prof[PROFSIZE];
int duedate;
float value;
};
.
.
.
struct assignment populate_structure(struct assignment assi[], int assi_nbr)
{
int count;
int date_check = FALSE;
for (count = 0; count < assi_nbr; count++)
{
flushall();
printf("Enter Assignment #%d name (max %d chars):\n", count + 1,
STRSIZE);
gets(assi[count].name);
while (date_check == FALSE)
{
printf("Enter due date for Assignment #%d (YYYYMMDD):\n",
count + 1);
scanf("%d", &assi[count].duedate);
if (isdigit(assi[count].duedate))
{
date_check = TRUE;
}
else
{
printf("Invalid");
date_check = FALSE;
}
}
printf("Enter %% of final grade for Assignment #%d:\n", count + 1);
scanf("%f", &assi[count].value);
flushall();
printf("Enter Professor's name for Assignment #%d (max %d chars):\n",
count + 1, PROFSIZE);
gets(assi[count].prof);
printf("\n\n");
}
return assi[count];
}
It gives me no errors in Visual Studio, but when I run the program I get an Abort error whenever ANY value is input for assi[].duedate
If I remove if (isdigit(assi[count].duedate)), the program runs fine (so long as they only input an integer for duedate). Any help is greatly appreciated.
As the commenters already noted: isdigit() is for single characters only. Also: the way you use scanf() already assures the result to be a number.
But you should read a string instead, it is easier to test. For example
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
int c;
int position = 0;
int res;
char date[9] = {'\0'};
char input[20] = {'\0'};
puts("try if date is in the format \"YYYYMMDD\"");
res = scanf("%19s",input);
if(res != 1){
fprintf(stderr,"input was a mess, aborting\n");
goto __FAILURE;
}
c = input[position];
while(c != '\0'){
switch(position){
case 0:
if( c == '2' || c == '1' ){
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 1:
if( c == '9' || c == '0' ){
// check valid digit by looking back here
// (not implemented)
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 2:
if( isdigit(c) ){
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 3:
if( isdigit(c) ){
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 4: // month
if( c == '0' || c == '1' ){
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 5: // month
if( isdigit(c) ){
// check valid digit by looking back here
// (not implemented)
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 6: // day
if( c == '0' || c == '1' || c == '2' || c == '3'){
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 7: // day
if( isdigit(c)){
// check valid digit by looking back here
// (not implemented)
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
default:
break;
}
c = input[++position];
}
printf("Date was correct and is %s\n",date);
exit(EXIT_SUCCESS);
__FAILURE:
printf("Date was wrong at position %d with character %c or just too short/long\n",position,c);
exit(EXIT_FAILURE);
}
Fill out the rest (check if date is valid and in the correct range). You could also part the date into individual year/month/day sections instead of putting the string into another string and convert them into numbers via atoi ( you can use atoi `because you already made sure to have a valid number) or by converting manually inside the switch without extra variables and functions. Checking ranges arithmetically is simpler than comparing strings/characters.
Here is my offering - any invalid entry calls exit(1) though a better error handler would be preferred. The data is entered as a string, and then extracted and validated.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct {
int year;
int month;
int day;
} mydate_t;
int main(void){
int i;
mydate_t dat = {0};
int dayspermon[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
char str[12];
printf("Enter a date (YYYYMMDD): ");
fflush(stdout);
if(fgets(str, sizeof str, stdin) == NULL) {
exit(1);
}
for(i=0; i<8; i++) {
if(!isdigit(str[i])) {
exit(1); // also fails when the string is too short
}
}
// extract
for(i=0; i<4; i++) {
dat.year = dat.year * 10 + str[i] - '0';
}
for(i=4; i<6; i++) {
dat.month = dat.month * 10 + str[i] - '0';
}
for(i=6; i<8; i++) {
dat.day = dat.day * 10 + str[i] - '0';
}
// validate
if(dat.year < 2000 || dat.year > 3000) // arbitrary range
exit(1);
if(dat.year % 4 == 0 && (dat.year % 100 != 0 || dat.year % 400 == 0)) {
dayspermon[1]++; // leap year adjustment
}
if(dat.month < 1 || dat.month > 12)
exit(1);
if(dat.day < 1 || dat.day > dayspermon[dat.month - 1])
exit(1);
printf("Date: %04d %02d %02d\n", dat.year, dat.month, dat.day);
}

C Basics : Grade Book Using Array Storing and Printing, Plus Looping

Yes, hello. I'm really new to programming. I genuinely need help because I would like to both understand what I'm doing wrong and also pass my class.
I'm in a Intro to Programming class and my assignment is to create a program that uses an array to store percentage grades in the range from 0 to 100 (inclusive). The program should allow the user to indicate when they are done entering grades. When the user is done entering grades, the program should print out the grades entered.
I have a running code, compiled in Code::Blocks. But my questions/problems are:
A.) What's the best way to tell C when the user is done? Should I
Leave the code as is and let any key be hit?
Add a specific variable like 'done'?
Do something else?
B.) How do I print only the grades that have been entered without it going through all 100 slots? I can't for the life of me find the solution.
Any and all suggestions welcome and appreciated!!!
int i = 0;
float percentScore[100];
for (i = 0; i < 10; i++) {
printf("Grade %d: ", i + 1);
scanf("%f", &percentScore[i]);
}
for (i = 0; i < 10; i++) {
printf("\n%.2f%%", percentScore[i]);
}
return 0;
Your choices for A) are not mutually exclusive; the first is something the user can do, the second is a way to represent that in the code. As such, you could reasonably do both.
As for B), you need a way to represent the number of grades entered (hint: a variable); this can then be used to control how many get printed.
Here is a simple approach for your problem:
for each input, read a full line from the user ;
try and convert this line as a number with sscanf() ;
if the conversion fails, consider the input exhausted ;
if the value is out of bounds, restart this input.
The user can thus signal the end of the list by entering a blank line.
Here is a example:
#include <stdio.h>
#define GRADE_NB 100
int main(void) {
int i, n;
float grade, percentScore[GRADE_NB];
char buf[100];
for (n = 0; n < GRADE_NB;) {
printf("Grade %d: ", n + 1);
if (!fgets(buf, sizeof buf, stdin)) {
/* end of file reached: input exhausted */
break;
}
if (sscanf(buf, "%f", &grade) != 1) {
/* not a number: input exhausted */
break;
}
if (grade >= 0 && grade <= 100) {
/* value is OK, grade accepted */
percentScore[n] = grade;
n++;
} else {
printf("Invalid grade: %f\n", grade);
}
}
for (i = 0; i < n; i++) {
printf("%.2f%%\n", percentScore[i]);
}
return 0;
}
If the potential number of inputs is not limited, you must allocate the array from the heap and reallocate it as more inputs are gathered. Here is a simple solution for this where the array is reallocated for each input:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i, n;
float grade, *percentScore;
char buf[100];
for (n = 0, percentScore = NULL;;) {
printf("Grade %d: ", n + 1);
if (!fgets(buf, sizeof buf, stdin)) {
/* end of file reached: input exhausted */
break;
}
if (sscanf(buf, "%f", &grade) != 1) {
/* not a number: input exhausted */
break;
}
if (grade >= 0 && grade <= 100) {
/* value is OK, grade accepted */
percentScore = realloc(percentScore, (n + 1) * sizeof(*percentScore));
if (percentScore == NULL) {
printf("allocation failed\n");
return 1;
}
percentScore[n] = grade;
n++;
} else {
printf("Invalid grade: %f\n", grade);
}
}
for (i = 0; i < n; i++) {
printf("%.2f%%\n", percentScore[i]);
}
free(percentScore);
return 0;
}

Why does my if statement create an infinite loop?

The code works for every if statement except for the first one where if the statement is true, it proceeds to create an infinite loop of "Enter a student mark [0.00, 100,00] : " and "No input accepted!".
#include <stdio.h>
#define MIN 0
#define MAX 100
int getMark(void) {
int mark;
char ch;
int repeat = 1;
printf("Enter a student mark [0, 100] : ");
int r = scanf("%i%c", &mark, &ch);
if (r == 0) {
printf("**No input accepted!**\n");
}
else if (ch != '\n') {
printf("**Trailing characters!**\n");
}
else if (mark < MIN || mark > MAX) {
printf("**Out of range!**\n");
}
return mark;
}
int main() {
int mark;
do {
mark = getMark();
} while (mark != 0);
}
What's causing it to loop and how do I fix it?
1) If you input a string or just a char value you must remove it from your input stream before using it.
#include <stdio.h>
#define MIN 0
#define MAX 100
int getMark(void) //Funtion for marks input
{
int mark;
char ch;
//int repeat = 1;
char c;
printf("Enter a student mark [0.00, 100,00] : ");
int r = scanf("%d %c", &mark, &ch);
if (r == 0) //Input begins with a letter
{
printf("**No input accepted!**\n");
}
else if(ch == '\n') //Input ends with a letter
{
printf("**Trailing characters!**\n");
}
else if( mark < MIN || mark > MAX) //Range
{
printf("**Out of range!**\n");
}
//Remove the previous string from the input stream
while ( (c = getchar()) != '\n' && c != EOF );
return mark;
}
int main()
{
int mark;
do
{
mark = getMark();
}while (mark != 0);
return 0;
}
Output
Enter a student mark [0.00, 100,00] : -10 c
**Out of range!**
Enter a student mark [0.00, 100,00] : 101 b
**Out of range!**
Enter a student mark [0.00, 100,00] : 50 a
Enter a student mark [0.00, 100,00] : abcd
**No input accepted!**
Enter a student mark [0.00, 100,00] : 0 q
The problem is that with no input accepted the variable mark will be uninitialized and might be something else that 0. Your while loop will then continue forever without updating mark.

Resources