How do you ask the User multiple questions in C? - c

I am new to "C programming" and I have Googled for my answer, but I can't seem to get what I am looking for. I am making a simple 2 question program. The code is listed below:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char characterName[] = "Mike";
int age = 0;
printf("Enter your age, %s.\n", characterName);
scanf("%d", &age);
printf("Your being %d is old older than me and my brother "
"which was the first computer.Hahaaa.... \n", age);
return 0;
}
This is the next question:
char str[50];
{
printf("Anything to say about my comment? \n");
scanf ("%[^\n]", str);
printf("That was a good answer. I wasn't expecting that from you.\n");
return 0;
}

How about a function to ask a question, and return a response?
#include <stdio.h>
/*
* Prompt the user with the given question, return their
* input in answer, up to max_answer_length bytes
* returns 1 for ok, 0 on error.
*/
int askQuestion(const char *question, char *answer, const size_t max_answer_length)
{
int input_ok = 1;
// Show the user the question
printf( "%s: ", question );
// Throw away any existing input in the user's input-queue
// (like if they answered with a really-long string previously)
fflush(stdin);
// Read a line of input from the user into <answer>, but not more
// than <max_answer_length>-1 bytes are accepted (see fgets() for details)
// If the fgets() returns EOF or an error, make sure we remember it
if ( fgets( answer, max_answer_length, stdin ) == NULL )
input_ok = 0;
// return whether there was an error on input
return input_ok;
}
int main(void)
{
char answer_buffer[200];
askQuestion( "What is your favourite fruit?", answer_buffer, sizeof(answer_buffer) );
printf( ">> %s\n", answer_buffer );
askQuestion( "How long have you been programming C?", answer_buffer, sizeof(answer_buffer) );
printf( ">> %s\n", answer_buffer );
return 0;
}

Related

Counting Number Of User Input in C Program

printf("Enter number of patients:");
int numberOfInputs = scanf("%d", &patients);
if (numberOfInputs != 1) {
printf("ERROR: Wrong number of arguments. Please enter one argument d.\n");
}
I am asking the user to input one number as an argument, but would like to print out a statement if the user does not input anything or puts in more than one input. For example, once prompted with "Enter number of patients:", if the user hits enter without entering anything, I would like to print out a statement. The code above is what I have been specifically tinkering around with it for the past couple hours as a few previous posts on this site have suggested but when I run it in terminal, it does not work. Any suggestions? Thank you in advance, and all advice is greatly appreciated!
If I understand your question right, you want to print an error when the input is anything other than an integer and this includes newline as well. You can do that using a char array and the %[] specifier.
Example:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int patients;
char str[10];
printf("Enter number of patients:");
int numberOfInputs = scanf("%[0-9]", str);
if (numberOfInputs != 1) {
printf("ERROR: Wrong number of arguments. Please enter one argument.\n");
}
patients = atoi(str); //This is needed to convert the `str` back to an integer
}
This will print the error when the user just hits ENTER as well.
This looks super over-complicated, but it basically splits the input, checks it to be exactly one and than checks it to be an integer (and converts it). It works fine in loop as well and handles empty input.
I'm sure there are more elegant solutions to this problem, it's just a suggestion.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
int getNumberOfInput(char* str);
bool isNumber(char* str);
int main()
{
char str[512];
while(1)
{
printf("Enter text: ");
fgets(str, 512, stdin);
int numberOfInput = getNumberOfInput(str);
if ( numberOfInput == 0 )
printf("You must give an input\n");
else if ( numberOfInput > 1 )
printf("You have to give exactly one input\n");
else
{
if (!isNumber(str))
printf("The input is not an integer\n");
else
{
int input = atoi(str);
printf("input: %d\n", input);
}
}
}
return 0;
}
int getNumberOfInput(char* str)
{
char* word = strtok(str, " \t\n\v\f\r");
int counter = 0;
while(word != NULL)
{
++counter;
word = strtok(NULL, " \t\n\v\f\r");
}
return counter;
}
bool isNumber(char* str)
{
int i, len = strlen(str);
for (i=0; i<len; ++i)
if (!isdigit(str[i]))
return false;
return true;
}

Storing user input whilst still asking questions

Firstly, i know the source code below is long and you're not really supposed to post code like this, but i really don't understand why it's not working or how i could explain my issue without posting it like this.
Im trying to store the answer to each of the questions asked in it and display them at the end of the script. The biggest problem im having is that i get the error
"subscripted value is neither array nor pointer nor vector scanf("%s", a[i].incdest);"
The program doesn't accept a[i].incdest. it does this for all of the array values.
it is also saying that in function main variable "comp1" is undeclared.
#include<stdio.h>
#include<string.h>
int c_s(char*, char*);
typedef struct
{
char constab[30];
char vicwit[15];
char witdet[200];
char incdest[300];
char comp1[15];
char comp2[200];;
} sheetstore;
#define ARRAYLEN 2
sheetstore a[ARRAYLEN];
FILE *fp;
int main()
{
int i, a;
char wit[10] = "witness";
char yes[10] = "yes";
char comp1[10];
fp = fopen("sheetstore.dat","a+");
printf("Hate crime reporting system\n\n\n");
printf("If the crime you are reporting is an emergency,\nplease call 999, do not proceed any further with this form\n\n\n\nPlease press enter to confirm you have read the above and continue\n");
char enter = 0;
while (enter != '\r' && enter != '\n') { enter = getchar(); }
for( i=0; i<ARRAYLEN ; i++)
{
printf("Which police constabulary did the offence take place in?\n\n");
scanf("%s", a[i].constab);
printf("Are you a victim or witness of the crime?\nPlease answer victim/witness\n\n");
scanf("%s", a[i].comp1);
int res1 = (strcmp (comp1, wit));
if(res1 == 0){
printf("Please enter the details including phone number and address of any other witnesses that were present\n");
}
scanf("%s", a[i].witdet);
else{
printf("Where did the incident take place?\nIf in a house please provide the full address including postcode\n");
scanf("%s", a[i].incdest);
}
fwrite(&a[i], sizeof(a), 1, fp);
}
fclose(fp);
fopen("sheetstore.dat", "r");
for(i=0; i<ARRAYLEN; i++)
{
fread(&a[i], sizeof(a), 1, fp );
printf("Which police constabulary did the offence take place in? : %s\n", a[i].constab);
printf("Are you a victim or witness of the crime? : %s\n", a[i].comp1);
printf("Please enter the details including phone number and address of any other witnesses that were present : %s\n", a[i].witdet);
printf("Where did the incident take place? : %s\n", a[i].incdest);
}
fclose(fp);
return 0;
}
the main issue that i saw in your code, is that you shadowed the array a (sheetstore a[ARRAYLEN];) by declaring an int with the same name in your main().
you also had a scanf stament mislocated.
i fixed your code and put in a comment for every change - now, i don't persume to check the functionality of your code but at least this will compile and hopefully will give you a better understanding where you were wrong - from here it is up to you:
#include<stdio.h>
#include<string.h>
int c_s(char*, char*);
typedef struct
{
char constab[30];
char vicwit[15];
char witdet[200];
char incdest[300];
char comp1[15];
char comp2[200];;
} sheetstore;
#define ARRAYLEN 2
sheetstore sheetArr[ARRAYLEN]; //change this 'a' to avoid shadowing by the decleration on 'int a' in main
FILE *fp;
int main()
{
int i, a;
char wit[10] = "witness";
char yes[10] = "yes";
char comp1[10];
fp = fopen("sheetstore.dat","a+");
printf("Hate crime reporting system\n\n\n");
printf("If the crime you are reporting is an emergency,\nplease call 999, do not proceed any further with this form\n\n\n\nPlease press enter to confirm you have read the above and continue\n");
char enter = 0;
while (enter != '\r' && enter != '\n') { enter = getchar(); }
for( i=0; i<ARRAYLEN ; i++)
{
printf("Which police constabulary did the offence take place in?\n\n");
scanf("%s", sheetArr[i].constab);//change name from 'a'
printf("Are you a victim or witness of the crime?\nPlease answer victim/witness\n\n");
scanf("%s", sheetArr[i].comp1);//change name from 'a'
int res1 = (strcmp (sheetArr[i].comp1, wit));//compare with the value set in the struct
if(res1 == 0){
printf("Please enter the details including phone number and address of any other witnesses that were present\n");
/*this scanf should be inside the brackets of 'if(res1 == 0)' */
scanf("%s", sheetArr[i].witdet);//change name from 'a'
}
else{
printf("Where did the incident take place?\nIf in a house please provide the full address including postcode\n");
scanf("%s", sheetArr[i].incdest);//change name from 'a'
}
fwrite(&sheetArr[i], sizeof(sheetstore), 1, fp);//write a single struct
}
fclose(fp);
fopen("sheetstore.dat", "r");
for(i=0; i<ARRAYLEN; i++)
{
fread(&sheetArr[i], sizeof(sheetstore), 1, fp );//read a single struct
printf("Which police constabulary did the offence take place in? : %s\n", sheetArr[i].constab);
printf("Are you a victim or witness of the crime? : %s\n", sheetArr[i].comp1);
printf("Please enter the details including phone number and address of any other witnesses that were present : %s\n", sheetArr[i].witdet);
printf("Where did the incident take place? : %s\n", sheetArr[i].incdest);
}
fclose(fp);
return 0;
}
In addition to some useful comments posted above (meaningful variable names, line width not to be too long for readability), in general sense, your problem is due to two thing: in the body of the main function you declare an int a which is used instead of your global array a[ARRAYLEN]. Hence, you cannot refence a[i].incdet etc. Just comment or remove the int a from the main function. Secondly, your scanf("%s", a[i].witdet); should be in the body of the if statement above according to the program logic. I you do these two changes, the code will compile. However if you pass -Wall -Werror to the compiler, it will yields an error like error: unused variable ‘yes’ [-Werror=unused-variable]
char yes[10] = "yes";. Just comment this line to avoid using uncessary memory space on the stack.
The following proposed code:
corrects the first 50+ lines of your code.
Please correct your posted code so it cleanly compiles
for flexibility, separates the definition of the struct from the typedef of the struct
properly checks for error indications from system functions
honors the right margin (usually 72 or 80 characters)
replaces the CPU cycle intensive calls to printf() with calls to puts() when appropriate
This is only a guide for the first 50 lines of the OPs code. It is not a complete code replacement.
and now the proposed code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// prototypes
int c_s(char*, char*);
struct sSheet
{
char constab[30];
char vicwit[15];
char witdet[200];
char incdest[300];
char comp1[15];
char comp2[200];
};
typedef struct sSheet sheetstore;
#define ARRAYLEN 2
sheetstore a[ARRAYLEN];
FILE *fp;
int main( void )
{
int i;
char wit[10] = "witness";
//char yes[10] = "yes";
char comp1[10];
fp = fopen("sheetstore.dat","a+");
if( !fp )
{
perror( "fopen for appending to 'sheetstore.dat' failed" );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
puts("Hate crime reporting system\n\n\n");
puts("If the crime you are reporting is an emergency,\n"
"please call 999, "
" do not proceed any further with this form\n\n\n\n"
"Please press enter"
" to confirm you have read the above and continue\n");
int enter = 0;
while (enter != '\r' && enter != '\n')
{
enter = getchar();
}
for( i=0; i<ARRAYLEN ; i++)
{
puts("Which police constabulary did the offence take place in?\n\n");
if( scanf("%29s", a[i].constab) != 1)
{
fprintf( stderr, "scanf for which police constabulary failed" );
fclose( fp ); // cleanup
exit( EXIT_FAILURE );
}
// implied else, scanf successful

C Program - How to deny any non-numerical input

I've just started learning the language of C, and would love your help in cleaning up / simplifying my code if you know a better way to reach the following.
I want a program to ask for a number, and if that is found then proceed to print and end, however if anything else is put in (e.g. a letter key), then I want the program to loop asking for a number until one is given.
I started off by using a simple scanf input command, but this seemed to go into an infinite loop when I tried to check if a valid number (as we define them) was put in.
So instead I have ended up with this, from playing around / looking online, but I would love to know if there is any more efficient way!
//
// Name & Age Program
// Created by Ben Warren on 1/3/18.
//
#include <stdio.h>
int main (void)
{
//Setting up variables
int num;
char line[10]; /* this is for input */
//Collecting input
printf("Please enter any number? \t");
scanf("%d", &num);
//If Invalid input
while (num==0)
{
printf("\nTry again:\t");
fgets(line, 10, stdin); //turning input into line array
sscanf(line, "%d",&num); //scaning for number inside line and storing it as 'num'
if (num==0) printf("\nThat's not an number!");
}
//If Valid input
{
printf("\n%d is nice number, thank you! \n\n", num);
*}*
return 0;
}
Instead of checking if the value is different to 0, check the return value of
sscanf. It returns the number of conversions it made. In your case it should be 1. Unless the return value is 1, keep asking for a number.
#include <stdio.h>
int main(void)
{
int ret, num;
char line[1024];
do {
printf("Enter a number: ");
fflush(stdout);
if(fgets(line, sizeof line, stdin) == NULL)
{
fprintf(stderr, "Cannot read from stdin anymore\n");
return 1;
}
ret = sscanf(line, "%d", &num);
if(ret != 1)
fprintf(stderr, "That was not a number! Try again.\n");
} while(ret != 1);
printf("The number you entered is: %d\n", num);
return 0;
}
That is not a bad approach for someone new to C. One small improvement would be to actually check the return value of scanf(), since it returns the number of arguments successfully retrieved. Then you could get away from relying on num being 0 to indicate the input was valid. Unless you do want to specifically flag 0 as invalid input.
int ret = scanf("%d", &num);
ret == 1 would mean an integer was succesffully read into num, ret == 0 would mean it was not.
Consider using strtol to parse a string for a long int. This also allows you to detect trailing characters. In this example if the trailing character is not a newline, the input can be rejected. strtol can also detect overflow values. Read the documentation to see how that works.
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
//Setting up variables
long int num = 0;
char line[40] = ""; /* this is for input */
char *parsed = NULL;
printf("Please enter any number? \t");
fflush ( stdout);
while ( fgets(line, 40, stdin))
{
parsed = line;//set parsed to point to start of line
num = strtol ( line, &parsed, 10);
if ( parsed == line) {//if parsed equals start of line there was no integer
printf("Please enter a number? \t");
printf("\nTry again:\t");
fflush ( stdout);
continue;
}
if ( '\n' != *parsed) {//if the last character is not a newline reject the input
printf("Please enter only a number? \t");
printf("\nTry again:\t");
fflush ( stdout);
}
else {
break;
}
}
if ( !parsed || '\n' != *parsed) {
fprintf ( stderr, "problem fgets\n");
return 0;
}
printf("\n%ld is nice number, thank you! \n\n", num);
return 0;
}
0 (zero) is a number...
But I see what you want to do...
You can check for a valid number, using isdigit or a combination of similar functions
I think its also important to follow the advice of other answers to use the return value from scanf using code such as:
int ret = scanf("%d", &num);
and examining ret for success or failure of scanf.

C programming - Scanf/gets unexpected behaviour

The program is supposed to do the following:
Add Major details
Add University details
Add major to university
Update major cost
Search for a major
Before completing the main function I'm facing a problem:
When I use scanf instead of gets in the functions, It asks 2 questions without letting me to fill the previous one. ex: Enter university's name: Enter university's address:
And when I used gets I faced the same problem.
If there's any other mistake please hint me
Thanks in advance!
#include <stdio.h>
#include <string.h>
//Define Structures
typedef struct {
char name[30];
char department[30];
int nb_students;
int credits;
float cost;
char adv_name[15];
}Major;
typedef struct {
char name[50];
char address[30];
Major uni_majors[50];
int nb_majors;
}University;
// Define Functions Prototypes
Major majors_function();
University university_function();
void AddMajor(Major *major,University *university);
University UpdateMajor(char nameMajor[], University U, float newCost);
void SearchMajor(Major major,University university);
int main(int argc, const char * argv[])
{
Major new_major;
University new_university;
new_major = majors_function();
new_university = university_function();
return 0;
}
// Fills The Major Details Function
Major majors_function() {
Major major;
printf("Enter Major name: ");
gets(major.name);
printf("Enter Department name: ");
gets(major.department);
printf("Enter number of students: ");
scanf("%d",&major.nb_students);
printf("Enter number of credits: ");
scanf("%d",&major.credits);
printf("Enter the cost of credit: ");
scanf("%f",&major.cost);
printf("Enter the Advisor's Last Name: ");
scanf("%s",major.adv_name);
return major;
}
// Fills the university details Function
University university_function() {
University university;
printf("Enter university's name: ");
gets(university.name);
printf("Enter university's address: ");
gets(university.address);
printf("Enter number of majors in this univeristy: ");
scanf("%d",&university.nb_majors);
return university;
}
// Adds Major to a university
void AddMajor(Major *major,University *university) {
university->nb_majors = 0;
if(university->nb_majors <50) {
university->uni_majors[university->nb_majors] = *major;
}
else
printf("No Available space");
university->nb_majors++;
}
// Update Major's Cost
University UpdateMajor(char nameMajor[], University U, float newCost) {
if(strcmp(nameMajor,U.uni_majors->name)) {
U.uni_majors->cost = newCost;
}
return U;
}
// Searches for a major in a university
void SearchMajor(Major major,University university) {
if(strcmp(university.uni_majors->name,major.name))
printf("The total cost of this major is %.2f",(major.cost*major.credits));
else
printf("There is no such major!");
}
When using scanf to scan strings or characters. you might want to skip leading whitespace (like newlines). This can simply be done by asking scanf to skip whitespace, by adding a single space in front of the format code, like
scanf(" %s",major.adv_name);
/* ^ */
/* | */
/* Note space */
You might want to read more about scanf and its siblings on e.g. this reference page.
NEVER NEVER NEVER NEVER NEVER NEVER NEVER NEVERN NEVER NEVER use gets, not for homework assignments, even for toy code. It was deprecated in the 1999 standard and has been removed from the 2011 standard. It will introduce a major point of failure in your program. Use fgets instead:
fgets( major.name, sizeof major.name, stdin );
and check the return value to make sure it succeeded.
Alternately, you can use scanf, but you'll want to specify the max buffer size in the conversion specifier:
scanf( "%29s", major.name ); // leave 1 space for the 0 terminator
The only problem with this is that the size has to be hardcoded; you can't pass it as an argument like you do with printf. Alternately, you can build the format string at runtime, like:
char fmt[5]; // good for %0s to %99s
sprintf( fmt, "%%%zus", sizeof major.name );
...
scanf( fmt, major.name );
Frankly, you're better off using fgets for everything, including the numeric inputs.
char inbuf[10];
char *chk;
// Read the number of students as text, then convert with the
// strtol library function; allows us to catch and reject
// non-numeric input.
printf( "Enter number of students: " );
fflush( stdout );
if ( fgets( inbuf, sizeof inbuf, stdin ) != EOF )
{
int tmp = (int) strtol( inbuf, &chk, 10 );
if ( isspace( *chk ) || *chk == 0 )
{
major.nb_students = tmp;
}
else
{
fprintf( stderr, "%s is not a valid number\n", inbuf );
}
}

C Language. Accept Alphabets only and seperate two questions?

I want the program to answer the first and last name separately while also accepting the input strictly to alphabets. Where do I find more info about that?? Thanks.
#include <stdio.h>
int main(void)
{
char MyFname[20];
char MyLname[20];
printf("Enter your first and last names: \n");
scanf(" %s %s", MyFname, MyLname);
printf("Goodbye %s %s, have a great day!", MyFname, MyLname);
return 0;
}
Edited to incorporate #chux's suggestions.
You can use character-classes in the conversion specification string.
#include <stdio.h>
int main() {
char alphabetic_string[80], numeric_string[80];
scanf(" %79[a-zA-Z] %79[0-9]", alphabetic_string, numeric_string);
return 0;
}
To ask two separate questions, uh, ask two separate questions!
#include <stdio.h>
int main() {
char ans1[80], ans2[80];
printf("Input answer to question 1: ");
fflush(NULL);
scanf(" %79[a-zA-Z]", ans1);
printf("Input answer to question 2: ");
fflush(NULL);
scanf(" %79[a-zA-Z]", ans2);
return 0;
}
#include<stdio.h>
#include<stdlib.h>
int main()
{
char buff[1024];
char MyFname[20];
char MyLname[20];
if ( fgets ( buff, sizeof buff, stdin ) != NULL )
{
if ( sscanf ( buff, "%[a-zA-Z] %[a-zA-Z]", MyFname, MyLname ) != 2 )
{
fprintf ( stderr, "Invalid input\n" );
exit ( EXIT_FAILURE );
}
}
printf ( "Goodbye %s have a great day!\nGoodbye %s have a great day!", MyFname,
MyLname );
return 0;
}
Enter your first and last names:
John smith
Goodbye John have a great day!
Goodbye smith have a great day!
It is best to use fgets to take input and then verifying with sscanf. sscanf will successfully return the total number of inputs read if format entered is correct.
Don't forget to leave space when entering first and last name i.e John smith

Resources